blob: 6e38962d2a5d91a63cab4f700c09bb13c80a9eb5 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020047#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020048#include <proto/lb_fwlc.h>
49#include <proto/lb_fwrr.h>
50#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010052#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020053#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010054#include <proto/protocols.h>
55#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020056#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010057#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010058#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020059#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010061#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010063#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064
65
Willy Tarreauf3c69202006-07-09 16:42:34 +020066/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
67 * ssl-hello-chk option to ensure that the remote server speaks SSL.
68 *
69 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
70 */
71const char sslv3_client_hello_pkt[] = {
72 "\x16" /* ContentType : 0x16 = Hanshake */
73 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
74 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
75 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
76 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
77 "\x03\x00" /* Hello Version : 0x0300 = v3 */
78 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
79 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
80 "\x00" /* Session ID length : empty (no session ID) */
81 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
82 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
83 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
84 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
85 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
86 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
87 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
88 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
89 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
90 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
91 "\x00\x38" "\x00\x39" "\x00\x3A"
92 "\x01" /* Compression Length : 0x01 = 1 byte for types */
93 "\x00" /* Compression Type : 0x00 = NULL compression */
94};
95
Willy Tarreau3842f002009-06-14 11:39:52 +020096/* various keyword modifiers */
97enum kw_mod {
98 KWM_STD = 0, /* normal */
99 KWM_NO, /* "no" prefixed before the keyword */
100 KWM_DEF, /* "default" prefixed before the keyword */
101};
102
Willy Tarreau13943ab2006-12-31 00:24:10 +0100103/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100104struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100105 const char *name;
106 unsigned int val;
107 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100108 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100109 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100110};
111
112/* proxy->options */
113static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100115 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
116 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
117 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
118 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
119 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
120 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
121 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
122 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
125 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
127 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
128 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
129 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
130 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100131#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100132 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100133#else
134 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100135#endif
136
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100137 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138};
139
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140/* proxy->options2 */
141static const struct cfg_opt cfg_opts2[] =
142{
143#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
145 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100147#else
148 { "splice-request", 0, 0, 0, 0 },
149 { "splice-response", 0, 0, 0, 0 },
150 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
153 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
154 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
155 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
156 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
157 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
158 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
160 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
161 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200162 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200163 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100164 { NULL, 0, 0, 0 }
165};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166
Willy Tarreau6daf3432008-01-22 16:44:08 +0100167static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
169int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100170int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200172/* List head of all known configuration keywords */
173static struct cfg_kw_list cfg_keywords = {
174 .list = LIST_HEAD_INIT(cfg_keywords.list)
175};
176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177/*
178 * converts <str> to a list of listeners which are dynamically allocated.
179 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
180 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
181 * - <port> is a numerical port from 1 to 65535 ;
182 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
183 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200184 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100186static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187{
188 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100189 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200190 int port, end;
191
192 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 while (next && *next) {
195 struct sockaddr_storage ss;
196
197 str = next;
198 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100199 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 *next++ = 0;
201 }
202
Emeric Bruned760922010-10-22 17:59:25 +0200203 if (*str == '/') {
204 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
205 /* so compute max path */
206 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
207 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
Emeric Bruned760922010-10-22 17:59:25 +0200209 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100210 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
211 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200212 goto fail;
213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200216 ss.ss_family = AF_UNIX;
217 if (global.unix_bind.prefix) {
218 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
219 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 }
Emeric Bruned760922010-10-22 17:59:25 +0200221 else {
222 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
223 }
224 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 }
226 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100227 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100229 ss2 = str2sa_range(str, &port, &end);
230 if (!ss2) {
231 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
232 file, line, str);
233 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 if (!port) {
237 Alert("parsing [%s:%d] : missing port number: '%s'\n",
238 file, line, str);
239 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 /* OK the address looks correct */
243 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Emeric Bruned760922010-10-22 17:59:25 +0200245 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100246 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
247 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200248 goto fail;
249 }
250
251 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100252 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
253 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200254 goto fail;
255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256 }
257
258 for (; port <= end; port++) {
259 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200260 l->next = curproxy->listen;
261 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
263 l->fd = -1;
264 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100265 l->state = LI_INIT;
266
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100267 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100269 tcpv4_add_listener(l);
270 }
Emeric Bruned760922010-10-22 17:59:25 +0200271 else if (ss.ss_family == AF_INET6) {
272 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
273 tcpv6_add_listener(l);
274 }
275 else {
276 l->perm.ux.gid = l->perm.ux.uid = -1;
277 l->perm.ux.mode = 0;
278 uxst_add_listener(l);
279 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200280
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200281 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100282 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283 } /* end for(port) */
284 } /* end while(next) */
285 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200286 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200287 fail:
288 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200289 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290}
291
Willy Tarreau977b8e42006-12-29 14:19:17 +0100292/*
293 * Sends a warning if proxy <proxy> does not have at least one of the
294 * capabilities in <cap>. An optionnal <hint> may be added at the end
295 * of the warning to help the user. Returns 1 if a warning was emitted
296 * or 0 if the condition is valid.
297 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100298int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299{
300 char *msg;
301
302 switch (cap) {
303 case PR_CAP_BE: msg = "no backend"; break;
304 case PR_CAP_FE: msg = "no frontend"; break;
305 case PR_CAP_RS: msg = "no ruleset"; break;
306 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
307 default: msg = "not enough"; break;
308 }
309
310 if (!(proxy->cap & cap)) {
311 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100312 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100313 return 1;
314 }
315 return 0;
316}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317
Willy Tarreau61d18892009-03-31 10:49:21 +0200318/* Report a warning if a rule is placed after a 'block' rule.
319 * Return 1 if the warning has been emitted, otherwise 0.
320 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100321int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200322{
323 if (!LIST_ISEMPTY(&proxy->block_cond)) {
324 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
325 file, line, arg);
326 return 1;
327 }
328 return 0;
329}
330
331/* Report a warning if a rule is placed after a reqrewrite rule.
332 * Return 1 if the warning has been emitted, otherwise 0.
333 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100334int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200335{
336 if (proxy->req_exp) {
337 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
338 file, line, arg);
339 return 1;
340 }
341 return 0;
342}
343
344/* Report a warning if a rule is placed after a reqadd rule.
345 * Return 1 if the warning has been emitted, otherwise 0.
346 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100347int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200348{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100349 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200350 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
351 file, line, arg);
352 return 1;
353 }
354 return 0;
355}
356
357/* Report a warning if a rule is placed after a redirect rule.
358 * Return 1 if the warning has been emitted, otherwise 0.
359 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100360int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200361{
362 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
363 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
364 file, line, arg);
365 return 1;
366 }
367 return 0;
368}
369
370/* Report a warning if a rule is placed after a 'use_backend' rule.
371 * Return 1 if the warning has been emitted, otherwise 0.
372 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100373int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200374{
375 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
376 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
377 file, line, arg);
378 return 1;
379 }
380 return 0;
381}
382
383/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
387 warnif_rule_after_reqadd(proxy, file, line, arg) ||
388 warnif_rule_after_redirect(proxy, file, line, arg) ||
389 warnif_rule_after_use_backend(proxy, file, line, arg);
390}
391
392/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
395 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
396 warnif_rule_after_redirect(proxy, file, line, arg) ||
397 warnif_rule_after_use_backend(proxy, file, line, arg);
398}
399
400/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 return warnif_rule_after_redirect(proxy, file, line, arg) ||
404 warnif_rule_after_use_backend(proxy, file, line, arg);
405}
406
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100407/* Report it if a request ACL condition uses some response-only parameters. It
408 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
409 * Note that <cond> may be NULL and then will be ignored.
410 */
411static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
412{
413 struct acl *acl;
414
415 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
416 return 0;
417
418 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
419 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
420 file, line, acl ? acl->name : "(unknown)");
421 return ERR_WARN;
422}
423
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100424/* Report it if a request ACL condition uses some request-only volatile parameters.
425 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
426 * Note that <cond> may be NULL and then will be ignored.
427 */
428static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
429{
430 struct acl *acl;
431
432 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
433 return 0;
434
435 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
436 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
437 file, line, acl ? acl->name : "(unknown)");
438 return ERR_WARN;
439}
440
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100441
Willy Tarreaubaaee002006-06-26 02:48:02 +0200442/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 * parse a line in a <global> section. Returns the error code, 0 if OK, or
444 * any combination of :
445 * - ERR_ABORT: must abort ASAP
446 * - ERR_FATAL: we can continue parsing but not start the service
447 * - ERR_WARN: a warning has been emitted
448 * - ERR_ALERT: an alert has been emitted
449 * Only the two first ones can stop processing, the two others are just
450 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200451 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200452int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453{
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455
456 if (!strcmp(args[0], "global")) { /* new section */
457 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200459 }
460 else if (!strcmp(args[0], "daemon")) {
461 global.mode |= MODE_DAEMON;
462 }
463 else if (!strcmp(args[0], "debug")) {
464 global.mode |= MODE_DEBUG;
465 }
466 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100467 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200469 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100470 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200471 }
472 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100473 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100476 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200477 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100478 else if (!strcmp(args[0], "nosplice")) {
479 global.tune.options &= ~GTUNE_USE_SPLICE;
480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481 else if (!strcmp(args[0], "quiet")) {
482 global.mode |= MODE_QUIET;
483 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200484 else if (!strcmp(args[0], "tune.maxpollevents")) {
485 if (global.tune.maxpollevents != 0) {
486 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200487 err_code |= ERR_ALERT;
488 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200489 }
490 if (*(args[1]) == 0) {
491 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200492 err_code |= ERR_ALERT | ERR_FATAL;
493 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200494 }
495 global.tune.maxpollevents = atol(args[1]);
496 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100497 else if (!strcmp(args[0], "tune.maxaccept")) {
498 if (global.tune.maxaccept != 0) {
499 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200500 err_code |= ERR_ALERT;
501 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100502 }
503 if (*(args[1]) == 0) {
504 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100507 }
508 global.tune.maxaccept = atol(args[1]);
509 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200510 else if (!strcmp(args[0], "tune.chksize")) {
511 if (*(args[1]) == 0) {
512 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
513 err_code |= ERR_ALERT | ERR_FATAL;
514 goto out;
515 }
516 global.tune.chksize = atol(args[1]);
517 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200518 else if (!strcmp(args[0], "tune.bufsize")) {
519 if (*(args[1]) == 0) {
520 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT | ERR_FATAL;
522 goto out;
523 }
524 global.tune.bufsize = atol(args[1]);
525 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
526 global.tune.maxrewrite = global.tune.bufsize / 2;
527 }
528 else if (!strcmp(args[0], "tune.maxrewrite")) {
529 if (*(args[1]) == 0) {
530 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
531 err_code |= ERR_ALERT | ERR_FATAL;
532 goto out;
533 }
534 global.tune.maxrewrite = atol(args[1]);
535 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
536 global.tune.maxrewrite = global.tune.bufsize / 2;
537 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100538 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
539 if (global.tune.client_rcvbuf != 0) {
540 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
541 err_code |= ERR_ALERT;
542 goto out;
543 }
544 if (*(args[1]) == 0) {
545 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
546 err_code |= ERR_ALERT | ERR_FATAL;
547 goto out;
548 }
549 global.tune.client_rcvbuf = atol(args[1]);
550 }
551 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
552 if (global.tune.server_rcvbuf != 0) {
553 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT;
555 goto out;
556 }
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.server_rcvbuf = atol(args[1]);
563 }
564 else if (!strcmp(args[0], "tune.sndbuf.client")) {
565 if (global.tune.client_sndbuf != 0) {
566 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
567 err_code |= ERR_ALERT;
568 goto out;
569 }
570 if (*(args[1]) == 0) {
571 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
572 err_code |= ERR_ALERT | ERR_FATAL;
573 goto out;
574 }
575 global.tune.client_sndbuf = atol(args[1]);
576 }
577 else if (!strcmp(args[0], "tune.sndbuf.server")) {
578 if (global.tune.server_sndbuf != 0) {
579 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT;
581 goto out;
582 }
583 if (*(args[1]) == 0) {
584 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
585 err_code |= ERR_ALERT | ERR_FATAL;
586 goto out;
587 }
588 global.tune.server_sndbuf = atol(args[1]);
589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 else if (!strcmp(args[0], "uid")) {
591 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200592 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200593 err_code |= ERR_ALERT;
594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
596 if (*(args[1]) == 0) {
597 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200598 err_code |= ERR_ALERT | ERR_FATAL;
599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 }
601 global.uid = atol(args[1]);
602 }
603 else if (!strcmp(args[0], "gid")) {
604 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200605 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200606 err_code |= ERR_ALERT;
607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 }
609 if (*(args[1]) == 0) {
610 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200611 err_code |= ERR_ALERT | ERR_FATAL;
612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 }
614 global.gid = atol(args[1]);
615 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200616 /* user/group name handling */
617 else if (!strcmp(args[0], "user")) {
618 struct passwd *ha_user;
619 if (global.uid != 0) {
620 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
622 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200623 }
624 errno = 0;
625 ha_user = getpwnam(args[1]);
626 if (ha_user != NULL) {
627 global.uid = (int)ha_user->pw_uid;
628 }
629 else {
630 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200631 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200632 }
633 }
634 else if (!strcmp(args[0], "group")) {
635 struct group *ha_group;
636 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200637 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200638 err_code |= ERR_ALERT;
639 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200640 }
641 errno = 0;
642 ha_group = getgrnam(args[1]);
643 if (ha_group != NULL) {
644 global.gid = (int)ha_group->gr_gid;
645 }
646 else {
647 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200648 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200649 }
650 }
651 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 else if (!strcmp(args[0], "nbproc")) {
653 if (global.nbproc != 0) {
654 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200655 err_code |= ERR_ALERT;
656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 }
658 if (*(args[1]) == 0) {
659 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT | ERR_FATAL;
661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 }
663 global.nbproc = atol(args[1]);
664 }
665 else if (!strcmp(args[0], "maxconn")) {
666 if (global.maxconn != 0) {
667 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200668 err_code |= ERR_ALERT;
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 }
671 if (*(args[1]) == 0) {
672 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT | ERR_FATAL;
674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 }
676 global.maxconn = atol(args[1]);
677#ifdef SYSTEM_MAXCONN
678 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
679 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
680 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200681 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
683#endif /* SYSTEM_MAXCONN */
684 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100685 else if (!strcmp(args[0], "maxpipes")) {
686 if (global.maxpipes != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT;
689 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100695 }
696 global.maxpipes = atol(args[1]);
697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 else if (!strcmp(args[0], "ulimit-n")) {
699 if (global.rlimit_nofile != 0) {
700 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT;
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 }
704 if (*(args[1]) == 0) {
705 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200708 }
709 global.rlimit_nofile = atol(args[1]);
710 }
711 else if (!strcmp(args[0], "chroot")) {
712 if (global.chroot != NULL) {
713 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200714 err_code |= ERR_ALERT;
715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716 }
717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722 global.chroot = strdup(args[1]);
723 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200724 else if (!strcmp(args[0], "description")) {
725 int i, len=0;
726 char *d;
727
728 if (!*args[1]) {
729 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
730 file, linenum, args[0]);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734
735 for(i=1; *args[i]; i++)
736 len += strlen(args[i])+1;
737
738 if (global.desc)
739 free(global.desc);
740
741 global.desc = d = (char *)calloc(1, len);
742
743 d += sprintf(d, "%s", args[1]);
744 for(i=2; *args[i]; i++)
745 d += sprintf(d, " %s", args[i]);
746 }
747 else if (!strcmp(args[0], "node")) {
748 int i;
749 char c;
750
751 for (i=0; args[1][i]; i++) {
752 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100753 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
754 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200755 break;
756 }
757
758 if (!i || args[1][i]) {
759 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
760 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
761 file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765
766 if (global.node)
767 free(global.node);
768
769 global.node = strdup(args[1]);
770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 else if (!strcmp(args[0], "pidfile")) {
772 if (global.pidfile != NULL) {
773 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT;
775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 }
782 global.pidfile = strdup(args[1]);
783 }
Emeric Bruned760922010-10-22 17:59:25 +0200784 else if (!strcmp(args[0], "unix-bind")) {
785 int cur_arg = 1;
786 while (*(args[cur_arg])) {
787 if (!strcmp(args[cur_arg], "prefix")) {
788 if (global.unix_bind.prefix != NULL) {
789 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
790 err_code |= ERR_ALERT;
791 cur_arg += 2;
792 continue;
793 }
794
795 if (*(args[cur_arg+1]) == 0) {
796 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800 global.unix_bind.prefix = strdup(args[cur_arg+1]);
801 cur_arg += 2;
802 continue;
803 }
804
805 if (!strcmp(args[cur_arg], "mode")) {
806
807 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
808 cur_arg += 2;
809 continue;
810 }
811
812 if (!strcmp(args[cur_arg], "uid")) {
813
814 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
815 cur_arg += 2;
816 continue;
817 }
818
819 if (!strcmp(args[cur_arg], "gid")) {
820
821 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
822 cur_arg += 2;
823 continue;
824 }
825
826 if (!strcmp(args[cur_arg], "user")) {
827 struct passwd *user;
828
829 user = getpwnam(args[cur_arg + 1]);
830 if (!user) {
831 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
832 file, linenum, args[0], args[cur_arg + 1 ]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
836
837 global.unix_bind.ux.uid = user->pw_uid;
838 cur_arg += 2;
839 continue;
840 }
841
842 if (!strcmp(args[cur_arg], "group")) {
843 struct group *group;
844
845 group = getgrnam(args[cur_arg + 1]);
846 if (!group) {
847 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
848 file, linenum, args[0], args[cur_arg + 1 ]);
849 err_code |= ERR_ALERT | ERR_FATAL;
850 goto out;
851 }
852
853 global.unix_bind.ux.gid = group->gr_gid;
854 cur_arg += 2;
855 continue;
856 }
857
858 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
859 file, linenum, args[0]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
862 }
863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200864 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100865 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200866 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867
868 if (*(args[1]) == 0 || *(args[2]) == 0) {
869 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872 }
873
874 facility = get_log_facility(args[2]);
875 if (facility < 0) {
876 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200877 err_code |= ERR_ALERT | ERR_FATAL;
878 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879 }
880
881 level = 7; /* max syslog level = debug */
882 if (*(args[3])) {
883 level = get_log_level(args[3]);
884 if (level < 0) {
885 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200886 err_code |= ERR_ALERT | ERR_FATAL;
887 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888 }
889 }
890
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200891 minlvl = 0; /* limit syslog level to this level (emerg) */
892 if (*(args[4])) {
893 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200894 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200895 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200896 err_code |= ERR_ALERT | ERR_FATAL;
897 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200898 }
899 }
900
Robert Tsai81ae1952007-12-05 10:47:29 +0100901 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100902 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100903 if (!sk) {
904 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100905 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100909 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100910 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100911 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100912 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100913 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100917 logsrv.addr = *sk;
918 if (!get_host_port(&logsrv.addr))
919 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921
922 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100923 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 global.logfac1 = facility;
925 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200926 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100929 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 global.logfac2 = facility;
931 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200932 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 }
934 else {
935 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200936 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200938 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100939 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
940 char *name;
941 int len;
942
943 if (global.log_send_hostname != NULL) {
944 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
945 err_code |= ERR_ALERT;
946 goto out;
947 }
948
949 if (*(args[1]))
950 name = args[1];
951 else
952 name = hostname;
953
954 len = strlen(name);
955
956 /* We'll add a space after the name to respect the log format */
957 free(global.log_send_hostname);
958 global.log_send_hostname = malloc(len + 2);
959 snprintf(global.log_send_hostname, len + 2, "%s ", name);
960 }
Kevinm48936af2010-12-22 16:08:21 +0000961 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
962 if (*(args[1]) == 0) {
963 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
966 }
967 free(global.log_tag);
968 global.log_tag = strdup(args[1]);
969 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200970 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
971 if (global.spread_checks != 0) {
972 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200973 err_code |= ERR_ALERT;
974 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200975 }
976 if (*(args[1]) == 0) {
977 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200980 }
981 global.spread_checks = atol(args[1]);
982 if (global.spread_checks < 0 || global.spread_checks > 50) {
983 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200984 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 }
987 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200988 struct cfg_kw_list *kwl;
989 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200990 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200991
992 list_for_each_entry(kwl, &cfg_keywords.list, list) {
993 for (index = 0; kwl->kw[index].kw != NULL; index++) {
994 if (kwl->kw[index].section != CFG_GLOBAL)
995 continue;
996 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
997 /* prepare error message just in case */
998 snprintf(trash, sizeof(trash),
999 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001000 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1001 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001002 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001003 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001004 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001005 else if (rc > 0) {
1006 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001007 err_code |= ERR_WARN;
1008 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001009 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001010 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001011 }
1012 }
1013 }
1014
Willy Tarreaubaaee002006-06-26 02:48:02 +02001015 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001016 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001018
Willy Tarreau058e9072009-07-20 09:30:05 +02001019 out:
1020 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021}
1022
Willy Tarreau97cb7802010-01-03 20:23:58 +01001023/* Perform the most basic initialization of a proxy :
1024 * memset(), list_init(*), reset_timeouts(*).
1025 */
1026static void init_new_proxy(struct proxy *p)
1027{
1028 memset(p, 0, sizeof(struct proxy));
1029 LIST_INIT(&p->pendconns);
1030 LIST_INIT(&p->acl);
Willy Tarreauff011f22011-01-06 17:51:27 +01001031 LIST_INIT(&p->http_req_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001032 LIST_INIT(&p->block_cond);
1033 LIST_INIT(&p->redirect_rules);
1034 LIST_INIT(&p->mon_fail_cond);
1035 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001036 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +01001037 LIST_INIT(&p->sticking_rules);
1038 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001039 LIST_INIT(&p->tcp_req.inspect_rules);
Emeric Brun97679e72010-09-23 17:56:44 +02001040 LIST_INIT(&p->tcp_rep.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +02001041 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01001042 LIST_INIT(&p->req_add);
1043 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001044
1045 /* Timeouts are defined as -1 */
1046 proxy_reset_timeouts(p);
Emeric Brun97679e72010-09-23 17:56:44 +02001047 p->tcp_rep.inspect_delay = TICK_ETERNITY;
Willy Tarreau97cb7802010-01-03 20:23:58 +01001048}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001050void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001052 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 defproxy.mode = PR_MODE_TCP;
1054 defproxy.state = PR_STNEW;
1055 defproxy.maxconn = cfg_maxpconn;
1056 defproxy.conn_retries = CONN_RETRIES;
1057 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001058
1059 defproxy.defsrv.inter = DEF_CHKINTR;
1060 defproxy.defsrv.fastinter = 0;
1061 defproxy.defsrv.downinter = 0;
1062 defproxy.defsrv.rise = DEF_RISETIME;
1063 defproxy.defsrv.fall = DEF_FALLTIME;
1064 defproxy.defsrv.check_port = 0;
1065 defproxy.defsrv.maxqueue = 0;
1066 defproxy.defsrv.minconn = 0;
1067 defproxy.defsrv.maxconn = 0;
1068 defproxy.defsrv.slowstart = 0;
1069 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1070 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1071 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072}
1073
Willy Tarreauade5ec42010-01-28 19:33:49 +01001074
1075static int create_cond_regex_rule(const char *file, int line,
1076 struct proxy *px, int dir, int action, int flags,
1077 const char *cmd, const char *reg, const char *repl,
1078 const char **cond_start)
1079{
1080 regex_t *preg = NULL;
1081 const char *err;
1082 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001083 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001084
1085 if (px == &defproxy) {
1086 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1087 err_code |= ERR_ALERT | ERR_FATAL;
1088 goto err;
1089 }
1090
1091 if (*reg == 0) {
1092 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto err;
1095 }
1096
1097 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1098 err_code |= ERR_WARN;
1099
Willy Tarreau5321c422010-01-28 20:35:13 +01001100 if (cond_start &&
1101 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1102 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1103 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1104 file, line, cmd);
1105 err_code |= ERR_ALERT | ERR_FATAL;
1106 goto err;
1107 }
1108 }
1109 else if (cond_start && **cond_start) {
1110 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1111 file, line, cmd, *cond_start);
1112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto err;
1114 }
1115
1116 if (dir == ACL_DIR_REQ)
1117 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001118 else
1119 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001120
Willy Tarreauade5ec42010-01-28 19:33:49 +01001121 preg = calloc(1, sizeof(regex_t));
1122 if (!preg) {
1123 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1124 err_code = ERR_ALERT | ERR_FATAL;
1125 goto err;
1126 }
1127
1128 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1129 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1130 err_code = ERR_ALERT | ERR_FATAL;
1131 goto err;
1132 }
1133
1134 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001135 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001136 if (repl && err) {
1137 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1138 file, line, cmd, *err);
1139 err_code |= ERR_ALERT | ERR_FATAL;
1140 goto err;
1141 }
1142
1143 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1144 err_code |= ERR_WARN;
1145
1146 return err_code;
1147 err:
1148 free(preg);
1149 return err_code;
1150}
1151
Willy Tarreaubaaee002006-06-26 02:48:02 +02001152/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001153 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001154 * Returns the error code, 0 if OK, or any combination of :
1155 * - ERR_ABORT: must abort ASAP
1156 * - ERR_FATAL: we can continue parsing but not start the service
1157 * - ERR_WARN: a warning has been emitted
1158 * - ERR_ALERT: an alert has been emitted
1159 * Only the two first ones can stop processing, the two others are just
1160 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001161 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001162int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1163{
1164 static struct peers *curpeers = NULL;
1165 struct peer *newpeer = NULL;
1166 const char *err;
1167 int err_code = 0;
1168
1169 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1170
1171 err = invalid_char(args[1]);
1172 if (err) {
1173 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1174 file, linenum, *err, args[0], args[1]);
1175 err_code |= ERR_ALERT | ERR_FATAL;
1176 }
1177
1178 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1179 /*
1180 * If there are two proxies with the same name only following
1181 * combinations are allowed:
1182 */
1183 if (strcmp(curpeers->id, args[1]) == 0) {
1184 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1185 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1186 err_code |= ERR_WARN;
1187 }
1188 }
1189
1190 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1191 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1192 err_code |= ERR_ALERT | ERR_ABORT;
1193 goto out;
1194 }
1195
1196 curpeers->next = peers;
1197 peers = curpeers;
1198 curpeers->conf.file = file;
1199 curpeers->conf.line = linenum;
1200 curpeers->last_change = now.tv_sec;
1201 curpeers->id = strdup(args[1]);
1202 }
1203 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1204 char *rport, *raddr;
1205 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001206 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001207
1208 if (!*args[2]) {
1209 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1210 file, linenum, args[0]);
1211 err_code |= ERR_ALERT | ERR_FATAL;
1212 goto out;
1213 }
1214
1215 err = invalid_char(args[1]);
1216 if (err) {
1217 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1218 file, linenum, *err, args[1]);
1219 err_code |= ERR_ALERT | ERR_FATAL;
1220 goto out;
1221 }
1222
1223 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1224 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1225 err_code |= ERR_ALERT | ERR_ABORT;
1226 goto out;
1227 }
1228
1229 /* the peers are linked backwards first */
1230 curpeers->count++;
1231 newpeer->next = curpeers->remote;
1232 curpeers->remote = newpeer;
1233 newpeer->peers = curpeers;
1234 newpeer->conf.file = file;
1235 newpeer->conf.line = linenum;
1236
1237 newpeer->last_change = now.tv_sec;
1238 newpeer->id = strdup(args[1]);
1239
1240 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001241 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001242 if (rport) {
1243 *rport++ = 0;
1244 realport = atol(rport);
1245 }
1246 if (!realport) {
1247 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1248 err_code |= ERR_ALERT | ERR_FATAL;
1249 goto out;
1250 }
1251
Willy Tarreaufab5a432011-03-04 15:31:53 +01001252 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001253 free(raddr);
1254 if (!sk) {
1255 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1256 err_code |= ERR_ALERT | ERR_FATAL;
1257 goto out;
1258 }
1259 newpeer->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001260
1261 switch (newpeer->addr.ss_family) {
1262 case AF_INET:
1263 ((struct sockaddr_in *)&newpeer->addr)->sin_port = htons(realport);
1264 break;
1265 case AF_INET6:
1266 ((struct sockaddr_in6 *)&newpeer->addr)->sin6_port = htons(realport);
1267 break;
1268 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001269
1270 if (strcmp(newpeer->id, localpeer) == 0) {
1271 /* Current is local peer, it define a frontend */
1272 newpeer->local = 1;
1273
1274 if (!curpeers->peers_fe) {
1275 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1276 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1277 err_code |= ERR_ALERT | ERR_ABORT;
1278 goto out;
1279 }
1280 curpeers->peers_fe->parent = curpeers;
1281
1282 LIST_INIT(&(curpeers->peers_fe)->pendconns);
1283 LIST_INIT(&(curpeers->peers_fe)->acl);
1284 LIST_INIT(&(curpeers->peers_fe)->block_cond);
1285 LIST_INIT(&(curpeers->peers_fe)->redirect_rules);
1286 LIST_INIT(&(curpeers->peers_fe)->mon_fail_cond);
1287 LIST_INIT(&(curpeers->peers_fe)->switching_rules);
1288 LIST_INIT(&(curpeers->peers_fe)->tcp_req.inspect_rules);
1289 LIST_INIT(&(curpeers->peers_fe)->tcp_rep.inspect_rules);
1290
1291 proxy_reset_timeouts(curpeers->peers_fe);
1292
1293 curpeers->peers_fe->last_change = now.tv_sec;
1294 curpeers->peers_fe->id = strdup(args[1]);
1295 curpeers->peers_fe->cap = PR_CAP_FE;
1296 curpeers->peers_fe->maxconn = 65000;
1297 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1298 curpeers->peers_fe->timeout.connect = 5000;
1299 curpeers->peers_fe->accept = peer_accept;
1300 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001301 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001302 err_code |= ERR_FATAL;
1303 goto out;
1304 }
1305 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1306 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1307 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1308 curpeers->peers_fe->listen->accept = session_accept;
1309 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1310 curpeers->peers_fe->listen->handler = process_session;
1311 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1312 }
1313 }
1314 } /* neither "peer" nor "peers" */
1315 else if (*args[0] != 0) {
1316 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1317 err_code |= ERR_ALERT | ERR_FATAL;
1318 goto out;
1319 }
1320
1321out:
1322 return err_code;
1323}
1324
1325
Willy Tarreau3842f002009-06-14 11:39:52 +02001326int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001327{
1328 static struct proxy *curproxy = NULL;
1329 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001330 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001331 int rc;
1332 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001333 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001334 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001335
Willy Tarreau977b8e42006-12-29 14:19:17 +01001336 if (!strcmp(args[0], "listen"))
1337 rc = PR_CAP_LISTEN;
1338 else if (!strcmp(args[0], "frontend"))
1339 rc = PR_CAP_FE | PR_CAP_RS;
1340 else if (!strcmp(args[0], "backend"))
1341 rc = PR_CAP_BE | PR_CAP_RS;
1342 else if (!strcmp(args[0], "ruleset"))
1343 rc = PR_CAP_RS;
1344 else
1345 rc = PR_CAP_NONE;
1346
1347 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001348 if (!*args[1]) {
1349 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1350 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1351 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001352 err_code |= ERR_ALERT | ERR_ABORT;
1353 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001354 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001355
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001356 err = invalid_char(args[1]);
1357 if (err) {
1358 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1359 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001360 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001361 }
1362
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001363 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1364 /*
1365 * If there are two proxies with the same name only following
1366 * combinations are allowed:
1367 *
1368 * listen backend frontend ruleset
1369 * listen - - - -
1370 * backend - - OK -
1371 * frontend - OK - -
1372 * ruleset - - - -
1373 */
1374
1375 if (!strcmp(curproxy->id, args[1]) &&
1376 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1377 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001378 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1379 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1380 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001381 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001382 }
1383 }
1384
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1386 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001387 err_code |= ERR_ALERT | ERR_ABORT;
1388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001390
Willy Tarreau97cb7802010-01-03 20:23:58 +01001391 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 curproxy->next = proxy;
1393 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001394 curproxy->conf.file = file;
1395 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001396 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001397 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001398 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399
1400 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001401 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001402 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001403 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001404 err_code |= ERR_FATAL;
1405 goto out;
1406 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001407 new = curproxy->listen;
1408 while (new != last) {
1409 new->conf.file = file;
1410 new->conf.line = linenum;
1411 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001412 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001413 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 }
1415
1416 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001417 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001418 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001419
Willy Tarreaubaaee002006-06-26 02:48:02 +02001420 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001422 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001423 curproxy->no_options = defproxy.no_options;
1424 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001425 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001426 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001427 curproxy->except_net = defproxy.except_net;
1428 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001429 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001430 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001432 if (defproxy.fwdfor_hdr_len) {
1433 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1434 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1435 }
1436
Willy Tarreaub86db342009-11-30 11:50:16 +01001437 if (defproxy.orgto_hdr_len) {
1438 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1439 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1440 }
1441
Willy Tarreau977b8e42006-12-29 14:19:17 +01001442 if (curproxy->cap & PR_CAP_FE) {
1443 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001444 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001445 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001446
1447 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001448 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1449 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001450
1451 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1452 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453
Willy Tarreau977b8e42006-12-29 14:19:17 +01001454 if (curproxy->cap & PR_CAP_BE) {
1455 curproxy->fullconn = defproxy.fullconn;
1456 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001458 if (defproxy.check_req) {
1459 curproxy->check_req = calloc(1, defproxy.check_len);
1460 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1461 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001462 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463
Willy Tarreau977b8e42006-12-29 14:19:17 +01001464 if (defproxy.cookie_name)
1465 curproxy->cookie_name = strdup(defproxy.cookie_name);
1466 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001467 if (defproxy.cookie_domain)
1468 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001469
Willy Tarreau31936852010-10-06 16:59:56 +02001470 if (defproxy.cookie_maxidle)
1471 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1472
1473 if (defproxy.cookie_maxlife)
1474 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1475
Emeric Brun647caf12009-06-30 17:57:00 +02001476 if (defproxy.rdp_cookie_name)
1477 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1478 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1479
Willy Tarreau01732802007-11-01 22:48:15 +01001480 if (defproxy.url_param_name)
1481 curproxy->url_param_name = strdup(defproxy.url_param_name);
1482 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001483
Benoitaffb4812009-03-25 13:02:10 +01001484 if (defproxy.hh_name)
1485 curproxy->hh_name = strdup(defproxy.hh_name);
1486 curproxy->hh_len = defproxy.hh_len;
1487 curproxy->hh_match_domain = defproxy.hh_match_domain;
1488
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001489 if (defproxy.iface_name)
1490 curproxy->iface_name = strdup(defproxy.iface_name);
1491 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001494 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001495 if (defproxy.capture_name)
1496 curproxy->capture_name = strdup(defproxy.capture_name);
1497 curproxy->capture_namelen = defproxy.capture_namelen;
1498 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001499 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500
Willy Tarreau977b8e42006-12-29 14:19:17 +01001501 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001502 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001503 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001504 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001505 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001506 curproxy->uri_auth = defproxy.uri_auth;
1507 curproxy->mon_net = defproxy.mon_net;
1508 curproxy->mon_mask = defproxy.mon_mask;
1509 if (defproxy.monitor_uri)
1510 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1511 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001512 if (defproxy.defbe.name)
1513 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001514 }
1515
1516 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001517 curproxy->timeout.connect = defproxy.timeout.connect;
1518 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001519 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001520 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001521 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001522 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001523 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001524 curproxy->source_addr = defproxy.source_addr;
1525 }
1526
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527 curproxy->mode = defproxy.mode;
1528 curproxy->logfac1 = defproxy.logfac1;
1529 curproxy->logsrv1 = defproxy.logsrv1;
1530 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001531 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532 curproxy->logfac2 = defproxy.logfac2;
1533 curproxy->logsrv2 = defproxy.logsrv2;
1534 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001535 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001536 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001537 curproxy->conf.used_listener_id = EB_ROOT;
1538 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001539
Willy Tarreau93893792009-07-23 13:19:11 +02001540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001541 }
1542 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1543 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001544 /* FIXME-20070101: we should do this too at the end of the
1545 * config parsing to free all default values.
1546 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001547 free(defproxy.check_req);
1548 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001549 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001550 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001551 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001552 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001553 free(defproxy.capture_name);
1554 free(defproxy.monitor_uri);
1555 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001556 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001557 free(defproxy.fwdfor_hdr_name);
1558 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001559 free(defproxy.orgto_hdr_name);
1560 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001561
Willy Tarreaua534fea2008-08-03 12:19:50 +02001562 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001563 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001564
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565 /* we cannot free uri_auth because it might already be used */
1566 init_default_instance();
1567 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001568 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 }
1571 else if (curproxy == NULL) {
1572 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001573 err_code |= ERR_ALERT | ERR_FATAL;
1574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001575 }
1576
Willy Tarreau977b8e42006-12-29 14:19:17 +01001577
1578 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001580 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001581 int cur_arg;
1582
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 if (curproxy == &defproxy) {
1584 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001585 err_code |= ERR_ALERT | ERR_FATAL;
1586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001588 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001589 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590
Emeric Bruned760922010-10-22 17:59:25 +02001591 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001592 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001593 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001594 err_code |= ERR_ALERT | ERR_FATAL;
1595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001597
1598 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001599
1600 /* NOTE: the following line might create several listeners if there
1601 * are comma-separated IPs or port ranges. So all further processing
1602 * will have to be applied to all listeners created after last_listen.
1603 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001604 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001605 err_code |= ERR_ALERT | ERR_FATAL;
1606 goto out;
1607 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001608
Willy Tarreau90a570f2009-10-04 20:54:54 +02001609 new_listen = curproxy->listen;
1610 while (new_listen != last_listen) {
1611 new_listen->conf.file = file;
1612 new_listen->conf.line = linenum;
1613 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001614 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001615 }
1616
Emeric Bruned760922010-10-22 17:59:25 +02001617 /* Set default global rights and owner for unix bind */
1618 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1619 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1620 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001621 cur_arg = 2;
1622 while (*(args[cur_arg])) {
1623 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1624#ifdef SO_BINDTODEVICE
1625 struct listener *l;
1626
Emeric Bruned760922010-10-22 17:59:25 +02001627 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1628 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1629 file, linenum, args[0], args[cur_arg]);
1630 err_code |= ERR_ALERT | ERR_FATAL;
1631 goto out;
1632 }
1633
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001634 if (!*args[cur_arg + 1]) {
1635 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1636 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001637 err_code |= ERR_ALERT | ERR_FATAL;
1638 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001639 }
1640
1641 for (l = curproxy->listen; l != last_listen; l = l->next)
1642 l->interface = strdup(args[cur_arg + 1]);
1643
1644 global.last_checks |= LSTCHK_NETADM;
1645
1646 cur_arg += 2;
1647 continue;
1648#else
1649 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1650 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001653#endif
1654 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001655 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1656#ifdef TCP_MAXSEG
1657 struct listener *l;
1658 int mss;
1659
Emeric Bruned760922010-10-22 17:59:25 +02001660 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1661 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1662 file, linenum, args[0], args[cur_arg]);
1663 err_code |= ERR_ALERT | ERR_FATAL;
1664 goto out;
1665 }
1666
Willy Tarreaube1b9182009-06-14 18:48:19 +02001667 if (!*args[cur_arg + 1]) {
1668 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1669 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001670 err_code |= ERR_ALERT | ERR_FATAL;
1671 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001672 }
1673
Willy Tarreau48a7e722010-12-24 15:26:39 +01001674 mss = atoi(args[cur_arg + 1]);
1675 if (!mss || abs(mss) > 65535) {
1676 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001677 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001678 err_code |= ERR_ALERT | ERR_FATAL;
1679 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001680 }
1681
1682 for (l = curproxy->listen; l != last_listen; l = l->next)
1683 l->maxseg = mss;
1684
1685 cur_arg += 2;
1686 continue;
1687#else
1688 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1689 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001690 err_code |= ERR_ALERT | ERR_FATAL;
1691 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001692#endif
1693 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001694
1695 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1696#ifdef TCP_DEFER_ACCEPT
1697 struct listener *l;
1698
1699 for (l = curproxy->listen; l != last_listen; l = l->next)
1700 l->options |= LI_O_DEF_ACCEPT;
1701
1702 cur_arg ++;
1703 continue;
1704#else
1705 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1706 file, linenum, args[0], args[cur_arg]);
1707 err_code |= ERR_ALERT | ERR_FATAL;
1708 goto out;
1709#endif
1710 }
1711
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001712 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001713#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001714 struct listener *l;
1715
Emeric Bruned760922010-10-22 17:59:25 +02001716 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1717 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1718 file, linenum, args[0], args[cur_arg]);
1719 err_code |= ERR_ALERT | ERR_FATAL;
1720 goto out;
1721 }
1722
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001723 for (l = curproxy->listen; l != last_listen; l = l->next)
1724 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001725
1726 cur_arg ++;
1727 continue;
1728#else
1729 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1730 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001731 err_code |= ERR_ALERT | ERR_FATAL;
1732 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001733#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001734 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001735
Willy Tarreau8a956912010-10-15 14:27:08 +02001736 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1737 struct listener *l;
1738
1739 for (l = curproxy->listen; l != last_listen; l = l->next)
1740 l->options |= LI_O_ACC_PROXY;
1741
1742 cur_arg ++;
1743 continue;
1744 }
1745
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001746 if (!strcmp(args[cur_arg], "name")) {
1747 struct listener *l;
1748
1749 for (l = curproxy->listen; l != last_listen; l = l->next)
1750 l->name = strdup(args[cur_arg + 1]);
1751
1752 cur_arg += 2;
1753 continue;
1754 }
1755
1756 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001757 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001758 struct listener *l;
1759
1760 if (curproxy->listen->next != last_listen) {
1761 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1762 file, linenum, args[cur_arg]);
1763 err_code |= ERR_ALERT | ERR_FATAL;
1764 goto out;
1765 }
1766
1767 if (!*args[cur_arg + 1]) {
1768 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1769 file, linenum, args[cur_arg]);
1770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
1772 }
1773
1774 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001775 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001776
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001777 if (curproxy->listen->luid <= 0) {
1778 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001779 file, linenum);
1780 err_code |= ERR_ALERT | ERR_FATAL;
1781 goto out;
1782 }
1783
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001784 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1785 if (node) {
1786 l = container_of(node, struct listener, conf.id);
1787 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1788 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1789 err_code |= ERR_ALERT | ERR_FATAL;
1790 goto out;
1791 }
1792 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1793
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001794 cur_arg += 2;
1795 continue;
1796 }
1797
Emeric Bruned760922010-10-22 17:59:25 +02001798 if (!strcmp(args[cur_arg], "mode")) {
1799
1800 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1801 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1802 file, linenum, args[0], args[cur_arg]);
1803 err_code |= ERR_ALERT | ERR_FATAL;
1804 goto out;
1805 }
1806
1807 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1808
1809 cur_arg += 2;
1810 continue;
1811 }
1812
1813 if (!strcmp(args[cur_arg], "uid")) {
1814
1815 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1816 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1817 file, linenum, args[0], args[cur_arg]);
1818 err_code |= ERR_ALERT | ERR_FATAL;
1819 goto out;
1820 }
1821
1822 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1823 cur_arg += 2;
1824 continue;
1825 }
1826
1827 if (!strcmp(args[cur_arg], "gid")) {
1828
1829 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1830 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1831 file, linenum, args[0], args[cur_arg]);
1832 err_code |= ERR_ALERT | ERR_FATAL;
1833 goto out;
1834 }
1835
1836 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1837 cur_arg += 2;
1838 continue;
1839 }
1840
1841 if (!strcmp(args[cur_arg], "user")) {
1842 struct passwd *user;
1843
1844 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1845 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1846 file, linenum, args[0], args[cur_arg]);
1847 err_code |= ERR_ALERT | ERR_FATAL;
1848 goto out;
1849 }
1850 user = getpwnam(args[cur_arg + 1]);
1851 if (!user) {
1852 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1853 file, linenum, args[0], args[cur_arg + 1 ]);
1854 err_code |= ERR_ALERT | ERR_FATAL;
1855 goto out;
1856 }
1857
1858 curproxy->listen->perm.ux.uid = user->pw_uid;
1859 cur_arg += 2;
1860 continue;
1861 }
1862
1863 if (!strcmp(args[cur_arg], "group")) {
1864 struct group *group;
1865
1866 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1867 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1868 file, linenum, args[0], args[cur_arg]);
1869 err_code |= ERR_ALERT | ERR_FATAL;
1870 goto out;
1871 }
1872 group = getgrnam(args[cur_arg + 1]);
1873 if (!group) {
1874 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1875 file, linenum, args[0], args[cur_arg + 1 ]);
1876 err_code |= ERR_ALERT | ERR_FATAL;
1877 goto out;
1878 }
1879
1880 curproxy->listen->perm.ux.gid = group->gr_gid;
1881 cur_arg += 2;
1882 continue;
1883 }
1884
Willy Tarreau8a956912010-10-15 14:27:08 +02001885 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001886 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001889 }
Willy Tarreau93893792009-07-23 13:19:11 +02001890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001891 }
1892 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1893 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1894 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1895 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001896 err_code |= ERR_ALERT | ERR_FATAL;
1897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001898 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001899 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001900 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001901
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 /* flush useless bits */
1903 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001906 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001907 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001908 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001909
Willy Tarreau1c47f852006-07-09 08:22:27 +02001910 if (!*args[1]) {
1911 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1912 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001913 err_code |= ERR_ALERT | ERR_FATAL;
1914 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001915 }
1916
Willy Tarreaua534fea2008-08-03 12:19:50 +02001917 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001918 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001919 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001920 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001921 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1922
Willy Tarreau93893792009-07-23 13:19:11 +02001923 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1926 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1927 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1928 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1929 else {
1930 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 }
1934 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001935 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001936 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001937
1938 if (curproxy == &defproxy) {
1939 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1940 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001941 err_code |= ERR_ALERT | ERR_FATAL;
1942 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001943 }
1944
1945 if (!*args[1]) {
1946 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1947 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001948 err_code |= ERR_ALERT | ERR_FATAL;
1949 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001950 }
1951
1952 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001953 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001954
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001955 if (curproxy->uuid <= 0) {
1956 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001957 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001958 err_code |= ERR_ALERT | ERR_FATAL;
1959 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001960 }
1961
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001962 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1963 if (node) {
1964 struct proxy *target = container_of(node, struct proxy, conf.id);
1965 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1966 file, linenum, proxy_type_str(curproxy), curproxy->id,
1967 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1968 err_code |= ERR_ALERT | ERR_FATAL;
1969 goto out;
1970 }
1971 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001972 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001973 else if (!strcmp(args[0], "description")) {
1974 int i, len=0;
1975 char *d;
1976
Cyril Bonté99ed3272010-01-24 23:29:44 +01001977 if (curproxy == &defproxy) {
1978 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1979 file, linenum, args[0]);
1980 err_code |= ERR_ALERT | ERR_FATAL;
1981 goto out;
1982 }
1983
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001984 if (!*args[1]) {
1985 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1986 file, linenum, args[0]);
1987 return -1;
1988 }
1989
1990 for(i=1; *args[i]; i++)
1991 len += strlen(args[i])+1;
1992
1993 d = (char *)calloc(1, len);
1994 curproxy->desc = d;
1995
1996 d += sprintf(d, "%s", args[1]);
1997 for(i=2; *args[i]; i++)
1998 d += sprintf(d, " %s", args[i]);
1999
2000 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002001 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2002 curproxy->state = PR_STSTOPPED;
2003 }
2004 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2005 curproxy->state = PR_STNEW;
2006 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002007 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2008 int cur_arg = 1;
2009 unsigned int set = 0;
2010
2011 while (*args[cur_arg]) {
2012 int u;
2013 if (strcmp(args[cur_arg], "all") == 0) {
2014 set = 0;
2015 break;
2016 }
2017 else if (strcmp(args[cur_arg], "odd") == 0) {
2018 set |= 0x55555555;
2019 }
2020 else if (strcmp(args[cur_arg], "even") == 0) {
2021 set |= 0xAAAAAAAA;
2022 }
2023 else {
2024 u = str2uic(args[cur_arg]);
2025 if (u < 1 || u > 32) {
2026 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2027 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002028 err_code |= ERR_ALERT | ERR_FATAL;
2029 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002030 }
2031 if (u > global.nbproc) {
2032 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2033 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002035 }
2036 set |= 1 << (u - 1);
2037 }
2038 cur_arg++;
2039 }
2040 curproxy->bind_proc = set;
2041 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002042 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002043 if (curproxy == &defproxy) {
2044 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002045 err_code |= ERR_ALERT | ERR_FATAL;
2046 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002047 }
2048
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002049 err = invalid_char(args[1]);
2050 if (err) {
2051 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2052 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002053 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002054 }
2055
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002056 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2057 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2058 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002061 }
2062 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2064 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002065
Willy Tarreau977b8e42006-12-29 14:19:17 +01002066 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002067 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002068
Willy Tarreaubaaee002006-06-26 02:48:02 +02002069 if (*(args[1]) == 0) {
2070 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2071 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002072 err_code |= ERR_ALERT | ERR_FATAL;
2073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002075
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002076 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002077 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002078 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002079 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002080 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081 curproxy->cookie_name = strdup(args[1]);
2082 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002083
Willy Tarreaubaaee002006-06-26 02:48:02 +02002084 cur_arg = 2;
2085 while (*(args[cur_arg])) {
2086 if (!strcmp(args[cur_arg], "rewrite")) {
2087 curproxy->options |= PR_O_COOK_RW;
2088 }
2089 else if (!strcmp(args[cur_arg], "indirect")) {
2090 curproxy->options |= PR_O_COOK_IND;
2091 }
2092 else if (!strcmp(args[cur_arg], "insert")) {
2093 curproxy->options |= PR_O_COOK_INS;
2094 }
2095 else if (!strcmp(args[cur_arg], "nocache")) {
2096 curproxy->options |= PR_O_COOK_NOC;
2097 }
2098 else if (!strcmp(args[cur_arg], "postonly")) {
2099 curproxy->options |= PR_O_COOK_POST;
2100 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002101 else if (!strcmp(args[cur_arg], "preserve")) {
2102 curproxy->options2 |= PR_O2_COOK_PSV;
2103 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 else if (!strcmp(args[cur_arg], "prefix")) {
2105 curproxy->options |= PR_O_COOK_PFX;
2106 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002107 else if (!strcmp(args[cur_arg], "domain")) {
2108 if (!*args[cur_arg + 1]) {
2109 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2110 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002111 err_code |= ERR_ALERT | ERR_FATAL;
2112 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002113 }
2114
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002115 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002116 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002117 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2118 " dots nor does not start with a dot."
2119 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002120 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002121 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002122 }
2123
2124 err = invalid_domainchar(args[cur_arg + 1]);
2125 if (err) {
2126 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2127 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002128 err_code |= ERR_ALERT | ERR_FATAL;
2129 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002130 }
2131
Willy Tarreau68a897b2009-12-03 23:28:34 +01002132 if (!curproxy->cookie_domain) {
2133 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2134 } else {
2135 /* one domain was already specified, add another one by
2136 * building the string which will be returned along with
2137 * the cookie.
2138 */
2139 char *new_ptr;
2140 int new_len = strlen(curproxy->cookie_domain) +
2141 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2142 new_ptr = malloc(new_len);
2143 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2144 free(curproxy->cookie_domain);
2145 curproxy->cookie_domain = new_ptr;
2146 }
Willy Tarreau31936852010-10-06 16:59:56 +02002147 cur_arg++;
2148 }
2149 else if (!strcmp(args[cur_arg], "maxidle")) {
2150 unsigned int maxidle;
2151 const char *res;
2152
2153 if (!*args[cur_arg + 1]) {
2154 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2155 file, linenum, args[cur_arg]);
2156 err_code |= ERR_ALERT | ERR_FATAL;
2157 goto out;
2158 }
2159
2160 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2161 if (res) {
2162 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2163 file, linenum, *res, args[cur_arg]);
2164 err_code |= ERR_ALERT | ERR_FATAL;
2165 goto out;
2166 }
2167 curproxy->cookie_maxidle = maxidle;
2168 cur_arg++;
2169 }
2170 else if (!strcmp(args[cur_arg], "maxlife")) {
2171 unsigned int maxlife;
2172 const char *res;
2173
2174 if (!*args[cur_arg + 1]) {
2175 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2176 file, linenum, args[cur_arg]);
2177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
2179 }
2180
2181 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2182 if (res) {
2183 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2184 file, linenum, *res, args[cur_arg]);
2185 err_code |= ERR_ALERT | ERR_FATAL;
2186 goto out;
2187 }
2188 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002189 cur_arg++;
2190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002191 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002192 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002194 err_code |= ERR_ALERT | ERR_FATAL;
2195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002196 }
2197 cur_arg++;
2198 }
2199 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2200 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2201 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002202 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 }
2204
2205 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2206 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2207 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002208 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002210
2211 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2212 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2213 file, linenum);
2214 err_code |= ERR_ALERT | ERR_FATAL;
2215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002216 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002217 else if (!strcmp(args[0], "persist")) { /* persist */
2218 if (*(args[1]) == 0) {
2219 Alert("parsing [%s:%d] : missing persist method.\n",
2220 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002221 err_code |= ERR_ALERT | ERR_FATAL;
2222 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002223 }
2224
2225 if (!strncmp(args[1], "rdp-cookie", 10)) {
2226 curproxy->options2 |= PR_O2_RDPC_PRST;
2227
Emeric Brunb982a3d2010-01-04 15:45:53 +01002228 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002229 const char *beg, *end;
2230
2231 beg = args[1] + 11;
2232 end = strchr(beg, ')');
2233
2234 if (!end || end == beg) {
2235 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2236 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002239 }
2240
2241 free(curproxy->rdp_cookie_name);
2242 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2243 curproxy->rdp_cookie_len = end-beg;
2244 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002245 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002246 free(curproxy->rdp_cookie_name);
2247 curproxy->rdp_cookie_name = strdup("msts");
2248 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2249 }
2250 else { /* syntax */
2251 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2252 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002253 err_code |= ERR_ALERT | ERR_FATAL;
2254 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002255 }
2256 }
2257 else {
2258 Alert("parsing [%s:%d] : unknown persist method.\n",
2259 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002262 }
2263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002265 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002267 if (curproxy == &defproxy) {
2268 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
2271 }
2272
Willy Tarreau977b8e42006-12-29 14:19:17 +01002273 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002274 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002275
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002277 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002278 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002281 }
2282 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002283 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284 curproxy->appsession_name = strdup(args[1]);
2285 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2286 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002287 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2288 if (err) {
2289 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2290 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002293 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002294 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002295
Willy Tarreau51041c72007-09-09 21:56:53 +02002296 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2297 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002298 err_code |= ERR_ALERT | ERR_ABORT;
2299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002301
2302 cur_arg = 6;
2303 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002304 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2305 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002306 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002307 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002308 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002309 } else if (!strcmp(args[cur_arg], "prefix")) {
2310 curproxy->options2 |= PR_O2_AS_PFX;
2311 } else if (!strcmp(args[cur_arg], "mode")) {
2312 if (!*args[cur_arg + 1]) {
2313 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2314 file, linenum, args[0], args[cur_arg]);
2315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
2317 }
2318
2319 cur_arg++;
2320 if (!strcmp(args[cur_arg], "query-string")) {
2321 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2322 curproxy->options2 |= PR_O2_AS_M_QS;
2323 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2324 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2325 curproxy->options2 |= PR_O2_AS_M_PP;
2326 } else {
2327 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
2330 }
2331 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002332 cur_arg++;
2333 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 } /* Url App Session */
2335 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002336 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002337 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002338
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002340 if (curproxy == &defproxy) {
2341 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
2344 }
2345
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 if (*(args[4]) == 0) {
2347 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2348 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002349 err_code |= ERR_ALERT | ERR_FATAL;
2350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002352 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 curproxy->capture_name = strdup(args[2]);
2354 curproxy->capture_namelen = strlen(curproxy->capture_name);
2355 curproxy->capture_len = atol(args[4]);
2356 if (curproxy->capture_len >= CAPTURE_LEN) {
2357 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2358 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 curproxy->capture_len = CAPTURE_LEN - 1;
2361 }
2362 curproxy->to_log |= LW_COOKIE;
2363 }
2364 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2365 struct cap_hdr *hdr;
2366
2367 if (curproxy == &defproxy) {
2368 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002369 err_code |= ERR_ALERT | ERR_FATAL;
2370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 }
2372
2373 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2374 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2375 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 }
2379
2380 hdr = calloc(sizeof(struct cap_hdr), 1);
2381 hdr->next = curproxy->req_cap;
2382 hdr->name = strdup(args[3]);
2383 hdr->namelen = strlen(args[3]);
2384 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002385 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 hdr->index = curproxy->nb_req_cap++;
2387 curproxy->req_cap = hdr;
2388 curproxy->to_log |= LW_REQHDR;
2389 }
2390 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2391 struct cap_hdr *hdr;
2392
2393 if (curproxy == &defproxy) {
2394 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002395 err_code |= ERR_ALERT | ERR_FATAL;
2396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 }
2398
2399 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2400 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2401 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002402 err_code |= ERR_ALERT | ERR_FATAL;
2403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 }
2405 hdr = calloc(sizeof(struct cap_hdr), 1);
2406 hdr->next = curproxy->rsp_cap;
2407 hdr->name = strdup(args[3]);
2408 hdr->namelen = strlen(args[3]);
2409 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002410 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 hdr->index = curproxy->nb_rsp_cap++;
2412 curproxy->rsp_cap = hdr;
2413 curproxy->to_log |= LW_RSPHDR;
2414 }
2415 else {
2416 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2417 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 }
2421 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002423 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002425
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 if (*(args[1]) == 0) {
2427 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2428 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 }
2432 curproxy->conn_retries = atol(args[1]);
2433 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002434 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002435 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002436
2437 if (curproxy == &defproxy) {
2438 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
2441 }
2442
Willy Tarreauff011f22011-01-06 17:51:27 +01002443 if (!LIST_ISEMPTY(&curproxy->http_req_rules) && !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002444 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2445 file, linenum, args[0]);
2446 err_code |= ERR_WARN;
2447 }
2448
Willy Tarreauff011f22011-01-06 17:51:27 +01002449 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002450
Willy Tarreauff011f22011-01-06 17:51:27 +01002451 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002452 err_code |= ERR_ALERT | ERR_ABORT;
2453 goto out;
2454 }
2455
Willy Tarreauff011f22011-01-06 17:51:27 +01002456 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2457 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002458 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002459 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002460 if (curproxy == &defproxy) {
2461 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002462 err_code |= ERR_ALERT | ERR_FATAL;
2463 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002464 }
2465
Willy Tarreauef6494c2010-01-28 17:12:36 +01002466 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002467 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2468 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002471 }
2472
Willy Tarreauef6494c2010-01-28 17:12:36 +01002473 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002474 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2475 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002478 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002479
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002480 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002481 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002482 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002483 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002484 struct redirect_rule *rule;
2485 int cur_arg;
2486 int type = REDIRECT_TYPE_NONE;
2487 int code = 302;
2488 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002489 char *cookie = NULL;
2490 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002491 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002492
Cyril Bonté99ed3272010-01-24 23:29:44 +01002493 if (curproxy == &defproxy) {
2494 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2495 err_code |= ERR_ALERT | ERR_FATAL;
2496 goto out;
2497 }
2498
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002499 cur_arg = 1;
2500 while (*(args[cur_arg])) {
2501 if (!strcmp(args[cur_arg], "location")) {
2502 if (!*args[cur_arg + 1]) {
2503 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2504 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002507 }
2508
2509 type = REDIRECT_TYPE_LOCATION;
2510 cur_arg++;
2511 destination = args[cur_arg];
2512 }
2513 else if (!strcmp(args[cur_arg], "prefix")) {
2514 if (!*args[cur_arg + 1]) {
2515 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2516 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002517 err_code |= ERR_ALERT | ERR_FATAL;
2518 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002519 }
2520
2521 type = REDIRECT_TYPE_PREFIX;
2522 cur_arg++;
2523 destination = args[cur_arg];
2524 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002525 else if (!strcmp(args[cur_arg], "set-cookie")) {
2526 if (!*args[cur_arg + 1]) {
2527 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2528 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002531 }
2532
2533 cur_arg++;
2534 cookie = args[cur_arg];
2535 cookie_set = 1;
2536 }
2537 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2538 if (!*args[cur_arg + 1]) {
2539 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2540 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002541 err_code |= ERR_ALERT | ERR_FATAL;
2542 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002543 }
2544
2545 cur_arg++;
2546 cookie = args[cur_arg];
2547 cookie_set = 0;
2548 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002549 else if (!strcmp(args[cur_arg],"code")) {
2550 if (!*args[cur_arg + 1]) {
2551 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2552 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002555 }
2556 cur_arg++;
2557 code = atol(args[cur_arg]);
2558 if (code < 301 || code > 303) {
2559 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2560 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002561 err_code |= ERR_ALERT | ERR_FATAL;
2562 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002563 }
2564 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002565 else if (!strcmp(args[cur_arg],"drop-query")) {
2566 flags |= REDIRECT_FLAG_DROP_QS;
2567 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002568 else if (!strcmp(args[cur_arg],"append-slash")) {
2569 flags |= REDIRECT_FLAG_APPEND_SLASH;
2570 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002571 else if (strcmp(args[cur_arg], "if") == 0 ||
2572 strcmp(args[cur_arg], "unless") == 0) {
2573 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2574 if (!cond) {
2575 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2576 file, linenum, args[0]);
2577 err_code |= ERR_ALERT | ERR_FATAL;
2578 goto out;
2579 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002580 break;
2581 }
2582 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002583 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002584 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002585 err_code |= ERR_ALERT | ERR_FATAL;
2586 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002587 }
2588 cur_arg++;
2589 }
2590
2591 if (type == REDIRECT_TYPE_NONE) {
2592 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2593 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002596 }
2597
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002598 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2599 rule->cond = cond;
2600 rule->rdr_str = strdup(destination);
2601 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002602 if (cookie) {
2603 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002604 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002605 */
2606 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002607 if (cookie_set) {
2608 rule->cookie_str = malloc(rule->cookie_len + 10);
2609 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2610 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2611 rule->cookie_len += 9;
2612 } else {
2613 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002614 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002615 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2616 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002617 }
2618 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002619 rule->type = type;
2620 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002621 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002622 LIST_INIT(&rule->list);
2623 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002624 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2625 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002626 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002627 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002628 struct switching_rule *rule;
2629
Willy Tarreaub099aca2008-10-12 17:26:37 +02002630 if (curproxy == &defproxy) {
2631 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002632 err_code |= ERR_ALERT | ERR_FATAL;
2633 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002634 }
2635
Willy Tarreau55ea7572007-06-17 19:56:27 +02002636 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002637 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002638
2639 if (*(args[1]) == 0) {
2640 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002643 }
2644
Willy Tarreauef6494c2010-01-28 17:12:36 +01002645 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002646 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2647 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002650 }
2651
Willy Tarreauef6494c2010-01-28 17:12:36 +01002652 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002653 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002654 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002657 }
2658
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002659 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002660
Willy Tarreau55ea7572007-06-17 19:56:27 +02002661 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2662 rule->cond = cond;
2663 rule->be.name = strdup(args[1]);
2664 LIST_INIT(&rule->list);
2665 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2666 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002667 else if ((!strcmp(args[0], "force-persist")) ||
2668 (!strcmp(args[0], "ignore-persist"))) {
2669 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002670
2671 if (curproxy == &defproxy) {
2672 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2673 err_code |= ERR_ALERT | ERR_FATAL;
2674 goto out;
2675 }
2676
2677 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2678 err_code |= ERR_WARN;
2679
Willy Tarreauef6494c2010-01-28 17:12:36 +01002680 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002681 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2682 file, linenum, args[0]);
2683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
2685 }
2686
Willy Tarreauef6494c2010-01-28 17:12:36 +01002687 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002688 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2689 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
2692 }
2693
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002694 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002695
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002696 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002697 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002698 if (!strcmp(args[0], "force-persist")) {
2699 rule->type = PERSIST_TYPE_FORCE;
2700 } else {
2701 rule->type = PERSIST_TYPE_IGNORE;
2702 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002703 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002704 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002705 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002706 else if (!strcmp(args[0], "stick-table")) {
2707 int myidx = 1;
2708
Emeric Brun32da3c42010-09-23 18:39:19 +02002709 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002710 curproxy->table.type = (unsigned int)-1;
2711 while (*args[myidx]) {
2712 const char *err;
2713
2714 if (strcmp(args[myidx], "size") == 0) {
2715 myidx++;
2716 if (!*(args[myidx])) {
2717 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2718 file, linenum, args[myidx-1]);
2719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
2721 }
2722 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2723 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2724 file, linenum, *err, args[myidx-1]);
2725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
2727 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002728 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002729 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002730 else if (strcmp(args[myidx], "peers") == 0) {
2731 myidx++;
2732 if (!*(args[myidx])) {
2733 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2734 file, linenum, args[myidx-1]);
2735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
2737 }
2738 curproxy->table.peers.name = strdup(args[myidx++]);
2739 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002740 else if (strcmp(args[myidx], "expire") == 0) {
2741 myidx++;
2742 if (!*(args[myidx])) {
2743 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2744 file, linenum, args[myidx-1]);
2745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
2747 }
2748 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2749 if (err) {
2750 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2751 file, linenum, *err, args[myidx-1]);
2752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
2754 }
2755 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002756 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002757 }
2758 else if (strcmp(args[myidx], "nopurge") == 0) {
2759 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002760 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002761 }
2762 else if (strcmp(args[myidx], "type") == 0) {
2763 myidx++;
2764 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2765 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2766 file, linenum, args[myidx]);
2767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
2769 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002770 /* myidx already points to next arg */
2771 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002772 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002773 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002774 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002775
2776 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002777 nw = args[myidx];
2778 while (*nw) {
2779 /* the "store" keyword supports a comma-separated list */
2780 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002781 sa = NULL; /* store arg */
2782 while (*nw && *nw != ',') {
2783 if (*nw == '(') {
2784 *nw = 0;
2785 sa = ++nw;
2786 while (*nw != ')') {
2787 if (!*nw) {
2788 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2789 file, linenum, args[0], cw);
2790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
2792 }
2793 nw++;
2794 }
2795 *nw = '\0';
2796 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002797 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002798 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002799 if (*nw)
2800 *nw++ = '\0';
2801 type = stktable_get_data_type(cw);
2802 if (type < 0) {
2803 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2804 file, linenum, args[0], cw);
2805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
2807 }
Willy Tarreauac782882010-06-20 10:41:54 +02002808
2809 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2810 switch (err) {
2811 case PE_NONE: break;
2812 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002813 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2814 file, linenum, args[0], cw);
2815 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002816 break;
2817
2818 case PE_ARG_MISSING:
2819 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2820 file, linenum, args[0], cw);
2821 err_code |= ERR_ALERT | ERR_FATAL;
2822 goto out;
2823
2824 case PE_ARG_NOT_USED:
2825 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2826 file, linenum, args[0], cw);
2827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
2829
2830 default:
2831 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2832 file, linenum, args[0], cw);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002835 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002836 }
2837 myidx++;
2838 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002839 else {
2840 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2841 file, linenum, args[myidx]);
2842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002844 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002845 }
2846
2847 if (!curproxy->table.size) {
2848 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2849 file, linenum);
2850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
2852 }
2853
2854 if (curproxy->table.type == (unsigned int)-1) {
2855 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2856 file, linenum);
2857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
2859 }
2860 }
2861 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002862 struct sticking_rule *rule;
2863 struct pattern_expr *expr;
2864 int myidx = 0;
2865 const char *name = NULL;
2866 int flags;
2867
2868 if (curproxy == &defproxy) {
2869 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
2872 }
2873
2874 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2875 err_code |= ERR_WARN;
2876 goto out;
2877 }
2878
2879 myidx++;
2880 if ((strcmp(args[myidx], "store") == 0) ||
2881 (strcmp(args[myidx], "store-request") == 0)) {
2882 myidx++;
2883 flags = STK_IS_STORE;
2884 }
2885 else if (strcmp(args[myidx], "store-response") == 0) {
2886 myidx++;
2887 flags = STK_IS_STORE | STK_ON_RSP;
2888 }
2889 else if (strcmp(args[myidx], "match") == 0) {
2890 myidx++;
2891 flags = STK_IS_MATCH;
2892 }
2893 else if (strcmp(args[myidx], "on") == 0) {
2894 myidx++;
2895 flags = STK_IS_MATCH | STK_IS_STORE;
2896 }
2897 else {
2898 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2899 err_code |= ERR_ALERT | ERR_FATAL;
2900 goto out;
2901 }
2902
2903 if (*(args[myidx]) == 0) {
2904 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
2907 }
2908
Emeric Brun485479d2010-09-23 18:02:19 +02002909 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002910 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002911 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
2914 }
2915
2916 if (flags & STK_ON_RSP) {
2917 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2918 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2919 file, linenum, args[0], expr->fetch->kw);
2920 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002921 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002922 goto out;
2923 }
2924 } else {
2925 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2926 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2927 file, linenum, args[0], expr->fetch->kw);
2928 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002929 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002930 goto out;
2931 }
2932 }
2933
2934 if (strcmp(args[myidx], "table") == 0) {
2935 myidx++;
2936 name = args[myidx++];
2937 }
2938
Willy Tarreauef6494c2010-01-28 17:12:36 +01002939 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2940 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002941 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2942 file, linenum, args[0]);
2943 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002944 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002945 goto out;
2946 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002947 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002948 else if (*(args[myidx])) {
2949 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2950 file, linenum, args[0], args[myidx]);
2951 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002952 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002953 goto out;
2954 }
Emeric Brun97679e72010-09-23 17:56:44 +02002955 if (flags & STK_ON_RSP)
2956 err_code |= warnif_cond_requires_req(cond, file, linenum);
2957 else
2958 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002959
Emeric Brunb982a3d2010-01-04 15:45:53 +01002960 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2961 rule->cond = cond;
2962 rule->expr = expr;
2963 rule->flags = flags;
2964 rule->table.name = name ? strdup(name) : NULL;
2965 LIST_INIT(&rule->list);
2966 if (flags & STK_ON_RSP)
2967 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2968 else
2969 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2970 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002972 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002973 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002974
Willy Tarreaubaaee002006-06-26 02:48:02 +02002975 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2976 curproxy->uri_auth = NULL; /* we must detach from the default config */
2977
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002978 if (!*args[1]) {
2979 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002980 } else if (!strcmp(args[1], "admin")) {
2981 struct stats_admin_rule *rule;
2982
2983 if (curproxy == &defproxy) {
2984 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
2987 }
2988
2989 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2990 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2991 err_code |= ERR_ALERT | ERR_ABORT;
2992 goto out;
2993 }
2994
2995 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2996 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2997 file, linenum, args[0], args[1]);
2998 err_code |= ERR_ALERT | ERR_FATAL;
2999 goto out;
3000 }
3001 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3002 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3003 file, linenum, args[0], args[1]);
3004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
3006 }
3007
3008 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3009
3010 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3011 rule->cond = cond;
3012 LIST_INIT(&rule->list);
3013 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 } else if (!strcmp(args[1], "uri")) {
3015 if (*(args[2]) == 0) {
3016 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003019 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3020 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003021 err_code |= ERR_ALERT | ERR_ABORT;
3022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 }
3024 } else if (!strcmp(args[1], "realm")) {
3025 if (*(args[2]) == 0) {
3026 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003027 err_code |= ERR_ALERT | ERR_FATAL;
3028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3030 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003031 err_code |= ERR_ALERT | ERR_ABORT;
3032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003034 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003035 unsigned interval;
3036
3037 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3038 if (err) {
3039 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3040 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003041 err_code |= ERR_ALERT | ERR_FATAL;
3042 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003043 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3044 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_ALERT | ERR_ABORT;
3046 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003047 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003048 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003049 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003050
3051 if (curproxy == &defproxy) {
3052 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
3055 }
3056
3057 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3058 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3059 err_code |= ERR_ALERT | ERR_ABORT;
3060 goto out;
3061 }
3062
Willy Tarreauff011f22011-01-06 17:51:27 +01003063 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3064 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003065 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3066 file, linenum, args[0]);
3067 err_code |= ERR_WARN;
3068 }
3069
Willy Tarreauff011f22011-01-06 17:51:27 +01003070 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003071
Willy Tarreauff011f22011-01-06 17:51:27 +01003072 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003073 err_code |= ERR_ALERT | ERR_ABORT;
3074 goto out;
3075 }
3076
Willy Tarreauff011f22011-01-06 17:51:27 +01003077 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3078 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003079
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 } else if (!strcmp(args[1], "auth")) {
3081 if (*(args[2]) == 0) {
3082 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3086 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003087 err_code |= ERR_ALERT | ERR_ABORT;
3088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089 }
3090 } else if (!strcmp(args[1], "scope")) {
3091 if (*(args[2]) == 0) {
3092 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003093 err_code |= ERR_ALERT | ERR_FATAL;
3094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003095 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3096 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003097 err_code |= ERR_ALERT | ERR_ABORT;
3098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003099 }
3100 } else if (!strcmp(args[1], "enable")) {
3101 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3102 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003103 err_code |= ERR_ALERT | ERR_ABORT;
3104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003106 } else if (!strcmp(args[1], "hide-version")) {
3107 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3108 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003109 err_code |= ERR_ALERT | ERR_ABORT;
3110 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003111 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003112 } else if (!strcmp(args[1], "show-legends")) {
3113 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3114 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3115 err_code |= ERR_ALERT | ERR_ABORT;
3116 goto out;
3117 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003118 } else if (!strcmp(args[1], "show-node")) {
3119
3120 if (*args[2]) {
3121 int i;
3122 char c;
3123
3124 for (i=0; args[2][i]; i++) {
3125 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003126 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3127 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003128 break;
3129 }
3130
3131 if (!i || args[2][i]) {
3132 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3133 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3134 file, linenum, args[0], args[1]);
3135 err_code |= ERR_ALERT | ERR_FATAL;
3136 goto out;
3137 }
3138 }
3139
3140 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3141 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3142 err_code |= ERR_ALERT | ERR_ABORT;
3143 goto out;
3144 }
3145 } else if (!strcmp(args[1], "show-desc")) {
3146 char *desc = NULL;
3147
3148 if (*args[2]) {
3149 int i, len=0;
3150 char *d;
3151
3152 for(i=2; *args[i]; i++)
3153 len += strlen(args[i])+1;
3154
3155 desc = d = (char *)calloc(1, len);
3156
3157 d += sprintf(d, "%s", args[2]);
3158 for(i=3; *args[i]; i++)
3159 d += sprintf(d, " %s", args[i]);
3160 }
3161
3162 if (!*args[2] && !global.desc)
3163 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3164 file, linenum, args[1]);
3165 else {
3166 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3167 free(desc);
3168 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3169 err_code |= ERR_ALERT | ERR_ABORT;
3170 goto out;
3171 }
3172 free(desc);
3173 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003174 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003175stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003176 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 +01003177 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 }
3181 }
3182 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003183 int optnum;
3184
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003185 if (*(args[1]) == '\0') {
3186 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3187 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003188 err_code |= ERR_ALERT | ERR_FATAL;
3189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003191
3192 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3193 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003194 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3195 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3196 file, linenum, cfg_opts[optnum].name);
3197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
3199 }
Willy Tarreau93893792009-07-23 13:19:11 +02003200 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3201 err_code |= ERR_WARN;
3202 goto out;
3203 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003204
Willy Tarreau3842f002009-06-14 11:39:52 +02003205 curproxy->no_options &= ~cfg_opts[optnum].val;
3206 curproxy->options &= ~cfg_opts[optnum].val;
3207
3208 switch (kwm) {
3209 case KWM_STD:
3210 curproxy->options |= cfg_opts[optnum].val;
3211 break;
3212 case KWM_NO:
3213 curproxy->no_options |= cfg_opts[optnum].val;
3214 break;
3215 case KWM_DEF: /* already cleared */
3216 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003217 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003218
Willy Tarreau93893792009-07-23 13:19:11 +02003219 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003220 }
3221 }
3222
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003223 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3224 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003225 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3226 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3227 file, linenum, cfg_opts2[optnum].name);
3228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
3230 }
Willy Tarreau93893792009-07-23 13:19:11 +02003231 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3232 err_code |= ERR_WARN;
3233 goto out;
3234 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003235
Willy Tarreau3842f002009-06-14 11:39:52 +02003236 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3237 curproxy->options2 &= ~cfg_opts2[optnum].val;
3238
3239 switch (kwm) {
3240 case KWM_STD:
3241 curproxy->options2 |= cfg_opts2[optnum].val;
3242 break;
3243 case KWM_NO:
3244 curproxy->no_options2 |= cfg_opts2[optnum].val;
3245 break;
3246 case KWM_DEF: /* already cleared */
3247 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003248 }
Willy Tarreau93893792009-07-23 13:19:11 +02003249 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003250 }
3251 }
3252
Willy Tarreau3842f002009-06-14 11:39:52 +02003253 if (kwm != KWM_STD) {
3254 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003255 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003256 err_code |= ERR_ALERT | ERR_FATAL;
3257 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003258 }
3259
Emeric Brun3a058f32009-06-30 18:26:00 +02003260 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003262 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003264 if (*(args[2]) != '\0') {
3265 if (!strcmp(args[2], "clf")) {
3266 curproxy->options2 |= PR_O2_CLFLOG;
3267 } else {
3268 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003269 err_code |= ERR_ALERT | ERR_FATAL;
3270 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003271 }
3272 }
3273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274 else if (!strcmp(args[1], "tcplog"))
3275 /* generate a detailed TCP log */
3276 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003277 else if (!strcmp(args[1], "tcpka")) {
3278 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003279 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003280 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003281
3282 if (curproxy->cap & PR_CAP_FE)
3283 curproxy->options |= PR_O_TCP_CLI_KA;
3284 if (curproxy->cap & PR_CAP_BE)
3285 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 }
3287 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003288 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003289 err_code |= ERR_WARN;
3290
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003292 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003293 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003294 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003295 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003296 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003297 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003298 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003299 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 if (!*args[2]) { /* no argument */
3301 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3302 curproxy->check_len = strlen(DEF_CHECK_REQ);
3303 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003304 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 curproxy->check_req = (char *)malloc(reqlen);
3306 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003307 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003309 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 if (*args[4])
3311 reqlen += strlen(args[4]);
3312 else
3313 reqlen += strlen("HTTP/1.0");
3314
3315 curproxy->check_req = (char *)malloc(reqlen);
3316 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003317 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003319 }
3320 else if (!strcmp(args[1], "ssl-hello-chk")) {
3321 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003322 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003323 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003324
Willy Tarreaua534fea2008-08-03 12:19:50 +02003325 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003326 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003327 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003328 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003329 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003330 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003331 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003332 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 }
Willy Tarreau23677902007-05-08 23:50:35 +02003334 else if (!strcmp(args[1], "smtpchk")) {
3335 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003336 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003337 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003338 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003339 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003340 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003341 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003342 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003343 curproxy->options |= PR_O_SMTP_CHK;
3344
3345 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3346 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3347 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3348 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3349 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3350 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3351 curproxy->check_req = (char *)malloc(reqlen);
3352 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3353 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3354 } else {
3355 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3356 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3357 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3358 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3359 }
3360 }
3361 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003362 else if (!strcmp(args[1], "pgsql-check")) {
3363 /* use PostgreSQL request to check servers' health */
3364 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3365 err_code |= ERR_WARN;
3366
3367 free(curproxy->check_req);
3368 curproxy->check_req = NULL;
3369 curproxy->options &= ~PR_O_HTTP_CHK;
3370 curproxy->options &= ~PR_O_SMTP_CHK;
3371 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3372 curproxy->options2 &= ~PR_O2_LDAP_CHK;
3373 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3374 curproxy->options2 |= PR_O2_PGSQL_CHK;
3375
3376 if (*(args[2])) {
3377 int cur_arg = 2;
3378
3379 while (*(args[cur_arg])) {
3380 if (strcmp(args[cur_arg], "user") == 0) {
3381 char * packet;
3382 uint32_t packet_len;
3383 uint32_t pv;
3384
3385 /* suboption header - needs additional argument for it */
3386 if (*(args[cur_arg+1]) == 0) {
3387 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3388 file, linenum, args[0], args[1], args[cur_arg]);
3389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
3391 }
3392
3393 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3394 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3395 pv = htonl(0x30000); /* protocol version 3.0 */
3396
3397 packet = (char*) calloc(1, packet_len);
3398
3399 memcpy(packet + 4, &pv, 4);
3400
3401 /* copy "user" */
3402 memcpy(packet + 8, "user", 4);
3403
3404 /* copy username */
3405 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3406
3407 free(curproxy->check_req);
3408 curproxy->check_req = packet;
3409 curproxy->check_len = packet_len;
3410
3411 packet_len = htonl(packet_len);
3412 memcpy(packet, &packet_len, 4);
3413 cur_arg += 2;
3414 } else {
3415 /* unknown suboption - catchall */
3416 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3417 file, linenum, args[0], args[1]);
3418 err_code |= ERR_ALERT | ERR_FATAL;
3419 goto out;
3420 }
3421 } /* end while loop */
3422 }
3423 }
3424
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003425 else if (!strcmp(args[1], "mysql-check")) {
3426 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003427 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3428 err_code |= ERR_WARN;
3429
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003430 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003431 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003432 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003433 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003434 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003435 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003436 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003437 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003438
3439 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3440 * const char mysql40_client_auth_pkt[] = {
3441 * "\x0e\x00\x00" // packet length
3442 * "\x01" // packet number
3443 * "\x00\x00" // client capabilities
3444 * "\x00\x00\x01" // max packet
3445 * "haproxy\x00" // username (null terminated string)
3446 * "\x00" // filler (always 0x00)
3447 * "\x01\x00\x00" // packet length
3448 * "\x00" // packet number
3449 * "\x01" // COM_QUIT command
3450 * };
3451 */
3452
3453 if (*(args[2])) {
3454 int cur_arg = 2;
3455
3456 while (*(args[cur_arg])) {
3457 if (strcmp(args[cur_arg], "user") == 0) {
3458 char *mysqluser;
3459 int packetlen, reqlen, userlen;
3460
3461 /* suboption header - needs additional argument for it */
3462 if (*(args[cur_arg+1]) == 0) {
3463 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3464 file, linenum, args[0], args[1], args[cur_arg]);
3465 err_code |= ERR_ALERT | ERR_FATAL;
3466 goto out;
3467 }
3468 mysqluser = args[cur_arg + 1];
3469 userlen = strlen(mysqluser);
3470 packetlen = userlen + 7;
3471 reqlen = packetlen + 9;
3472
3473 free(curproxy->check_req);
3474 curproxy->check_req = (char *)calloc(1, reqlen);
3475 curproxy->check_len = reqlen;
3476
3477 snprintf(curproxy->check_req, 4, "%c%c%c",
3478 ((unsigned char) packetlen & 0xff),
3479 ((unsigned char) (packetlen >> 8) & 0xff),
3480 ((unsigned char) (packetlen >> 16) & 0xff));
3481
3482 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003483 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003484 curproxy->check_req[8] = 1;
3485 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3486 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3487 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3488 cur_arg += 2;
3489 } else {
3490 /* unknown suboption - catchall */
3491 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3492 file, linenum, args[0], args[1]);
3493 err_code |= ERR_ALERT | ERR_FATAL;
3494 goto out;
3495 }
3496 } /* end while loop */
3497 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003498 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003499 else if (!strcmp(args[1], "ldap-check")) {
3500 /* use LDAP request to check servers' health */
3501 free(curproxy->check_req);
3502 curproxy->check_req = NULL;
3503 curproxy->options &= ~PR_O_HTTP_CHK;
3504 curproxy->options &= ~PR_O_SMTP_CHK;
3505 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3506 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003507 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003508 curproxy->options2 |= PR_O2_LDAP_CHK;
3509
3510 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3511 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3512 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3513 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003514 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003515 int cur_arg;
3516
3517 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3518 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003519 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003520
3521 curproxy->options |= PR_O_FWDFOR;
3522
3523 free(curproxy->fwdfor_hdr_name);
3524 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3525 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3526
3527 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3528 cur_arg = 2;
3529 while (*(args[cur_arg])) {
3530 if (!strcmp(args[cur_arg], "except")) {
3531 /* suboption except - needs additional argument for it */
3532 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3533 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3534 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003537 }
3538 /* flush useless bits */
3539 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003540 cur_arg += 2;
3541 } else if (!strcmp(args[cur_arg], "header")) {
3542 /* suboption header - needs additional argument for it */
3543 if (*(args[cur_arg+1]) == 0) {
3544 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3545 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003546 err_code |= ERR_ALERT | ERR_FATAL;
3547 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003548 }
3549 free(curproxy->fwdfor_hdr_name);
3550 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3551 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3552 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003553 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003554 /* unknown suboption - catchall */
3555 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3556 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003557 err_code |= ERR_ALERT | ERR_FATAL;
3558 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003559 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003560 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003561 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003562 else if (!strcmp(args[1], "originalto")) {
3563 int cur_arg;
3564
3565 /* insert x-original-to field, but not for the IP address listed as an except.
3566 * set default options (ie: bitfield, header name, etc)
3567 */
3568
3569 curproxy->options |= PR_O_ORGTO;
3570
3571 free(curproxy->orgto_hdr_name);
3572 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3573 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3574
3575 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3576 cur_arg = 2;
3577 while (*(args[cur_arg])) {
3578 if (!strcmp(args[cur_arg], "except")) {
3579 /* suboption except - needs additional argument for it */
3580 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3581 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3582 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003583 err_code |= ERR_ALERT | ERR_FATAL;
3584 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003585 }
3586 /* flush useless bits */
3587 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3588 cur_arg += 2;
3589 } else if (!strcmp(args[cur_arg], "header")) {
3590 /* suboption header - needs additional argument for it */
3591 if (*(args[cur_arg+1]) == 0) {
3592 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3593 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003596 }
3597 free(curproxy->orgto_hdr_name);
3598 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3599 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3600 cur_arg += 2;
3601 } else {
3602 /* unknown suboption - catchall */
3603 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3604 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003607 }
3608 } /* end while loop */
3609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003610 else {
3611 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003614 }
Willy Tarreau93893792009-07-23 13:19:11 +02003615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003616 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003617 else if (!strcmp(args[0], "default_backend")) {
3618 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003619 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003620
3621 if (*(args[1]) == 0) {
3622 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003623 err_code |= ERR_ALERT | ERR_FATAL;
3624 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003625 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003626 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003627 curproxy->defbe.name = strdup(args[1]);
3628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003629 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003630 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003632
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003633 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3634 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003635 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003636 /* enable reconnections to dispatch */
3637 curproxy->options |= PR_O_REDISP;
3638 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003639 else if (!strcmp(args[0], "http-check")) {
3640 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003641 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003642
3643 if (strcmp(args[1], "disable-on-404") == 0) {
3644 /* enable a graceful server shutdown on an HTTP 404 response */
3645 curproxy->options |= PR_O_DISABLE404;
3646 }
Willy Tarreauef781042010-01-27 11:53:01 +01003647 else if (strcmp(args[1], "send-state") == 0) {
3648 /* enable emission of the apparent state of a server in HTTP checks */
3649 curproxy->options2 |= PR_O2_CHK_SNDST;
3650 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003651 else if (strcmp(args[1], "expect") == 0) {
3652 const char *ptr_arg;
3653 int cur_arg;
3654
3655 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3656 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3657 err_code |= ERR_ALERT | ERR_FATAL;
3658 goto out;
3659 }
3660
3661 cur_arg = 2;
3662 /* consider exclamation marks, sole or at the beginning of a word */
3663 while (*(ptr_arg = args[cur_arg])) {
3664 while (*ptr_arg == '!') {
3665 curproxy->options2 ^= PR_O2_EXP_INV;
3666 ptr_arg++;
3667 }
3668 if (*ptr_arg)
3669 break;
3670 cur_arg++;
3671 }
3672 /* now ptr_arg points to the beginning of a word past any possible
3673 * exclamation mark, and cur_arg is the argument which holds this word.
3674 */
3675 if (strcmp(ptr_arg, "status") == 0) {
3676 if (!*(args[cur_arg + 1])) {
3677 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3678 file, linenum, args[0], args[1], ptr_arg);
3679 err_code |= ERR_ALERT | ERR_FATAL;
3680 goto out;
3681 }
3682 curproxy->options2 |= PR_O2_EXP_STS;
3683 curproxy->expect_str = strdup(args[cur_arg + 1]);
3684 }
3685 else if (strcmp(ptr_arg, "string") == 0) {
3686 if (!*(args[cur_arg + 1])) {
3687 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3688 file, linenum, args[0], args[1], ptr_arg);
3689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
3691 }
3692 curproxy->options2 |= PR_O2_EXP_STR;
3693 curproxy->expect_str = strdup(args[cur_arg + 1]);
3694 }
3695 else if (strcmp(ptr_arg, "rstatus") == 0) {
3696 if (!*(args[cur_arg + 1])) {
3697 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3698 file, linenum, args[0], args[1], ptr_arg);
3699 err_code |= ERR_ALERT | ERR_FATAL;
3700 goto out;
3701 }
3702 curproxy->options2 |= PR_O2_EXP_RSTS;
3703 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3704 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3705 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3706 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
3709 }
3710 }
3711 else if (strcmp(ptr_arg, "rstring") == 0) {
3712 if (!*(args[cur_arg + 1])) {
3713 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3714 file, linenum, args[0], args[1], ptr_arg);
3715 err_code |= ERR_ALERT | ERR_FATAL;
3716 goto out;
3717 }
3718 curproxy->options2 |= PR_O2_EXP_RSTR;
3719 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3720 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3721 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3722 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3723 err_code |= ERR_ALERT | ERR_FATAL;
3724 goto out;
3725 }
3726 }
3727 else {
3728 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3729 file, linenum, args[0], args[1], ptr_arg);
3730 err_code |= ERR_ALERT | ERR_FATAL;
3731 goto out;
3732 }
3733 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003734 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003735 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003738 }
3739 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003740 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003741 if (curproxy == &defproxy) {
3742 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003743 err_code |= ERR_ALERT | ERR_FATAL;
3744 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003745 }
3746
Willy Tarreaub80c2302007-11-30 20:51:32 +01003747 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003748 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003749
3750 if (strcmp(args[1], "fail") == 0) {
3751 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003752 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003753 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3754 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_ALERT | ERR_FATAL;
3756 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003757 }
3758
Willy Tarreauef6494c2010-01-28 17:12:36 +01003759 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003760 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3761 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003764 }
3765 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3766 }
3767 else {
3768 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003771 }
3772 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003773#ifdef TPROXY
3774 else if (!strcmp(args[0], "transparent")) {
3775 /* enable transparent proxy connections */
3776 curproxy->options |= PR_O_TRANSP;
3777 }
3778#endif
3779 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003780 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003782
Willy Tarreaubaaee002006-06-26 02:48:02 +02003783 if (*(args[1]) == 0) {
3784 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003787 }
3788 curproxy->maxconn = atol(args[1]);
3789 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003790 else if (!strcmp(args[0], "backlog")) { /* backlog */
3791 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003793
3794 if (*(args[1]) == 0) {
3795 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003798 }
3799 curproxy->backlog = atol(args[1]);
3800 }
Willy Tarreau86034312006-12-29 00:10:33 +01003801 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003802 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003804
Willy Tarreau86034312006-12-29 00:10:33 +01003805 if (*(args[1]) == 0) {
3806 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003809 }
3810 curproxy->fullconn = atol(args[1]);
3811 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003812 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3813 if (*(args[1]) == 0) {
3814 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003818 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3819 if (err) {
3820 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3821 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003824 }
3825 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003826 }
3827 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003828 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003829 if (curproxy == &defproxy) {
3830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003834 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003836
Willy Tarreaubaaee002006-06-26 02:48:02 +02003837 if (strchr(args[1], ':') == NULL) {
3838 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003842 sk = str2sa(args[1]);
3843 if (!sk) {
3844 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
3847 }
3848 curproxy->dispatch_addr = *sk;
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01003849 curproxy->options2 |= PR_O2_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 }
3851 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003852 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003853 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003854
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003855 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003856 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3857 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003861 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003862 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3863 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3864 err_code |= ERR_WARN;
3865
3866 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3867 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3868 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3869 }
3870 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3871 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3872 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3873 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003874 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3875 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3876 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3877 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003878 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003879 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
3882 }
3883 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003884 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003885 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003886 char *rport, *raddr;
3887 short realport = 0;
3888 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003890 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003894 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003895 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003896 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003897
3898 if (!*args[2]) {
3899 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3900 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003901 err_code |= ERR_ALERT | ERR_FATAL;
3902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003903 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003904
3905 err = invalid_char(args[1]);
3906 if (err) {
3907 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3908 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003909 err_code |= ERR_ALERT | ERR_FATAL;
3910 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003911 }
3912
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003913 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003914 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003915
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003916 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3917 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3918 err_code |= ERR_ALERT | ERR_ABORT;
3919 goto out;
3920 }
3921
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003922 /* the servers are linked backwards first */
3923 newsrv->next = curproxy->srv;
3924 curproxy->srv = newsrv;
3925 newsrv->proxy = curproxy;
3926 newsrv->conf.file = file;
3927 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003928
Simon Hormanaf514952011-06-21 14:34:57 +09003929 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003930 LIST_INIT(&newsrv->pendconns);
3931 do_check = 0;
3932 newsrv->state = SRV_RUNNING; /* early server setup */
3933 newsrv->last_change = now.tv_sec;
3934 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003935
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003936 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003937 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003938 * - IP: => port=+0, relative
3939 * - IP:N => port=N, absolute
3940 * - IP:+N => port=+N, relative
3941 * - IP:-N => port=-N, relative
3942 */
3943 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003944 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003945 if (rport) {
3946 *rport++ = 0;
3947 realport = atol(rport);
3948 if (!isdigit((unsigned char)*rport))
3949 newsrv->state |= SRV_MAPPORTS;
3950 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003951 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003952
Willy Tarreaufab5a432011-03-04 15:31:53 +01003953 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003954 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003955 if (!sk) {
3956 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
3959 }
3960 newsrv->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01003961
3962 switch (newsrv->addr.ss_family) {
3963 case AF_INET:
3964 ((struct sockaddr_in *)&newsrv->addr)->sin_port = htons(realport);
3965 break;
3966 case AF_INET6:
3967 ((struct sockaddr_in6 *)&newsrv->addr)->sin6_port = htons(realport);
3968 break;
3969 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003970
3971 newsrv->check_port = curproxy->defsrv.check_port;
3972 newsrv->inter = curproxy->defsrv.inter;
3973 newsrv->fastinter = curproxy->defsrv.fastinter;
3974 newsrv->downinter = curproxy->defsrv.downinter;
3975 newsrv->rise = curproxy->defsrv.rise;
3976 newsrv->fall = curproxy->defsrv.fall;
3977 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3978 newsrv->minconn = curproxy->defsrv.minconn;
3979 newsrv->maxconn = curproxy->defsrv.maxconn;
3980 newsrv->slowstart = curproxy->defsrv.slowstart;
3981 newsrv->onerror = curproxy->defsrv.onerror;
3982 newsrv->consecutive_errors_limit
3983 = curproxy->defsrv.consecutive_errors_limit;
3984 newsrv->uweight = newsrv->iweight
3985 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003986
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003987 newsrv->curfd = -1; /* no health-check in progress */
3988 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003989
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003990 cur_arg = 3;
3991 } else {
3992 newsrv = &curproxy->defsrv;
3993 cur_arg = 1;
3994 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003995
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003997 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003998 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003999
4000 if (!*args[cur_arg + 1]) {
4001 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4002 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004003 err_code |= ERR_ALERT | ERR_FATAL;
4004 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004005 }
4006
4007 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004008 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004009
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004010 if (newsrv->puid <= 0) {
4011 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004012 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004013 err_code |= ERR_ALERT | ERR_FATAL;
4014 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004015 }
4016
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004017 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4018 if (node) {
4019 struct server *target = container_of(node, struct server, conf.id);
4020 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4021 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4022 err_code |= ERR_ALERT | ERR_FATAL;
4023 goto out;
4024 }
4025 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004026 cur_arg += 2;
4027 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004028 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004029 newsrv->cookie = strdup(args[cur_arg + 1]);
4030 newsrv->cklen = strlen(args[cur_arg + 1]);
4031 cur_arg += 2;
4032 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004033 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004034 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4035 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4036 cur_arg += 2;
4037 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004038 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004039 if (!*args[cur_arg + 1]) {
4040 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4041 file, linenum, args[cur_arg]);
4042 err_code |= ERR_ALERT | ERR_FATAL;
4043 goto out;
4044 }
4045
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004047 if (newsrv->rise <= 0) {
4048 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4049 file, linenum, args[cur_arg]);
4050 err_code |= ERR_ALERT | ERR_FATAL;
4051 goto out;
4052 }
4053
Willy Tarreau96839092010-03-29 10:02:24 +02004054 if (newsrv->health)
4055 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004056 cur_arg += 2;
4057 }
4058 else if (!strcmp(args[cur_arg], "fall")) {
4059 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004060
4061 if (!*args[cur_arg + 1]) {
4062 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4063 file, linenum, args[cur_arg]);
4064 err_code |= ERR_ALERT | ERR_FATAL;
4065 goto out;
4066 }
4067
4068 if (newsrv->fall <= 0) {
4069 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4070 file, linenum, args[cur_arg]);
4071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
4073 }
4074
Willy Tarreaubaaee002006-06-26 02:48:02 +02004075 cur_arg += 2;
4076 }
4077 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004078 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4079 if (err) {
4080 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4081 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004084 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004085 if (val <= 0) {
4086 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4087 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004088 err_code |= ERR_ALERT | ERR_FATAL;
4089 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004090 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004091 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004092 cur_arg += 2;
4093 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004094 else if (!strcmp(args[cur_arg], "fastinter")) {
4095 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4096 if (err) {
4097 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4098 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004101 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004102 if (val <= 0) {
4103 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4104 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004105 err_code |= ERR_ALERT | ERR_FATAL;
4106 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004107 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004108 newsrv->fastinter = val;
4109 cur_arg += 2;
4110 }
4111 else if (!strcmp(args[cur_arg], "downinter")) {
4112 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4113 if (err) {
4114 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4115 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004118 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004119 if (val <= 0) {
4120 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4121 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004122 err_code |= ERR_ALERT | ERR_FATAL;
4123 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004124 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004125 newsrv->downinter = val;
4126 cur_arg += 2;
4127 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004128 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004129 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004130 if (!sk) {
4131 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
4134 }
4135 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004136 cur_arg += 2;
4137 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004138 else if (!strcmp(args[cur_arg], "port")) {
4139 newsrv->check_port = atol(args[cur_arg + 1]);
4140 cur_arg += 2;
4141 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004142 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004143 newsrv->state |= SRV_BACKUP;
4144 cur_arg ++;
4145 }
Simon Hormanfa461682011-06-25 09:39:49 +09004146 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4147 newsrv->state |= SRV_NON_STICK;
4148 cur_arg ++;
4149 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004150 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4151 newsrv->state |= SRV_SEND_PROXY;
4152 cur_arg ++;
4153 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 else if (!strcmp(args[cur_arg], "weight")) {
4155 int w;
4156 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004157 if (w < 0 || w > 256) {
4158 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004159 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004160 err_code |= ERR_ALERT | ERR_FATAL;
4161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004162 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004163 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004164 cur_arg += 2;
4165 }
4166 else if (!strcmp(args[cur_arg], "minconn")) {
4167 newsrv->minconn = atol(args[cur_arg + 1]);
4168 cur_arg += 2;
4169 }
4170 else if (!strcmp(args[cur_arg], "maxconn")) {
4171 newsrv->maxconn = atol(args[cur_arg + 1]);
4172 cur_arg += 2;
4173 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004174 else if (!strcmp(args[cur_arg], "maxqueue")) {
4175 newsrv->maxqueue = atol(args[cur_arg + 1]);
4176 cur_arg += 2;
4177 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004178 else if (!strcmp(args[cur_arg], "slowstart")) {
4179 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004180 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004181 if (err) {
4182 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4183 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004186 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004187 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004188 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4189 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004190 err_code |= ERR_ALERT | ERR_FATAL;
4191 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004192 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004193 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004194 cur_arg += 2;
4195 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004196 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004197
4198 if (!*args[cur_arg + 1]) {
4199 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4200 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004201 err_code |= ERR_ALERT | ERR_FATAL;
4202 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004203 }
4204
4205 newsrv->trackit = strdup(args[cur_arg + 1]);
4206
4207 cur_arg += 2;
4208 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004209 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 global.maxsock++;
4211 do_check = 1;
4212 cur_arg += 1;
4213 }
Willy Tarreau96839092010-03-29 10:02:24 +02004214 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4215 newsrv->state |= SRV_MAINTAIN;
4216 newsrv->state &= ~SRV_RUNNING;
4217 newsrv->health = 0;
4218 cur_arg += 1;
4219 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004220 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004221 if (!strcmp(args[cur_arg + 1], "none"))
4222 newsrv->observe = HANA_OBS_NONE;
4223 else if (!strcmp(args[cur_arg + 1], "layer4"))
4224 newsrv->observe = HANA_OBS_LAYER4;
4225 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4226 if (curproxy->mode != PR_MODE_HTTP) {
4227 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4228 file, linenum, args[cur_arg + 1]);
4229 err_code |= ERR_ALERT;
4230 }
4231 newsrv->observe = HANA_OBS_LAYER7;
4232 }
4233 else {
4234 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004235 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004236 file, linenum, args[cur_arg], args[cur_arg + 1]);
4237 err_code |= ERR_ALERT | ERR_FATAL;
4238 goto out;
4239 }
4240
4241 cur_arg += 2;
4242 }
4243 else if (!strcmp(args[cur_arg], "on-error")) {
4244 if (!strcmp(args[cur_arg + 1], "fastinter"))
4245 newsrv->onerror = HANA_ONERR_FASTINTER;
4246 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4247 newsrv->onerror = HANA_ONERR_FAILCHK;
4248 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4249 newsrv->onerror = HANA_ONERR_SUDDTH;
4250 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4251 newsrv->onerror = HANA_ONERR_MARKDWN;
4252 else {
4253 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004254 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004255 file, linenum, args[cur_arg], args[cur_arg + 1]);
4256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
4258 }
4259
4260 cur_arg += 2;
4261 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004262 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4263 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4264 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4265 else {
4266 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4267 file, linenum, args[cur_arg], args[cur_arg + 1]);
4268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
4270 }
4271
4272 cur_arg += 2;
4273 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004274 else if (!strcmp(args[cur_arg], "error-limit")) {
4275 if (!*args[cur_arg + 1]) {
4276 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4277 file, linenum, args[cur_arg]);
4278 err_code |= ERR_ALERT | ERR_FATAL;
4279 goto out;
4280 }
4281
4282 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4283
4284 if (newsrv->consecutive_errors_limit <= 0) {
4285 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4286 file, linenum, args[cur_arg]);
4287 err_code |= ERR_ALERT | ERR_FATAL;
4288 goto out;
4289 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004290 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004291 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004292 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004293 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004294 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004295
Willy Tarreaubaaee002006-06-26 02:48:02 +02004296 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004297#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004298 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004299 file, linenum, "source", "usesrc");
4300#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004301 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004302 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004303#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004304 err_code |= ERR_ALERT | ERR_FATAL;
4305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004306 }
4307 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004308 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4309 if (!sk) {
4310 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4311 err_code |= ERR_ALERT | ERR_FATAL;
4312 goto out;
4313 }
4314 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004315
4316 if (port_low != port_high) {
4317 int i;
4318 if (port_low <= 0 || port_low > 65535 ||
4319 port_high <= 0 || port_high > 65535 ||
4320 port_low > port_high) {
4321 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4322 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004325 }
4326 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4327 for (i = 0; i < newsrv->sport_range->size; i++)
4328 newsrv->sport_range->ports[i] = port_low + i;
4329 }
4330
Willy Tarreaubaaee002006-06-26 02:48:02 +02004331 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004332 while (*(args[cur_arg])) {
4333 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004334#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4335#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004336 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4337 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4338 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004339 err_code |= ERR_ALERT | ERR_FATAL;
4340 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004341 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004342#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004343 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004344 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004345 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004346 err_code |= ERR_ALERT | ERR_FATAL;
4347 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004348 }
4349 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004350 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004351 newsrv->state |= SRV_TPROXY_CLI;
4352 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004353 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004354 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004355 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4356 char *name, *end;
4357
4358 name = args[cur_arg+1] + 7;
4359 while (isspace(*name))
4360 name++;
4361
4362 end = name;
4363 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4364 end++;
4365
4366 newsrv->state &= ~SRV_TPROXY_MASK;
4367 newsrv->state |= SRV_TPROXY_DYN;
4368 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4369 newsrv->bind_hdr_len = end - name;
4370 memcpy(newsrv->bind_hdr_name, name, end - name);
4371 newsrv->bind_hdr_name[end-name] = '\0';
4372 newsrv->bind_hdr_occ = -1;
4373
4374 /* now look for an occurrence number */
4375 while (isspace(*end))
4376 end++;
4377 if (*end == ',') {
4378 end++;
4379 name = end;
4380 if (*end == '-')
4381 end++;
4382 while (isdigit(*end))
4383 end++;
4384 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4385 }
4386
4387 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4388 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4389 " occurrences values smaller than %d.\n",
4390 file, linenum, MAX_HDR_HISTORY);
4391 err_code |= ERR_ALERT | ERR_FATAL;
4392 goto out;
4393 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004394 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004395 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004396 if (!sk) {
4397 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
4400 }
4401 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004402 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004403 }
4404 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004405#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004406 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004407#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004408 cur_arg += 2;
4409 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004410#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004411 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004412 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= ERR_ALERT | ERR_FATAL;
4414 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004415#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4416 } /* "usesrc" */
4417
4418 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4419#ifdef SO_BINDTODEVICE
4420 if (!*args[cur_arg + 1]) {
4421 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4422 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004423 err_code |= ERR_ALERT | ERR_FATAL;
4424 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004425 }
4426 if (newsrv->iface_name)
4427 free(newsrv->iface_name);
4428
4429 newsrv->iface_name = strdup(args[cur_arg + 1]);
4430 newsrv->iface_len = strlen(newsrv->iface_name);
4431 global.last_checks |= LSTCHK_NETADM;
4432#else
4433 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4434 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004435 err_code |= ERR_ALERT | ERR_FATAL;
4436 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004437#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004438 cur_arg += 2;
4439 continue;
4440 }
4441 /* this keyword in not an option of "source" */
4442 break;
4443 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004444 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004445 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004446 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4447 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004448 err_code |= ERR_ALERT | ERR_FATAL;
4449 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004450 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004451 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004452 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004453 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 +01004454 file, linenum, newsrv->id);
4455 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004456 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 +01004457 file, linenum);
4458
Willy Tarreau93893792009-07-23 13:19:11 +02004459 err_code |= ERR_ALERT | ERR_FATAL;
4460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004461 }
4462 }
4463
4464 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004465 if (newsrv->trackit) {
4466 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4467 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004468 err_code |= ERR_ALERT | ERR_FATAL;
4469 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004470 }
4471
David du Colombier6f5ccb12011-03-10 22:26:24 +01004472 switch (newsrv->check_addr.ss_family) {
4473 case AF_INET:
4474 if (!newsrv->check_port && ((struct sockaddr_in *)&newsrv->check_addr)->sin_port)
4475 newsrv->check_port = ntohs(((struct sockaddr_in *)&newsrv->check_addr)->sin_port);
4476 break;
4477 case AF_INET6:
4478 if (!newsrv->check_port && ((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port)
4479 newsrv->check_port = ntohs(((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port);
4480 break;
4481 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004482
Willy Tarreaubaaee002006-06-26 02:48:02 +02004483 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4484 newsrv->check_port = realport; /* by default */
4485 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004486 /* not yet valid, because no port was set on
4487 * the server either. We'll check if we have
4488 * a known port on the first listener.
4489 */
4490 struct listener *l;
4491 l = curproxy->listen;
4492 if (l) {
4493 int port;
4494 port = (l->addr.ss_family == AF_INET6)
4495 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4496 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4497 newsrv->check_port = port;
4498 }
4499 }
4500 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4502 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004503 err_code |= ERR_ALERT | ERR_FATAL;
4504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004506
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004507 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004508 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004509 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4510 err_code |= ERR_ALERT | ERR_ABORT;
4511 goto out;
4512 }
4513
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004514 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004515 newsrv->state |= SRV_CHECKED;
4516 }
4517
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004518 if (!defsrv) {
4519 if (newsrv->state & SRV_BACKUP)
4520 curproxy->srv_bck++;
4521 else
4522 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004523
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004524 newsrv->prev_state = newsrv->state;
4525 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004526 }
4527 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004528 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004529 int facility;
4530
4531 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4532 curproxy->logfac1 = global.logfac1;
4533 curproxy->logsrv1 = global.logsrv1;
4534 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004535 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004536 curproxy->logfac2 = global.logfac2;
4537 curproxy->logsrv2 = global.logsrv2;
4538 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004539 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004540 }
4541 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004542 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004543
4544 facility = get_log_facility(args[2]);
4545 if (facility < 0) {
4546 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4547 exit(1);
4548 }
4549
4550 level = 7; /* max syslog level = debug */
4551 if (*(args[3])) {
4552 level = get_log_level(args[3]);
4553 if (level < 0) {
4554 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4555 exit(1);
4556 }
4557 }
4558
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004559 minlvl = 0; /* limit syslog level to this level (emerg) */
4560 if (*(args[4])) {
4561 minlvl = get_log_level(args[4]);
4562 if (level < 0) {
4563 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4564 exit(1);
4565 }
4566 }
4567
Robert Tsai81ae1952007-12-05 10:47:29 +01004568 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004569 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004570 if (!sk) {
4571 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004572 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
4575 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004576 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004577 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004578 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004579 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004580 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4581 err_code |= ERR_ALERT | ERR_FATAL;
4582 goto out;
4583 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004584 logsrv.addr = *sk;
4585 if (!get_host_port(&logsrv.addr))
4586 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004587 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004588
4589 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004590 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004591 curproxy->logfac1 = facility;
4592 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004593 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004594 }
4595 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004596 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004597 curproxy->logfac2 = facility;
4598 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004599 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004600 }
4601 else {
4602 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 }
4606 }
4607 else {
4608 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4609 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004612 }
4613 }
4614 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004615 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004616 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004617
Willy Tarreau977b8e42006-12-29 14:19:17 +01004618 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004619 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004620
Willy Tarreaubaaee002006-06-26 02:48:02 +02004621 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004622 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4623 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004624 err_code |= ERR_ALERT | ERR_FATAL;
4625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004626 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004627
4628 /* we must first clear any optional default setting */
4629 curproxy->options &= ~PR_O_TPXY_MASK;
4630 free(curproxy->iface_name);
4631 curproxy->iface_name = NULL;
4632 curproxy->iface_len = 0;
4633
Willy Tarreaud5191e72010-02-09 20:50:45 +01004634 sk = str2sa(args[1]);
4635 if (!sk) {
4636 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
4639 }
4640 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004641 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004642
4643 cur_arg = 2;
4644 while (*(args[cur_arg])) {
4645 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004646#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4647#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004648 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4649 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4650 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004651 err_code |= ERR_ALERT | ERR_FATAL;
4652 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004653 }
4654#endif
4655 if (!*args[cur_arg + 1]) {
4656 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4657 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004658 err_code |= ERR_ALERT | ERR_FATAL;
4659 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004660 }
4661
4662 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004663 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004664 curproxy->options |= PR_O_TPXY_CLI;
4665 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004666 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004667 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004668 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4669 char *name, *end;
4670
4671 name = args[cur_arg+1] + 7;
4672 while (isspace(*name))
4673 name++;
4674
4675 end = name;
4676 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4677 end++;
4678
4679 curproxy->options &= ~PR_O_TPXY_MASK;
4680 curproxy->options |= PR_O_TPXY_DYN;
4681 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4682 curproxy->bind_hdr_len = end - name;
4683 memcpy(curproxy->bind_hdr_name, name, end - name);
4684 curproxy->bind_hdr_name[end-name] = '\0';
4685 curproxy->bind_hdr_occ = -1;
4686
4687 /* now look for an occurrence number */
4688 while (isspace(*end))
4689 end++;
4690 if (*end == ',') {
4691 end++;
4692 name = end;
4693 if (*end == '-')
4694 end++;
4695 while (isdigit(*end))
4696 end++;
4697 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4698 }
4699
4700 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4701 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4702 " occurrences values smaller than %d.\n",
4703 file, linenum, MAX_HDR_HISTORY);
4704 err_code |= ERR_ALERT | ERR_FATAL;
4705 goto out;
4706 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004707 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004708 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004709 if (!sk) {
4710 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4711 err_code |= ERR_ALERT | ERR_FATAL;
4712 goto out;
4713 }
4714 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004715 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004716 }
4717 global.last_checks |= LSTCHK_NETADM;
4718#if !defined(CONFIG_HAP_LINUX_TPROXY)
4719 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004720#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004721#else /* no TPROXY support */
4722 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004723 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004724 err_code |= ERR_ALERT | ERR_FATAL;
4725 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004726#endif
4727 cur_arg += 2;
4728 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004729 }
4730
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004731 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4732#ifdef SO_BINDTODEVICE
4733 if (!*args[cur_arg + 1]) {
4734 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4735 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004736 err_code |= ERR_ALERT | ERR_FATAL;
4737 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004738 }
4739 if (curproxy->iface_name)
4740 free(curproxy->iface_name);
4741
4742 curproxy->iface_name = strdup(args[cur_arg + 1]);
4743 curproxy->iface_len = strlen(curproxy->iface_name);
4744 global.last_checks |= LSTCHK_NETADM;
4745#else
4746 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4747 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004748 err_code |= ERR_ALERT | ERR_FATAL;
4749 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004750#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004751 cur_arg += 2;
4752 continue;
4753 }
4754 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4755 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004756 err_code |= ERR_ALERT | ERR_FATAL;
4757 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004759 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004760 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4761 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4762 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004763 err_code |= ERR_ALERT | ERR_FATAL;
4764 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004766 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004767 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4769 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004772 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004773
4774 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4775 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004776 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004777 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004779 }
4780 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004781 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4782 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004783 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004784 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004786 }
4787 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004788 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4789 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004790 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004791 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 }
4794 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004795 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4796 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004797 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004798 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004800 }
4801 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004802 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4803 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004804 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004805 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004807 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004808 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004809 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4810 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004811 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004812 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004813 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004814 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004815 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004816 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4817 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004818 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004819 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004820 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004821 }
4822 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004823 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4824 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004825 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004826 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004827 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004828 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004829 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004830 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004831 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4832 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004833 err_code |= ERR_ALERT | ERR_FATAL;
4834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004835 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004836
4837 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4838 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004839 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004840 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 }
4843 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004844 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4845 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004846 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004847 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004849 }
4850 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004851 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4852 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004853 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004854 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004855 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004856 }
4857 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004858 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4859 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004860 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004861 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004862 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863 }
4864 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004865 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4866 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004867 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004868 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004870 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004871 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004872 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4873 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004874 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004875 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004876 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004877 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004879 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004880
Willy Tarreaubaaee002006-06-26 02:48:02 +02004881 if (curproxy == &defproxy) {
4882 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004883 err_code |= ERR_ALERT | ERR_FATAL;
4884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004885 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004886 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004887 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004888
Willy Tarreaubaaee002006-06-26 02:48:02 +02004889 if (*(args[1]) == 0) {
4890 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004891 err_code |= ERR_ALERT | ERR_FATAL;
4892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004893 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004894
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004895 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4896 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4897 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4898 file, linenum, args[0]);
4899 err_code |= ERR_ALERT | ERR_FATAL;
4900 goto out;
4901 }
4902 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4903 }
4904 else if (*args[2]) {
4905 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4906 file, linenum, args[0], args[2]);
4907 err_code |= ERR_ALERT | ERR_FATAL;
4908 goto out;
4909 }
4910
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004911 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004912 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004913 wl->s = strdup(args[1]);
4914 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004915 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004916 }
4917 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004918 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004919 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4920 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004921 err_code |= ERR_ALERT | ERR_FATAL;
4922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004924
Willy Tarreauade5ec42010-01-28 19:33:49 +01004925 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4926 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004927 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004928 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 }
4931 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004932 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4933 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004934 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004935 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937 }
4938 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004939 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4940 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004941 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004942 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944 }
4945 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004946 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4948 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004949 err_code |= ERR_ALERT | ERR_FATAL;
4950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 }
4952
Willy Tarreauade5ec42010-01-28 19:33:49 +01004953 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4954 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004955 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004956 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004958 }
4959 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004960 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4961 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004962 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004963 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
4966 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004967 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4968 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004969 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004970 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 }
4973 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004974 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004975
Willy Tarreaubaaee002006-06-26 02:48:02 +02004976 if (curproxy == &defproxy) {
4977 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004980 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004981 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004982 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004983
Willy Tarreaubaaee002006-06-26 02:48:02 +02004984 if (*(args[1]) == 0) {
4985 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 }
4989
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004990 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4991 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4992 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4993 file, linenum, args[0]);
4994 err_code |= ERR_ALERT | ERR_FATAL;
4995 goto out;
4996 }
4997 err_code |= warnif_cond_requires_req(cond, file, linenum);
4998 }
4999 else if (*args[2]) {
5000 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5001 file, linenum, args[0], args[2]);
5002 err_code |= ERR_ALERT | ERR_FATAL;
5003 goto out;
5004 }
5005
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005006 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005007 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005008 wl->s = strdup(args[1]);
5009 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 }
5011 else if (!strcmp(args[0], "errorloc") ||
5012 !strcmp(args[0], "errorloc302") ||
5013 !strcmp(args[0], "errorloc303")) { /* error location */
5014 int errnum, errlen;
5015 char *err;
5016
Willy Tarreau977b8e42006-12-29 14:19:17 +01005017 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005018 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005019
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005021 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005022 err_code |= ERR_ALERT | ERR_FATAL;
5023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 }
5025
5026 errnum = atol(args[1]);
5027 if (!strcmp(args[0], "errorloc303")) {
5028 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5029 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5030 } else {
5031 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5032 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5033 }
5034
Willy Tarreau0f772532006-12-23 20:51:41 +01005035 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5036 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005037 chunk_destroy(&curproxy->errmsg[rc]);
5038 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005039 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005040 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005041 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005042
5043 if (rc >= HTTP_ERR_SIZE) {
5044 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5045 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005046 free(err);
5047 }
5048 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005049 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5050 int errnum, errlen, fd;
5051 char *err;
5052 struct stat stat;
5053
5054 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005055 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005056
5057 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005058 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005061 }
5062
5063 fd = open(args[2], O_RDONLY);
5064 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5065 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5066 file, linenum, args[2], args[1]);
5067 if (fd >= 0)
5068 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005069 err_code |= ERR_ALERT | ERR_FATAL;
5070 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005071 }
5072
Willy Tarreau27a674e2009-08-17 07:23:33 +02005073 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005074 errlen = stat.st_size;
5075 } else {
5076 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005077 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005078 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005079 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005080 }
5081
5082 err = malloc(errlen); /* malloc() must succeed during parsing */
5083 errnum = read(fd, err, errlen);
5084 if (errnum != errlen) {
5085 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5086 file, linenum, args[2], args[1]);
5087 close(fd);
5088 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005089 err_code |= ERR_ALERT | ERR_FATAL;
5090 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005091 }
5092 close(fd);
5093
5094 errnum = atol(args[1]);
5095 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5096 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005097 chunk_destroy(&curproxy->errmsg[rc]);
5098 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005099 break;
5100 }
5101 }
5102
5103 if (rc >= HTTP_ERR_SIZE) {
5104 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5105 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005106 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005107 free(err);
5108 }
5109 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005110 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005111 struct cfg_kw_list *kwl;
5112 int index;
5113
5114 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5115 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5116 if (kwl->kw[index].section != CFG_LISTEN)
5117 continue;
5118 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5119 /* prepare error message just in case */
5120 snprintf(trash, sizeof(trash),
5121 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005122 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5123 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005124 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005125 err_code |= ERR_ALERT | ERR_FATAL;
5126 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005127 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005128 else if (rc > 0) {
5129 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005130 err_code |= ERR_WARN;
5131 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005132 }
Willy Tarreau93893792009-07-23 13:19:11 +02005133 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005134 }
5135 }
5136 }
5137
Willy Tarreau6daf3432008-01-22 16:44:08 +01005138 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005139 err_code |= ERR_ALERT | ERR_FATAL;
5140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005141 }
Willy Tarreau93893792009-07-23 13:19:11 +02005142 out:
5143 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005144}
5145
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005146int
5147cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5148{
5149
5150 int err_code = 0;
5151 const char *err;
5152
5153 if (!strcmp(args[0], "userlist")) { /* new userlist */
5154 struct userlist *newul;
5155
5156 if (!*args[1]) {
5157 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5158 file, linenum, args[0]);
5159 err_code |= ERR_ALERT | ERR_FATAL;
5160 goto out;
5161 }
5162
5163 err = invalid_char(args[1]);
5164 if (err) {
5165 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5166 file, linenum, *err, args[0], args[1]);
5167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
5169 }
5170
5171 for (newul = userlist; newul; newul = newul->next)
5172 if (!strcmp(newul->name, args[1])) {
5173 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5174 file, linenum, args[1]);
5175 err_code |= ERR_WARN;
5176 goto out;
5177 }
5178
5179 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5180 if (!newul) {
5181 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5182 err_code |= ERR_ALERT | ERR_ABORT;
5183 goto out;
5184 }
5185
5186 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5187 newul->name = strdup(args[1]);
5188
5189 if (!newul->groupusers | !newul->name) {
5190 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5191 err_code |= ERR_ALERT | ERR_ABORT;
5192 goto out;
5193 }
5194
5195 newul->next = userlist;
5196 userlist = newul;
5197
5198 } else if (!strcmp(args[0], "group")) { /* new group */
5199 int cur_arg, i;
5200 const char *err;
5201
5202 if (!*args[1]) {
5203 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5204 file, linenum, args[0]);
5205 err_code |= ERR_ALERT | ERR_FATAL;
5206 goto out;
5207 }
5208
5209 err = invalid_char(args[1]);
5210 if (err) {
5211 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5212 file, linenum, *err, args[0], args[1]);
5213 err_code |= ERR_ALERT | ERR_FATAL;
5214 goto out;
5215 }
5216
5217 for(i = 0; i < userlist->grpcnt; i++)
5218 if (!strcmp(userlist->groups[i], args[1])) {
5219 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5220 file, linenum, args[1], userlist->name);
5221 err_code |= ERR_ALERT;
5222 goto out;
5223 }
5224
5225 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5226 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5227 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5228 err_code |= ERR_ALERT | ERR_FATAL;
5229 goto out;
5230 }
5231
5232 cur_arg = 2;
5233
5234 while (*args[cur_arg]) {
5235 if (!strcmp(args[cur_arg], "users")) {
5236 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5237 cur_arg += 2;
5238 continue;
5239 } else {
5240 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5241 file, linenum, args[0]);
5242 err_code |= ERR_ALERT | ERR_FATAL;
5243 goto out;
5244 }
5245 }
5246
5247 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5248 } else if (!strcmp(args[0], "user")) { /* new user */
5249 struct auth_users *newuser;
5250 int cur_arg;
5251
5252 if (!*args[1]) {
5253 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5254 file, linenum, args[0]);
5255 err_code |= ERR_ALERT | ERR_FATAL;
5256 goto out;
5257 }
5258
5259 for (newuser = userlist->users; newuser; newuser = newuser->next)
5260 if (!strcmp(newuser->user, args[1])) {
5261 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5262 file, linenum, args[1], userlist->name);
5263 err_code |= ERR_ALERT;
5264 goto out;
5265 }
5266
5267 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5268 if (!newuser) {
5269 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5270 err_code |= ERR_ALERT | ERR_ABORT;
5271 goto out;
5272 }
5273
5274 newuser->user = strdup(args[1]);
5275
5276 newuser->next = userlist->users;
5277 userlist->users = newuser;
5278
5279 cur_arg = 2;
5280
5281 while (*args[cur_arg]) {
5282 if (!strcmp(args[cur_arg], "password")) {
5283#ifndef CONFIG_HAP_CRYPT
5284 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5285 file, linenum);
5286 err_code |= ERR_ALERT;
5287#endif
5288 newuser->pass = strdup(args[cur_arg + 1]);
5289 cur_arg += 2;
5290 continue;
5291 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5292 newuser->pass = strdup(args[cur_arg + 1]);
5293 newuser->flags |= AU_O_INSECURE;
5294 cur_arg += 2;
5295 continue;
5296 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005297 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005298 cur_arg += 2;
5299 continue;
5300 } else {
5301 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5302 file, linenum, args[0]);
5303 err_code |= ERR_ALERT | ERR_FATAL;
5304 goto out;
5305 }
5306 }
5307 } else {
5308 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5309 err_code |= ERR_ALERT | ERR_FATAL;
5310 }
5311
5312out:
5313 return err_code;
5314}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005315
5316/*
5317 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005318 * Returns the error code, 0 if OK, or any combination of :
5319 * - ERR_ABORT: must abort ASAP
5320 * - ERR_FATAL: we can continue parsing but not start the service
5321 * - ERR_WARN: a warning has been emitted
5322 * - ERR_ALERT: an alert has been emitted
5323 * Only the two first ones can stop processing, the two others are just
5324 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005325 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005326int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005327{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005328 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005329 FILE *f;
5330 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005331 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005332 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333
Willy Tarreaubaaee002006-06-26 02:48:02 +02005334 if ((f=fopen(file,"r")) == NULL)
5335 return -1;
5336
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005337 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005338 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005339 char *end;
5340 char *args[MAX_LINE_ARGS + 1];
5341 char *line = thisline;
5342
Willy Tarreaubaaee002006-06-26 02:48:02 +02005343 linenum++;
5344
5345 end = line + strlen(line);
5346
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005347 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5348 /* Check if we reached the limit and the last char is not \n.
5349 * Watch out for the last line without the terminating '\n'!
5350 */
5351 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005352 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005353 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005354 }
5355
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005357 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005358 line++;
5359
5360 arg = 0;
5361 args[arg] = line;
5362
5363 while (*line && arg < MAX_LINE_ARGS) {
5364 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5365 * C equivalent value. Other combinations left unchanged (eg: \1).
5366 */
5367 if (*line == '\\') {
5368 int skip = 0;
5369 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5370 *line = line[1];
5371 skip = 1;
5372 }
5373 else if (line[1] == 'r') {
5374 *line = '\r';
5375 skip = 1;
5376 }
5377 else if (line[1] == 'n') {
5378 *line = '\n';
5379 skip = 1;
5380 }
5381 else if (line[1] == 't') {
5382 *line = '\t';
5383 skip = 1;
5384 }
5385 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005386 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005387 unsigned char hex1, hex2;
5388 hex1 = toupper(line[2]) - '0';
5389 hex2 = toupper(line[3]) - '0';
5390 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5391 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5392 *line = (hex1<<4) + hex2;
5393 skip = 3;
5394 }
5395 else {
5396 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005397 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005398 }
5399 }
5400 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005401 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005402 end -= skip;
5403 }
5404 line++;
5405 }
5406 else if (*line == '#' || *line == '\n' || *line == '\r') {
5407 /* end of string, end of loop */
5408 *line = 0;
5409 break;
5410 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005411 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005412 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005413 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005414 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005415 line++;
5416 args[++arg] = line;
5417 }
5418 else {
5419 line++;
5420 }
5421 }
5422
5423 /* empty line */
5424 if (!**args)
5425 continue;
5426
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005427 if (*line) {
5428 /* we had to stop due to too many args.
5429 * Let's terminate the string, print the offending part then cut the
5430 * last arg.
5431 */
5432 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5433 line++;
5434 *line = '\0';
5435
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005436 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005437 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005438 err_code |= ERR_ALERT | ERR_FATAL;
5439 args[arg] = line;
5440 }
5441
Willy Tarreau540abe42007-05-02 20:50:16 +02005442 /* zero out remaining args and ensure that at least one entry
5443 * is zeroed out.
5444 */
5445 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005446 args[arg] = line;
5447 }
5448
Willy Tarreau3842f002009-06-14 11:39:52 +02005449 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005450 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005451 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005452 for (arg=0; *args[arg+1]; arg++)
5453 args[arg] = args[arg+1]; // shift args after inversion
5454 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005455 else if (!strcmp(args[0], "default")) {
5456 kwm = KWM_DEF;
5457 for (arg=0; *args[arg+1]; arg++)
5458 args[arg] = args[arg+1]; // shift args after inversion
5459 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005460
Willy Tarreau3842f002009-06-14 11:39:52 +02005461 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5462 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005463 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005464 }
5465
Willy Tarreau977b8e42006-12-29 14:19:17 +01005466 if (!strcmp(args[0], "listen") ||
5467 !strcmp(args[0], "frontend") ||
5468 !strcmp(args[0], "backend") ||
5469 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005470 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005471 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005472 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005473 cursection = strdup(args[0]);
5474 }
5475 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005476 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005477 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005478 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005479 }
5480 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005481 confsect = CFG_USERLIST;
5482 free(cursection);
5483 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005484 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005485 else if (!strcmp(args[0], "peers")) {
5486 confsect = CFG_PEERS;
5487 free(cursection);
5488 cursection = strdup(args[0]);
5489 }
5490
Willy Tarreaubaaee002006-06-26 02:48:02 +02005491 /* else it's a section keyword */
5492
5493 switch (confsect) {
5494 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005495 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005496 break;
5497 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005498 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005500 case CFG_USERLIST:
5501 err_code |= cfg_parse_users(file, linenum, args, kwm);
5502 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005503 case CFG_PEERS:
5504 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5505 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005506 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005507 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005508 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005509 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005510
5511 if (err_code & ERR_ABORT)
5512 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005513 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005514 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005515 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005517 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005518}
5519
Willy Tarreaubb925012009-07-23 13:36:36 +02005520/*
5521 * Returns the error code, 0 if OK, or any combination of :
5522 * - ERR_ABORT: must abort ASAP
5523 * - ERR_FATAL: we can continue parsing but not start the service
5524 * - ERR_WARN: a warning has been emitted
5525 * - ERR_ALERT: an alert has been emitted
5526 * Only the two first ones can stop processing, the two others are just
5527 * indicators.
5528 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005529int check_config_validity()
5530{
5531 int cfgerr = 0;
5532 struct proxy *curproxy = NULL;
5533 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005534 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005535 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005536 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005537
5538 /*
5539 * Now, check for the integrity of all that we have collected.
5540 */
5541
5542 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005543 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005544
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005545 /* first, we will invert the proxy list order */
5546 curproxy = NULL;
5547 while (proxy) {
5548 struct proxy *next;
5549
5550 next = proxy->next;
5551 proxy->next = curproxy;
5552 curproxy = proxy;
5553 if (!next)
5554 break;
5555 proxy = next;
5556 }
5557
Willy Tarreaubaaee002006-06-26 02:48:02 +02005558 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005559 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005562 }
5563
5564 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005565 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005566 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005567 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005568 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005569 unsigned int next_id;
5570
5571 if (!curproxy->uuid) {
5572 /* proxy ID not set, use automatic numbering with first
5573 * spare entry starting with next_pxid.
5574 */
5575 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5576 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5577 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005578 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005579 next_pxid++;
5580
Willy Tarreau55ea7572007-06-17 19:56:27 +02005581
Willy Tarreaubaaee002006-06-26 02:48:02 +02005582 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005583 /* ensure we don't keep listeners uselessly bound */
5584 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005585 curproxy = curproxy->next;
5586 continue;
5587 }
5588
Willy Tarreauff01a212009-03-15 13:46:16 +01005589 switch (curproxy->mode) {
5590 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005591 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005592 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005593 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5594 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005595 cfgerr++;
5596 }
5597
5598 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005599 Warning("config : servers will be ignored for %s '%s'.\n",
5600 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005601 break;
5602
5603 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005604 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005605 break;
5606
5607 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005608 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005609 break;
5610 }
5611
5612 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005613 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5614 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 cfgerr++;
5616 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005617
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005618 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005619 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005620 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005621 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5622 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005623 cfgerr++;
5624 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005625#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005626 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005627 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5628 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005629 cfgerr++;
5630 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005631#endif
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005632 else if (curproxy->options2 & PR_O2_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005633 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5634 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005635 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005636 }
5637 }
5638 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005639 !(curproxy->options2 & PR_O2_DISPATCH)) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005640 /* If no LB algo is set in a backend, and we're not in
5641 * transparent mode, dispatch mode nor proxy mode, we
5642 * want to use balance roundrobin by default.
5643 */
5644 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5645 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005646 }
5647 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005648
Willy Tarreaud6cc5322011-03-04 17:30:54 +01005649 if (curproxy->options2 & PR_O2_DISPATCH) {
5650 curproxy->options &= ~PR_O_TRANSP;
5651 curproxy->options &= ~PR_O_HTTP_PROXY;
5652 }
5653 else if (curproxy->options & PR_O_HTTP_PROXY) {
5654 curproxy->options2 &= ~PR_O2_DISPATCH;
5655 curproxy->options &= ~PR_O_TRANSP;
5656 }
5657 else if (curproxy->options & PR_O_TRANSP) {
5658 curproxy->options2 &= ~PR_O2_DISPATCH;
5659 curproxy->options &= ~PR_O_HTTP_PROXY;
5660 }
5661
Willy Tarreau82936582007-11-30 15:20:09 +01005662 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5663 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005664 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5665 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005666 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005667 }
5668
Willy Tarreauef781042010-01-27 11:53:01 +01005669 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5670 curproxy->options &= ~PR_O2_CHK_SNDST;
5671 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5672 "send-state", proxy_type_str(curproxy), curproxy->id);
5673 err_code |= ERR_WARN;
5674 }
5675
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005676 /* if a default backend was specified, let's find it */
5677 if (curproxy->defbe.name) {
5678 struct proxy *target;
5679
Alex Williams96532db2009-11-01 21:27:13 -05005680 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005681 if (!target) {
5682 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5683 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005684 cfgerr++;
5685 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005686 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5687 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005688 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005689 } else {
5690 free(curproxy->defbe.name);
5691 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005692 /* we force the backend to be present on at least all of
5693 * the frontend's processes.
5694 */
5695 target->bind_proc = curproxy->bind_proc ?
5696 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005697 }
5698 }
5699
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005700 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005701 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5702 /* map jump target for ACT_SETBE in req_rep chain */
5703 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005704 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005705 struct proxy *target;
5706
Willy Tarreaua496b602006-12-17 23:15:24 +01005707 if (exp->action != ACT_SETBE)
5708 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005709
Alex Williams96532db2009-11-01 21:27:13 -05005710 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005711 if (!target) {
5712 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5713 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005714 cfgerr++;
5715 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005716 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5717 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005718 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005719 } else {
5720 free((void *)exp->replace);
5721 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005722 /* we force the backend to be present on at least all of
5723 * the frontend's processes.
5724 */
5725 target->bind_proc = curproxy->bind_proc ?
5726 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005727 }
5728 }
5729 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005730
5731 /* find the target proxy for 'use_backend' rules */
5732 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005733 struct proxy *target;
5734
Alex Williams96532db2009-11-01 21:27:13 -05005735 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005736
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005737 if (!target) {
5738 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5739 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005740 cfgerr++;
5741 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005742 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5743 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005744 cfgerr++;
5745 } else {
5746 free((void *)rule->be.name);
5747 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005748 /* we force the backend to be present on at least all of
5749 * the frontend's processes.
5750 */
5751 target->bind_proc = curproxy->bind_proc ?
5752 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005753 }
5754 }
5755
Emeric Brunb982a3d2010-01-04 15:45:53 +01005756 /* find the target table for 'stick' rules */
5757 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5758 struct proxy *target;
5759
Emeric Brun1d33b292010-01-04 15:47:17 +01005760 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5761 if (mrule->flags & STK_IS_STORE)
5762 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5763
Emeric Brunb982a3d2010-01-04 15:45:53 +01005764 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005765 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005766 else
5767 target = curproxy;
5768
5769 if (!target) {
5770 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5771 curproxy->id, mrule->table.name);
5772 cfgerr++;
5773 }
5774 else if (target->table.size == 0) {
5775 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5776 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5777 cfgerr++;
5778 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005779 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005780 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5781 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5782 cfgerr++;
5783 }
5784 else {
5785 free((void *)mrule->table.name);
5786 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005787 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005788 }
5789 }
5790
5791 /* find the target table for 'store response' rules */
5792 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5793 struct proxy *target;
5794
Emeric Brun1d33b292010-01-04 15:47:17 +01005795 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5796
Emeric Brunb982a3d2010-01-04 15:45:53 +01005797 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005798 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005799 else
5800 target = curproxy;
5801
5802 if (!target) {
5803 Alert("Proxy '%s': unable to find store table '%s'.\n",
5804 curproxy->id, mrule->table.name);
5805 cfgerr++;
5806 }
5807 else if (target->table.size == 0) {
5808 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5809 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5810 cfgerr++;
5811 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005812 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005813 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5814 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5815 cfgerr++;
5816 }
5817 else {
5818 free((void *)mrule->table.name);
5819 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005820 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005821 }
5822 }
5823
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005824 /* find the target table for 'tcp-request' layer 4 rules */
5825 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5826 struct proxy *target;
5827
Willy Tarreau56123282010-08-06 19:06:56 +02005828 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005829 continue;
5830
5831 if (trule->act_prm.trk_ctr.table.n)
5832 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5833 else
5834 target = curproxy;
5835
5836 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005837 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5838 curproxy->id, trule->act_prm.trk_ctr.table.n,
5839 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005840 cfgerr++;
5841 }
5842 else if (target->table.size == 0) {
5843 Alert("Proxy '%s': table '%s' used but not configured.\n",
5844 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5845 cfgerr++;
5846 }
5847 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005848 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 +02005849 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5850 cfgerr++;
5851 }
5852 else {
5853 free(trule->act_prm.trk_ctr.table.n);
5854 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005855 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005856 * to pass a list of counters to track and allocate them right here using
5857 * stktable_alloc_data_type().
5858 */
5859 }
5860 }
5861
Willy Tarreaud1f96522010-08-03 19:34:32 +02005862 /* find the target table for 'tcp-request' layer 6 rules */
5863 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5864 struct proxy *target;
5865
Willy Tarreau56123282010-08-06 19:06:56 +02005866 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005867 continue;
5868
5869 if (trule->act_prm.trk_ctr.table.n)
5870 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5871 else
5872 target = curproxy;
5873
5874 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005875 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5876 curproxy->id, trule->act_prm.trk_ctr.table.n,
5877 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005878 cfgerr++;
5879 }
5880 else if (target->table.size == 0) {
5881 Alert("Proxy '%s': table '%s' used but not configured.\n",
5882 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5883 cfgerr++;
5884 }
5885 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005886 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 +02005887 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5888 cfgerr++;
5889 }
5890 else {
5891 free(trule->act_prm.trk_ctr.table.n);
5892 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005893 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005894 * to pass a list of counters to track and allocate them right here using
5895 * stktable_alloc_data_type().
5896 */
5897 }
5898 }
5899
Emeric Brun32da3c42010-09-23 18:39:19 +02005900 if (curproxy->table.peers.name) {
5901 struct peers *curpeers = peers;
5902
5903 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5904 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5905 free((void *)curproxy->table.peers.name);
5906 curproxy->table.peers.p = peers;
5907 break;
5908 }
5909 }
5910
5911 if (!curpeers) {
5912 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5913 curproxy->id, curproxy->table.peers.name);
5914 cfgerr++;
5915 }
5916 else if (!curpeers->peers_fe) {
5917 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5918 curproxy->id, curpeers->id);
5919 cfgerr++;
5920 }
5921 }
5922
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005923 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005924 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005925 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5926 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5927 "proxy", curproxy->id);
5928 cfgerr++;
5929 goto out_uri_auth_compat;
5930 }
5931
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005932 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005933 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005934 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005935 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005936
Willy Tarreau95fa4692010-02-01 13:05:50 +01005937 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5938 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005939
5940 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005941 uri_auth_compat_req[i++] = "realm";
5942 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5943 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005944
Willy Tarreau95fa4692010-02-01 13:05:50 +01005945 uri_auth_compat_req[i++] = "unless";
5946 uri_auth_compat_req[i++] = "{";
5947 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5948 uri_auth_compat_req[i++] = "}";
5949 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005950
Willy Tarreauff011f22011-01-06 17:51:27 +01005951 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5952 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005953 cfgerr++;
5954 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005955 }
5956
Willy Tarreauff011f22011-01-06 17:51:27 +01005957 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005958
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005959 if (curproxy->uri_auth->auth_realm) {
5960 free(curproxy->uri_auth->auth_realm);
5961 curproxy->uri_auth->auth_realm = NULL;
5962 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005963
5964 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005965 }
5966out_uri_auth_compat:
5967
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005968 cfgerr += acl_find_targets(curproxy);
5969
Willy Tarreau2738a142006-07-08 17:28:09 +02005970 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005971 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005972 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005973 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005974 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005975 " | While not properly invalid, you will certainly encounter various problems\n"
5976 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005977 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005978 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005979 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005980 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005981
Willy Tarreau1fa31262007-12-03 00:36:16 +01005982 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5983 * We must still support older configurations, so let's find out whether those
5984 * parameters have been set or must be copied from contimeouts.
5985 */
5986 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005987 if (!curproxy->timeout.tarpit ||
5988 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005989 /* tarpit timeout not set. We search in the following order:
5990 * default.tarpit, curr.connect, default.connect.
5991 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005992 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005993 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005994 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005995 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005996 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005997 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005998 }
5999 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006000 (!curproxy->timeout.queue ||
6001 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006002 /* queue timeout not set. We search in the following order:
6003 * default.queue, curr.connect, default.connect.
6004 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006005 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006006 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006007 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006008 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006009 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006010 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006011 }
6012 }
6013
Willy Tarreau07a54902010-03-29 18:33:29 +02006014 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006015 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6016 curproxy->check_req = (char *)malloc(curproxy->check_len);
6017 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006018 }
6019
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006020 /* The small pools required for the capture lists */
6021 if (curproxy->nb_req_cap)
6022 curproxy->req_cap_pool = create_pool("ptrcap",
6023 curproxy->nb_req_cap * sizeof(char *),
6024 MEM_F_SHARED);
6025 if (curproxy->nb_rsp_cap)
6026 curproxy->rsp_cap_pool = create_pool("ptrcap",
6027 curproxy->nb_rsp_cap * sizeof(char *),
6028 MEM_F_SHARED);
6029
Willy Tarreau1d4154a2007-05-13 22:57:02 +02006030 curproxy->hdr_idx_pool = create_pool("hdr_idx",
6031 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6032 MEM_F_SHARED);
6033
Willy Tarreaubaaee002006-06-26 02:48:02 +02006034 /* first, we will invert the servers list order */
6035 newsrv = NULL;
6036 while (curproxy->srv) {
6037 struct server *next;
6038
6039 next = curproxy->srv->next;
6040 curproxy->srv->next = newsrv;
6041 newsrv = curproxy->srv;
6042 if (!next)
6043 break;
6044 curproxy->srv = next;
6045 }
6046
Willy Tarreaudd701652010-05-25 23:03:02 +02006047 /* assign automatic UIDs to servers which don't have one yet */
6048 next_id = 1;
6049 newsrv = curproxy->srv;
6050 while (newsrv != NULL) {
6051 if (!newsrv->puid) {
6052 /* server ID not set, use automatic numbering with first
6053 * spare entry starting with next_svid.
6054 */
6055 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6056 newsrv->conf.id.key = newsrv->puid = next_id;
6057 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6058 }
6059 next_id++;
6060 newsrv = newsrv->next;
6061 }
6062
Willy Tarreau20697042007-11-15 23:26:18 +01006063 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006064 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006065
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006066 /* We have to initialize the server lookup mechanism depending
6067 * on what LB algorithm was choosen.
6068 */
6069
6070 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6071 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6072 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006073 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6074 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6075 init_server_map(curproxy);
6076 } else {
6077 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6078 fwrr_init_server_groups(curproxy);
6079 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006080 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006081
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006082 case BE_LB_KIND_LC:
6083 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006084 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006085 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006086
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006087 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006088 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6089 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6090 chash_init_server_tree(curproxy);
6091 } else {
6092 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6093 init_server_map(curproxy);
6094 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006095 break;
6096 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006097
6098 if (curproxy->options & PR_O_LOGASAP)
6099 curproxy->to_log &= ~LW_BYTES;
6100
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006101 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6102 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6103 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6104 proxy_type_str(curproxy), curproxy->id);
6105 err_code |= ERR_WARN;
6106 }
6107
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006108 if (curproxy->mode != PR_MODE_HTTP) {
6109 int optnum;
6110
6111 if (curproxy->options & PR_O_COOK_ANY) {
6112 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6113 proxy_type_str(curproxy), curproxy->id);
6114 err_code |= ERR_WARN;
6115 }
6116
6117 if (curproxy->uri_auth) {
6118 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6119 proxy_type_str(curproxy), curproxy->id);
6120 err_code |= ERR_WARN;
6121 curproxy->uri_auth = NULL;
6122 }
6123
6124 if (curproxy->options & PR_O_FWDFOR) {
6125 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6126 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6127 err_code |= ERR_WARN;
6128 curproxy->options &= ~PR_O_FWDFOR;
6129 }
6130
6131 if (curproxy->options & PR_O_ORGTO) {
6132 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6133 "originalto", proxy_type_str(curproxy), curproxy->id);
6134 err_code |= ERR_WARN;
6135 curproxy->options &= ~PR_O_ORGTO;
6136 }
6137
6138 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6139 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6140 (curproxy->cap & cfg_opts[optnum].cap) &&
6141 (curproxy->options & cfg_opts[optnum].val)) {
6142 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6143 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6144 err_code |= ERR_WARN;
6145 curproxy->options &= ~cfg_opts[optnum].val;
6146 }
6147 }
6148
6149 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6150 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6151 (curproxy->cap & cfg_opts2[optnum].cap) &&
6152 (curproxy->options2 & cfg_opts2[optnum].val)) {
6153 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6154 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6155 err_code |= ERR_WARN;
6156 curproxy->options2 &= ~cfg_opts2[optnum].val;
6157 }
6158 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006159
Willy Tarreauefa5f512010-03-30 20:13:29 +02006160#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006161 if (curproxy->bind_hdr_occ) {
6162 curproxy->bind_hdr_occ = 0;
6163 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6164 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6165 err_code |= ERR_WARN;
6166 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006167#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006168 }
6169
Willy Tarreaubaaee002006-06-26 02:48:02 +02006170 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006171 * ensure that we're not cross-dressing a TCP server into HTTP.
6172 */
6173 newsrv = curproxy->srv;
6174 while (newsrv != NULL) {
6175 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006176 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6177 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006178 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006179 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006180
Willy Tarreauefa5f512010-03-30 20:13:29 +02006181#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006182 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6183 newsrv->bind_hdr_occ = 0;
6184 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6185 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6186 err_code |= ERR_WARN;
6187 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006188#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006189 newsrv = newsrv->next;
6190 }
6191
6192 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006193 * If this server supports a maxconn parameter, it needs a dedicated
6194 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006195 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006196 */
6197 newsrv = curproxy->srv;
6198 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006199 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006200 /* Only 'minconn' was specified, or it was higher than or equal
6201 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6202 * this will avoid further useless expensive computations.
6203 */
6204 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006205 } else if (newsrv->maxconn && !newsrv->minconn) {
6206 /* minconn was not specified, so we set it to maxconn */
6207 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006208 }
6209
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006210 if (newsrv->trackit) {
6211 struct proxy *px;
6212 struct server *srv;
6213 char *pname, *sname;
6214
6215 pname = newsrv->trackit;
6216 sname = strrchr(pname, '/');
6217
6218 if (sname)
6219 *sname++ = '\0';
6220 else {
6221 sname = pname;
6222 pname = NULL;
6223 }
6224
6225 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006226 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006227 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006228 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6229 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006230 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006231 cfgerr++;
6232 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006233 }
6234 } else
6235 px = curproxy;
6236
6237 srv = findserver(px, sname);
6238 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006239 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6240 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006241 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006242 cfgerr++;
6243 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006244 }
6245
6246 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006247 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006248 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006249 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006250 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006251 cfgerr++;
6252 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006253 }
6254
6255 if (curproxy != px &&
6256 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006257 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006258 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006259 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006260 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006261 cfgerr++;
6262 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006263 }
6264
6265 newsrv->tracked = srv;
6266 newsrv->tracknext = srv->tracknext;
6267 srv->tracknext = newsrv;
6268
6269 free(newsrv->trackit);
6270 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006271 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006272 newsrv = newsrv->next;
6273 }
6274
Willy Tarreauc1a21672009-08-16 22:37:44 +02006275 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006276 curproxy->accept = frontend_accept;
6277
Willy Tarreauc1a21672009-08-16 22:37:44 +02006278 if (curproxy->tcp_req.inspect_delay ||
6279 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006280 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006281
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006282 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006283 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006284 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006285 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006286
6287 /* both TCP and HTTP must check switching rules */
6288 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6289 }
6290
6291 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006292 if (curproxy->tcp_req.inspect_delay ||
6293 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6294 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6295
Emeric Brun97679e72010-09-23 17:56:44 +02006296 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6297 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6298
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006299 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006300 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006301 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006302 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006303
6304 /* If the backend does requires RDP cookie persistence, we have to
6305 * enable the corresponding analyser.
6306 */
6307 if (curproxy->options2 & PR_O2_RDPC_PRST)
6308 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6309 }
6310
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006311 listener = NULL;
6312 while (curproxy->listen) {
6313 struct listener *next;
6314
6315 next = curproxy->listen->next;
6316 curproxy->listen->next = listener;
6317 listener = curproxy->listen;
6318
6319 if (!next)
6320 break;
6321
6322 curproxy->listen = next;
6323 }
6324
Willy Tarreaue6b98942007-10-29 01:09:36 +01006325 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006326 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006327 listener = curproxy->listen;
6328 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006329 if (!listener->luid) {
6330 /* listener ID not set, use automatic numbering with first
6331 * spare entry starting with next_luid.
6332 */
6333 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6334 listener->conf.id.key = listener->luid = next_id;
6335 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006336 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006337 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006338
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006339 /* enable separate counters */
6340 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6341 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6342 if (!listener->name) {
6343 sprintf(trash, "sock-%d", listener->luid);
6344 listener->name = strdup(trash);
6345 }
6346 }
6347
Willy Tarreaue6b98942007-10-29 01:09:36 +01006348 if (curproxy->options & PR_O_TCP_NOLING)
6349 listener->options |= LI_O_NOLINGER;
6350 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006351 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006352 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006353 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006354 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006355 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006356 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006357
Willy Tarreau8a956912010-10-15 14:27:08 +02006358 if (listener->options & LI_O_ACC_PROXY)
6359 listener->analysers |= AN_REQ_DECODE_PROXY;
6360
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006361 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6362 listener->options |= LI_O_TCP_RULES;
6363
Willy Tarreaude3041d2010-05-31 10:56:17 +02006364 if (curproxy->mon_mask.s_addr)
6365 listener->options |= LI_O_CHK_MONNET;
6366
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006367 /* smart accept mode is automatic in HTTP mode */
6368 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6369 (curproxy->mode == PR_MODE_HTTP &&
6370 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6371 listener->options |= LI_O_NOQUICKACK;
6372
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006373 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006374 listener = listener->next;
6375 }
6376
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006377 /* Check multi-process mode compatibility for the current proxy */
6378 if (global.nbproc > 1) {
6379 int nbproc = 0;
6380 if (curproxy->bind_proc) {
6381 int proc;
6382 for (proc = 0; proc < global.nbproc; proc++) {
6383 if (curproxy->bind_proc & (1 << proc)) {
6384 nbproc++;
6385 }
6386 }
6387 } else {
6388 nbproc = global.nbproc;
6389 }
6390 if (curproxy->table.peers.name) {
6391 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6392 curproxy->id);
6393 cfgerr++;
6394 }
6395 if (nbproc > 1) {
6396 if (curproxy->uri_auth) {
6397 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6398 curproxy->id);
6399 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6400 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6401 curproxy->id);
6402 }
6403 }
6404 if (curproxy->appsession_name) {
6405 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6406 curproxy->id);
6407 }
6408 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6409 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6410 curproxy->id);
6411 }
6412 }
6413 }
6414
Willy Tarreaubaaee002006-06-26 02:48:02 +02006415 curproxy = curproxy->next;
6416 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006417
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006418 /* Check multi-process mode compatibility */
6419 if (global.nbproc > 1) {
6420 if (global.stats_fe) {
6421 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6422 }
6423 }
6424
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006425 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6426 struct auth_users *curuser;
6427 int g;
6428
6429 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6430 unsigned int group_mask = 0;
6431 char *group = NULL;
6432
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006433 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006434 continue;
6435
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006436 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006437
6438 for (g = 0; g < curuserlist->grpcnt; g++)
6439 if (!strcmp(curuserlist->groups[g], group))
6440 break;
6441
6442 if (g == curuserlist->grpcnt) {
6443 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6444 curuserlist->name, group, curuser->user);
6445 err_code |= ERR_ALERT | ERR_FATAL;
6446 goto out;
6447 }
6448
6449 group_mask |= (1 << g);
6450 }
6451
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006452 free(curuser->u.groups);
6453 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006454 }
6455
6456 for (g = 0; g < curuserlist->grpcnt; g++) {
6457 char *user = NULL;
6458
6459 if (!curuserlist->groupusers[g])
6460 continue;
6461
6462 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6463 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6464 if (!strcmp(curuser->user, user))
6465 break;
6466
6467 if (!curuser) {
6468 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6469 curuserlist->name, user, curuserlist->groups[g]);
6470 err_code |= ERR_ALERT | ERR_FATAL;
6471 goto out;
6472 }
6473
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006474 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006475 }
6476
6477 free(curuserlist->groupusers[g]);
6478 }
6479
6480 free(curuserlist->groupusers);
6481
6482#ifdef DEBUG_AUTH
6483 for (g = 0; g < curuserlist->grpcnt; g++) {
6484 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6485
6486 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6487 if (curuser->group_mask & (1 << g))
6488 fprintf(stderr, " %s", curuser->user);
6489 }
6490
6491 fprintf(stderr, "\n");
6492 }
6493#endif
6494
Willy Tarreaufbb78422011-06-05 15:38:35 +02006495 }
6496
6497 /* automatically compute fullconn if not set. We must not do it in the
6498 * loop above because cross-references are not yet fully resolved.
6499 */
6500 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6501 /* If <fullconn> is not set, let's set it to 10% of the sum of
6502 * the possible incoming frontend's maxconns.
6503 */
6504 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6505 struct proxy *fe;
6506 int total = 0;
6507
6508 /* sum up the number of maxconns of frontends which
6509 * reference this backend at least once or which are
6510 * the same one ('listen').
6511 */
6512 for (fe = proxy; fe; fe = fe->next) {
6513 struct switching_rule *rule;
6514 struct hdr_exp *exp;
6515 int found = 0;
6516
6517 if (!(fe->cap & PR_CAP_FE))
6518 continue;
6519
6520 if (fe == curproxy) /* we're on a "listen" instance */
6521 found = 1;
6522
6523 if (fe->defbe.be == curproxy) /* "default_backend" */
6524 found = 1;
6525
6526 /* check if a "use_backend" rule matches */
6527 if (!found) {
6528 list_for_each_entry(rule, &fe->switching_rules, list) {
6529 if (rule->be.backend == curproxy) {
6530 found = 1;
6531 break;
6532 }
6533 }
6534 }
6535
6536 /* check if a "reqsetbe" rule matches */
6537 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6538 if (exp->action == ACT_SETBE &&
6539 (struct proxy *)exp->replace == curproxy) {
6540 found = 1;
6541 break;
6542 }
6543 }
6544
6545 /* now we've checked all possible ways to reference a backend
6546 * from a frontend.
6547 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006548 if (!found)
6549 continue;
6550 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006551 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006552 /* we have the sum of the maxconns in <total>. We only
6553 * keep 10% of that sum to set the default fullconn, with
6554 * a hard minimum of 1 (to avoid a divide by zero).
6555 */
6556 curproxy->fullconn = (total + 9) / 10;
6557 if (!curproxy->fullconn)
6558 curproxy->fullconn = 1;
6559 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006560 }
6561
Willy Tarreau056f5682010-06-06 15:51:11 +02006562 /* initialize stick-tables on backend capable proxies. This must not
6563 * be done earlier because the data size may be discovered while parsing
6564 * other proxies.
6565 */
6566 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006567 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006568
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006569 /*
6570 * Recount currently required checks.
6571 */
6572
6573 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6574 int optnum;
6575
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006576 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6577 if (curproxy->options & cfg_opts[optnum].val)
6578 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006579
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006580 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6581 if (curproxy->options2 & cfg_opts2[optnum].val)
6582 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006583 }
6584
Willy Tarreaubb925012009-07-23 13:36:36 +02006585 if (cfgerr > 0)
6586 err_code |= ERR_ALERT | ERR_FATAL;
6587 out:
6588 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006589}
6590
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006591/*
6592 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6593 * parsing sessions.
6594 */
6595void cfg_register_keywords(struct cfg_kw_list *kwl)
6596{
6597 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6598}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006599
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006600/*
6601 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6602 */
6603void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6604{
6605 LIST_DEL(&kwl->list);
6606 LIST_INIT(&kwl->list);
6607}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006608
6609/*
6610 * Local variables:
6611 * c-indent-level: 8
6612 * c-basic-offset: 8
6613 * End:
6614 */