blob: 39a289af36f24a71dd8e030eff3a5e77591770fa [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020047#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020048#include <proto/lb_fwlc.h>
49#include <proto/lb_fwrr.h>
50#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010052#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020053#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010054#include <proto/protocols.h>
55#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020056#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010057#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010058#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020059#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010061#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010063#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064
65
Willy Tarreauf3c69202006-07-09 16:42:34 +020066/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
67 * ssl-hello-chk option to ensure that the remote server speaks SSL.
68 *
69 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
70 */
71const char sslv3_client_hello_pkt[] = {
72 "\x16" /* ContentType : 0x16 = Hanshake */
73 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
74 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
75 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
76 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
77 "\x03\x00" /* Hello Version : 0x0300 = v3 */
78 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
79 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
80 "\x00" /* Session ID length : empty (no session ID) */
81 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
82 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
83 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
84 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
85 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
86 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
87 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
88 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
89 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
90 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
91 "\x00\x38" "\x00\x39" "\x00\x3A"
92 "\x01" /* Compression Length : 0x01 = 1 byte for types */
93 "\x00" /* Compression Type : 0x00 = NULL compression */
94};
95
Willy Tarreau3842f002009-06-14 11:39:52 +020096/* various keyword modifiers */
97enum kw_mod {
98 KWM_STD = 0, /* normal */
99 KWM_NO, /* "no" prefixed before the keyword */
100 KWM_DEF, /* "default" prefixed before the keyword */
101};
102
Willy Tarreau13943ab2006-12-31 00:24:10 +0100103/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100104struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100105 const char *name;
106 unsigned int val;
107 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100108 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100109 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100110};
111
112/* proxy->options */
113static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100115 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
116 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
117 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
118 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
119 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
120 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
121 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
122 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
125 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
127 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
128 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
129 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
130 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100131#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100132 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100133#else
134 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100135#endif
136
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100137 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138};
139
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140/* proxy->options2 */
141static const struct cfg_opt cfg_opts2[] =
142{
143#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
145 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100147#else
148 { "splice-request", 0, 0, 0, 0 },
149 { "splice-response", 0, 0, 0, 0 },
150 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
153 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
154 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
155 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
156 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
157 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
158 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
160 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
161 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200162 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200163 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100164 { NULL, 0, 0, 0 }
165};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166
Willy Tarreau6daf3432008-01-22 16:44:08 +0100167static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
169int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100170int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200172/* List head of all known configuration keywords */
173static struct cfg_kw_list cfg_keywords = {
174 .list = LIST_HEAD_INIT(cfg_keywords.list)
175};
176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177/*
178 * converts <str> to a list of listeners which are dynamically allocated.
179 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
180 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
181 * - <port> is a numerical port from 1 to 65535 ;
182 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
183 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200184 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100186static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187{
188 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100189 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200190 int port, end;
191
192 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 while (next && *next) {
195 struct sockaddr_storage ss;
196
197 str = next;
198 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100199 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 *next++ = 0;
201 }
202
Emeric Bruned760922010-10-22 17:59:25 +0200203 if (*str == '/') {
204 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
205 /* so compute max path */
206 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
207 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
Emeric Bruned760922010-10-22 17:59:25 +0200209 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100210 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
211 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200212 goto fail;
213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200216 ss.ss_family = AF_UNIX;
217 if (global.unix_bind.prefix) {
218 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
219 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 }
Emeric Bruned760922010-10-22 17:59:25 +0200221 else {
222 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
223 }
224 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 }
226 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100227 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100229 ss2 = str2sa_range(str, &port, &end);
230 if (!ss2) {
231 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
232 file, line, str);
233 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 if (!port) {
237 Alert("parsing [%s:%d] : missing port number: '%s'\n",
238 file, line, str);
239 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 /* OK the address looks correct */
243 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Emeric Bruned760922010-10-22 17:59:25 +0200245 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100246 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
247 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200248 goto fail;
249 }
250
251 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100252 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
253 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200254 goto fail;
255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256 }
257
258 for (; port <= end; port++) {
259 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200260 l->next = curproxy->listen;
261 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
263 l->fd = -1;
264 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100265 l->state = LI_INIT;
266
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100267 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100269 tcpv4_add_listener(l);
270 }
Emeric Bruned760922010-10-22 17:59:25 +0200271 else if (ss.ss_family == AF_INET6) {
272 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
273 tcpv6_add_listener(l);
274 }
275 else {
276 l->perm.ux.gid = l->perm.ux.uid = -1;
277 l->perm.ux.mode = 0;
278 uxst_add_listener(l);
279 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200280
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200281 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100282 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283 } /* end for(port) */
284 } /* end while(next) */
285 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200286 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200287 fail:
288 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200289 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290}
291
Willy Tarreau977b8e42006-12-29 14:19:17 +0100292/*
293 * Sends a warning if proxy <proxy> does not have at least one of the
294 * capabilities in <cap>. An optionnal <hint> may be added at the end
295 * of the warning to help the user. Returns 1 if a warning was emitted
296 * or 0 if the condition is valid.
297 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100298int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299{
300 char *msg;
301
302 switch (cap) {
303 case PR_CAP_BE: msg = "no backend"; break;
304 case PR_CAP_FE: msg = "no frontend"; break;
305 case PR_CAP_RS: msg = "no ruleset"; break;
306 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
307 default: msg = "not enough"; break;
308 }
309
310 if (!(proxy->cap & cap)) {
311 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100312 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100313 return 1;
314 }
315 return 0;
316}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317
Willy Tarreau61d18892009-03-31 10:49:21 +0200318/* Report a warning if a rule is placed after a 'block' rule.
319 * Return 1 if the warning has been emitted, otherwise 0.
320 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100321int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200322{
323 if (!LIST_ISEMPTY(&proxy->block_cond)) {
324 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
325 file, line, arg);
326 return 1;
327 }
328 return 0;
329}
330
331/* Report a warning if a rule is placed after a reqrewrite rule.
332 * Return 1 if the warning has been emitted, otherwise 0.
333 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100334int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200335{
336 if (proxy->req_exp) {
337 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
338 file, line, arg);
339 return 1;
340 }
341 return 0;
342}
343
344/* Report a warning if a rule is placed after a reqadd rule.
345 * Return 1 if the warning has been emitted, otherwise 0.
346 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100347int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200348{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100349 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200350 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
351 file, line, arg);
352 return 1;
353 }
354 return 0;
355}
356
357/* Report a warning if a rule is placed after a redirect rule.
358 * Return 1 if the warning has been emitted, otherwise 0.
359 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100360int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200361{
362 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
363 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
364 file, line, arg);
365 return 1;
366 }
367 return 0;
368}
369
370/* Report a warning if a rule is placed after a 'use_backend' rule.
371 * Return 1 if the warning has been emitted, otherwise 0.
372 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100373int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200374{
375 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
376 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
377 file, line, arg);
378 return 1;
379 }
380 return 0;
381}
382
383/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
387 warnif_rule_after_reqadd(proxy, file, line, arg) ||
388 warnif_rule_after_redirect(proxy, file, line, arg) ||
389 warnif_rule_after_use_backend(proxy, file, line, arg);
390}
391
392/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
395 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
396 warnif_rule_after_redirect(proxy, file, line, arg) ||
397 warnif_rule_after_use_backend(proxy, file, line, arg);
398}
399
400/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 return warnif_rule_after_redirect(proxy, file, line, arg) ||
404 warnif_rule_after_use_backend(proxy, file, line, arg);
405}
406
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100407/* Report it if a request ACL condition uses some response-only parameters. It
408 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
409 * Note that <cond> may be NULL and then will be ignored.
410 */
411static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
412{
413 struct acl *acl;
414
415 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
416 return 0;
417
418 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
419 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
420 file, line, acl ? acl->name : "(unknown)");
421 return ERR_WARN;
422}
423
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100424/* Report it if a request ACL condition uses some request-only volatile parameters.
425 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
426 * Note that <cond> may be NULL and then will be ignored.
427 */
428static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
429{
430 struct acl *acl;
431
432 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
433 return 0;
434
435 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
436 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
437 file, line, acl ? acl->name : "(unknown)");
438 return ERR_WARN;
439}
440
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100441
Willy Tarreaubaaee002006-06-26 02:48:02 +0200442/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 * parse a line in a <global> section. Returns the error code, 0 if OK, or
444 * any combination of :
445 * - ERR_ABORT: must abort ASAP
446 * - ERR_FATAL: we can continue parsing but not start the service
447 * - ERR_WARN: a warning has been emitted
448 * - ERR_ALERT: an alert has been emitted
449 * Only the two first ones can stop processing, the two others are just
450 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200451 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200452int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453{
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455
456 if (!strcmp(args[0], "global")) { /* new section */
457 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200459 }
460 else if (!strcmp(args[0], "daemon")) {
461 global.mode |= MODE_DAEMON;
462 }
463 else if (!strcmp(args[0], "debug")) {
464 global.mode |= MODE_DEBUG;
465 }
466 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100467 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200469 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100470 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200471 }
472 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100473 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100476 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200477 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100478 else if (!strcmp(args[0], "nosplice")) {
479 global.tune.options &= ~GTUNE_USE_SPLICE;
480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481 else if (!strcmp(args[0], "quiet")) {
482 global.mode |= MODE_QUIET;
483 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200484 else if (!strcmp(args[0], "tune.maxpollevents")) {
485 if (global.tune.maxpollevents != 0) {
486 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200487 err_code |= ERR_ALERT;
488 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200489 }
490 if (*(args[1]) == 0) {
491 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200492 err_code |= ERR_ALERT | ERR_FATAL;
493 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200494 }
495 global.tune.maxpollevents = atol(args[1]);
496 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100497 else if (!strcmp(args[0], "tune.maxaccept")) {
498 if (global.tune.maxaccept != 0) {
499 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200500 err_code |= ERR_ALERT;
501 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100502 }
503 if (*(args[1]) == 0) {
504 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100507 }
508 global.tune.maxaccept = atol(args[1]);
509 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200510 else if (!strcmp(args[0], "tune.chksize")) {
511 if (*(args[1]) == 0) {
512 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
513 err_code |= ERR_ALERT | ERR_FATAL;
514 goto out;
515 }
516 global.tune.chksize = atol(args[1]);
517 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200518 else if (!strcmp(args[0], "tune.bufsize")) {
519 if (*(args[1]) == 0) {
520 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT | ERR_FATAL;
522 goto out;
523 }
524 global.tune.bufsize = atol(args[1]);
525 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
526 global.tune.maxrewrite = global.tune.bufsize / 2;
527 }
528 else if (!strcmp(args[0], "tune.maxrewrite")) {
529 if (*(args[1]) == 0) {
530 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
531 err_code |= ERR_ALERT | ERR_FATAL;
532 goto out;
533 }
534 global.tune.maxrewrite = atol(args[1]);
535 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
536 global.tune.maxrewrite = global.tune.bufsize / 2;
537 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100538 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
539 if (global.tune.client_rcvbuf != 0) {
540 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
541 err_code |= ERR_ALERT;
542 goto out;
543 }
544 if (*(args[1]) == 0) {
545 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
546 err_code |= ERR_ALERT | ERR_FATAL;
547 goto out;
548 }
549 global.tune.client_rcvbuf = atol(args[1]);
550 }
551 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
552 if (global.tune.server_rcvbuf != 0) {
553 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT;
555 goto out;
556 }
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.server_rcvbuf = atol(args[1]);
563 }
564 else if (!strcmp(args[0], "tune.sndbuf.client")) {
565 if (global.tune.client_sndbuf != 0) {
566 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
567 err_code |= ERR_ALERT;
568 goto out;
569 }
570 if (*(args[1]) == 0) {
571 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
572 err_code |= ERR_ALERT | ERR_FATAL;
573 goto out;
574 }
575 global.tune.client_sndbuf = atol(args[1]);
576 }
577 else if (!strcmp(args[0], "tune.sndbuf.server")) {
578 if (global.tune.server_sndbuf != 0) {
579 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT;
581 goto out;
582 }
583 if (*(args[1]) == 0) {
584 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
585 err_code |= ERR_ALERT | ERR_FATAL;
586 goto out;
587 }
588 global.tune.server_sndbuf = atol(args[1]);
589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 else if (!strcmp(args[0], "uid")) {
591 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200592 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200593 err_code |= ERR_ALERT;
594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
596 if (*(args[1]) == 0) {
597 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200598 err_code |= ERR_ALERT | ERR_FATAL;
599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 }
601 global.uid = atol(args[1]);
602 }
603 else if (!strcmp(args[0], "gid")) {
604 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200605 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200606 err_code |= ERR_ALERT;
607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 }
609 if (*(args[1]) == 0) {
610 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200611 err_code |= ERR_ALERT | ERR_FATAL;
612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 }
614 global.gid = atol(args[1]);
615 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200616 /* user/group name handling */
617 else if (!strcmp(args[0], "user")) {
618 struct passwd *ha_user;
619 if (global.uid != 0) {
620 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
622 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200623 }
624 errno = 0;
625 ha_user = getpwnam(args[1]);
626 if (ha_user != NULL) {
627 global.uid = (int)ha_user->pw_uid;
628 }
629 else {
630 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200631 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200632 }
633 }
634 else if (!strcmp(args[0], "group")) {
635 struct group *ha_group;
636 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200637 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200638 err_code |= ERR_ALERT;
639 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200640 }
641 errno = 0;
642 ha_group = getgrnam(args[1]);
643 if (ha_group != NULL) {
644 global.gid = (int)ha_group->gr_gid;
645 }
646 else {
647 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200648 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200649 }
650 }
651 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 else if (!strcmp(args[0], "nbproc")) {
653 if (global.nbproc != 0) {
654 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200655 err_code |= ERR_ALERT;
656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 }
658 if (*(args[1]) == 0) {
659 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT | ERR_FATAL;
661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 }
663 global.nbproc = atol(args[1]);
664 }
665 else if (!strcmp(args[0], "maxconn")) {
666 if (global.maxconn != 0) {
667 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200668 err_code |= ERR_ALERT;
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 }
671 if (*(args[1]) == 0) {
672 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT | ERR_FATAL;
674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 }
676 global.maxconn = atol(args[1]);
677#ifdef SYSTEM_MAXCONN
678 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
679 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
680 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200681 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
683#endif /* SYSTEM_MAXCONN */
684 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200685 else if (!strcmp(args[0], "maxconnrate")) {
686 if (global.cps_lim != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT;
689 goto out;
690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
695 }
696 global.cps_lim = atol(args[1]);
697 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100698 else if (!strcmp(args[0], "maxpipes")) {
699 if (global.maxpipes != 0) {
700 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT;
702 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100703 }
704 if (*(args[1]) == 0) {
705 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100708 }
709 global.maxpipes = atol(args[1]);
710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 else if (!strcmp(args[0], "ulimit-n")) {
712 if (global.rlimit_nofile != 0) {
713 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200714 err_code |= ERR_ALERT;
715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716 }
717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722 global.rlimit_nofile = atol(args[1]);
723 }
724 else if (!strcmp(args[0], "chroot")) {
725 if (global.chroot != NULL) {
726 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200727 err_code |= ERR_ALERT;
728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729 }
730 if (*(args[1]) == 0) {
731 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200734 }
735 global.chroot = strdup(args[1]);
736 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200737 else if (!strcmp(args[0], "description")) {
738 int i, len=0;
739 char *d;
740
741 if (!*args[1]) {
742 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
743 file, linenum, args[0]);
744 err_code |= ERR_ALERT | ERR_FATAL;
745 goto out;
746 }
747
748 for(i=1; *args[i]; i++)
749 len += strlen(args[i])+1;
750
751 if (global.desc)
752 free(global.desc);
753
754 global.desc = d = (char *)calloc(1, len);
755
756 d += sprintf(d, "%s", args[1]);
757 for(i=2; *args[i]; i++)
758 d += sprintf(d, " %s", args[i]);
759 }
760 else if (!strcmp(args[0], "node")) {
761 int i;
762 char c;
763
764 for (i=0; args[1][i]; i++) {
765 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100766 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
767 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200768 break;
769 }
770
771 if (!i || args[1][i]) {
772 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
773 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
774 file, linenum, args[0]);
775 err_code |= ERR_ALERT | ERR_FATAL;
776 goto out;
777 }
778
779 if (global.node)
780 free(global.node);
781
782 global.node = strdup(args[1]);
783 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784 else if (!strcmp(args[0], "pidfile")) {
785 if (global.pidfile != NULL) {
786 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200787 err_code |= ERR_ALERT;
788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789 }
790 if (*(args[1]) == 0) {
791 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200794 }
795 global.pidfile = strdup(args[1]);
796 }
Emeric Bruned760922010-10-22 17:59:25 +0200797 else if (!strcmp(args[0], "unix-bind")) {
798 int cur_arg = 1;
799 while (*(args[cur_arg])) {
800 if (!strcmp(args[cur_arg], "prefix")) {
801 if (global.unix_bind.prefix != NULL) {
802 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
803 err_code |= ERR_ALERT;
804 cur_arg += 2;
805 continue;
806 }
807
808 if (*(args[cur_arg+1]) == 0) {
809 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
810 err_code |= ERR_ALERT | ERR_FATAL;
811 goto out;
812 }
813 global.unix_bind.prefix = strdup(args[cur_arg+1]);
814 cur_arg += 2;
815 continue;
816 }
817
818 if (!strcmp(args[cur_arg], "mode")) {
819
820 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
821 cur_arg += 2;
822 continue;
823 }
824
825 if (!strcmp(args[cur_arg], "uid")) {
826
827 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
828 cur_arg += 2;
829 continue;
830 }
831
832 if (!strcmp(args[cur_arg], "gid")) {
833
834 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
835 cur_arg += 2;
836 continue;
837 }
838
839 if (!strcmp(args[cur_arg], "user")) {
840 struct passwd *user;
841
842 user = getpwnam(args[cur_arg + 1]);
843 if (!user) {
844 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
845 file, linenum, args[0], args[cur_arg + 1 ]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849
850 global.unix_bind.ux.uid = user->pw_uid;
851 cur_arg += 2;
852 continue;
853 }
854
855 if (!strcmp(args[cur_arg], "group")) {
856 struct group *group;
857
858 group = getgrnam(args[cur_arg + 1]);
859 if (!group) {
860 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
861 file, linenum, args[0], args[cur_arg + 1 ]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865
866 global.unix_bind.ux.gid = group->gr_gid;
867 cur_arg += 2;
868 continue;
869 }
870
Willy Tarreaub48f9582011-09-05 01:17:06 +0200871 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200872 file, linenum, args[0]);
873 err_code |= ERR_ALERT | ERR_FATAL;
874 goto out;
875 }
876 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200877 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100878 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200879 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200880
881 if (*(args[1]) == 0 || *(args[2]) == 0) {
882 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200883 err_code |= ERR_ALERT | ERR_FATAL;
884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885 }
886
887 facility = get_log_facility(args[2]);
888 if (facility < 0) {
889 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 err_code |= ERR_ALERT | ERR_FATAL;
891 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 }
893
894 level = 7; /* max syslog level = debug */
895 if (*(args[3])) {
896 level = get_log_level(args[3]);
897 if (level < 0) {
898 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200899 err_code |= ERR_ALERT | ERR_FATAL;
900 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200901 }
902 }
903
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200904 minlvl = 0; /* limit syslog level to this level (emerg) */
905 if (*(args[4])) {
906 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200907 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200908 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200909 err_code |= ERR_ALERT | ERR_FATAL;
910 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200911 }
912 }
913
Robert Tsai81ae1952007-12-05 10:47:29 +0100914 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100915 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100916 if (!sk) {
917 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100918 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100922 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100923 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100924 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100925 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100926 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
927 err_code |= ERR_ALERT | ERR_FATAL;
928 goto out;
929 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100930 logsrv.addr = *sk;
931 if (!get_host_port(&logsrv.addr))
932 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100933 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934
935 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100936 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 global.logfac1 = facility;
938 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200939 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940 }
941 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100942 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 global.logfac2 = facility;
944 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200945 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 }
947 else {
948 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200949 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200951 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100952 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
953 char *name;
954 int len;
955
956 if (global.log_send_hostname != NULL) {
957 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
958 err_code |= ERR_ALERT;
959 goto out;
960 }
961
962 if (*(args[1]))
963 name = args[1];
964 else
965 name = hostname;
966
967 len = strlen(name);
968
969 /* We'll add a space after the name to respect the log format */
970 free(global.log_send_hostname);
971 global.log_send_hostname = malloc(len + 2);
972 snprintf(global.log_send_hostname, len + 2, "%s ", name);
973 }
Kevinm48936af2010-12-22 16:08:21 +0000974 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
975 if (*(args[1]) == 0) {
976 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
977 err_code |= ERR_ALERT | ERR_FATAL;
978 goto out;
979 }
980 free(global.log_tag);
981 global.log_tag = strdup(args[1]);
982 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200983 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
984 if (global.spread_checks != 0) {
985 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200986 err_code |= ERR_ALERT;
987 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200988 }
989 if (*(args[1]) == 0) {
990 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200993 }
994 global.spread_checks = atol(args[1]);
995 if (global.spread_checks < 0 || global.spread_checks > 50) {
996 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200997 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200998 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 }
1000 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001001 struct cfg_kw_list *kwl;
1002 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001003 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001004
1005 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1006 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1007 if (kwl->kw[index].section != CFG_GLOBAL)
1008 continue;
1009 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1010 /* prepare error message just in case */
1011 snprintf(trash, sizeof(trash),
1012 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001013 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1014 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001015 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001016 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001017 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001018 else if (rc > 0) {
1019 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001020 err_code |= ERR_WARN;
1021 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001022 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001023 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001024 }
1025 }
1026 }
1027
Willy Tarreaubaaee002006-06-26 02:48:02 +02001028 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001029 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001030 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001031
Willy Tarreau058e9072009-07-20 09:30:05 +02001032 out:
1033 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001034}
1035
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001036void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001038 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001039 defproxy.mode = PR_MODE_TCP;
1040 defproxy.state = PR_STNEW;
1041 defproxy.maxconn = cfg_maxpconn;
1042 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001043
1044 defproxy.defsrv.inter = DEF_CHKINTR;
1045 defproxy.defsrv.fastinter = 0;
1046 defproxy.defsrv.downinter = 0;
1047 defproxy.defsrv.rise = DEF_RISETIME;
1048 defproxy.defsrv.fall = DEF_FALLTIME;
1049 defproxy.defsrv.check_port = 0;
1050 defproxy.defsrv.maxqueue = 0;
1051 defproxy.defsrv.minconn = 0;
1052 defproxy.defsrv.maxconn = 0;
1053 defproxy.defsrv.slowstart = 0;
1054 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1055 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1056 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001057}
1058
Willy Tarreauade5ec42010-01-28 19:33:49 +01001059
1060static int create_cond_regex_rule(const char *file, int line,
1061 struct proxy *px, int dir, int action, int flags,
1062 const char *cmd, const char *reg, const char *repl,
1063 const char **cond_start)
1064{
1065 regex_t *preg = NULL;
1066 const char *err;
1067 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001068 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001069
1070 if (px == &defproxy) {
1071 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1072 err_code |= ERR_ALERT | ERR_FATAL;
1073 goto err;
1074 }
1075
1076 if (*reg == 0) {
1077 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto err;
1080 }
1081
1082 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1083 err_code |= ERR_WARN;
1084
Willy Tarreau5321c422010-01-28 20:35:13 +01001085 if (cond_start &&
1086 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1087 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1088 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1089 file, line, cmd);
1090 err_code |= ERR_ALERT | ERR_FATAL;
1091 goto err;
1092 }
1093 }
1094 else if (cond_start && **cond_start) {
1095 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1096 file, line, cmd, *cond_start);
1097 err_code |= ERR_ALERT | ERR_FATAL;
1098 goto err;
1099 }
1100
1101 if (dir == ACL_DIR_REQ)
1102 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001103 else
1104 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001105
Willy Tarreauade5ec42010-01-28 19:33:49 +01001106 preg = calloc(1, sizeof(regex_t));
1107 if (!preg) {
1108 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1109 err_code = ERR_ALERT | ERR_FATAL;
1110 goto err;
1111 }
1112
1113 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1114 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1115 err_code = ERR_ALERT | ERR_FATAL;
1116 goto err;
1117 }
1118
1119 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001120 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001121 if (repl && err) {
1122 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1123 file, line, cmd, *err);
1124 err_code |= ERR_ALERT | ERR_FATAL;
1125 goto err;
1126 }
1127
1128 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1129 err_code |= ERR_WARN;
1130
1131 return err_code;
1132 err:
1133 free(preg);
1134 return err_code;
1135}
1136
Willy Tarreaubaaee002006-06-26 02:48:02 +02001137/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001138 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001139 * Returns the error code, 0 if OK, or any combination of :
1140 * - ERR_ABORT: must abort ASAP
1141 * - ERR_FATAL: we can continue parsing but not start the service
1142 * - ERR_WARN: a warning has been emitted
1143 * - ERR_ALERT: an alert has been emitted
1144 * Only the two first ones can stop processing, the two others are just
1145 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001146 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001147int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1148{
1149 static struct peers *curpeers = NULL;
1150 struct peer *newpeer = NULL;
1151 const char *err;
1152 int err_code = 0;
1153
1154 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1155
1156 err = invalid_char(args[1]);
1157 if (err) {
1158 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1159 file, linenum, *err, args[0], args[1]);
1160 err_code |= ERR_ALERT | ERR_FATAL;
1161 }
1162
1163 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1164 /*
1165 * If there are two proxies with the same name only following
1166 * combinations are allowed:
1167 */
1168 if (strcmp(curpeers->id, args[1]) == 0) {
1169 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1170 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1171 err_code |= ERR_WARN;
1172 }
1173 }
1174
1175 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1176 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1177 err_code |= ERR_ALERT | ERR_ABORT;
1178 goto out;
1179 }
1180
1181 curpeers->next = peers;
1182 peers = curpeers;
1183 curpeers->conf.file = file;
1184 curpeers->conf.line = linenum;
1185 curpeers->last_change = now.tv_sec;
1186 curpeers->id = strdup(args[1]);
1187 }
1188 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1189 char *rport, *raddr;
1190 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001191 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001192
1193 if (!*args[2]) {
1194 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1195 file, linenum, args[0]);
1196 err_code |= ERR_ALERT | ERR_FATAL;
1197 goto out;
1198 }
1199
1200 err = invalid_char(args[1]);
1201 if (err) {
1202 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1203 file, linenum, *err, args[1]);
1204 err_code |= ERR_ALERT | ERR_FATAL;
1205 goto out;
1206 }
1207
1208 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1209 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1210 err_code |= ERR_ALERT | ERR_ABORT;
1211 goto out;
1212 }
1213
1214 /* the peers are linked backwards first */
1215 curpeers->count++;
1216 newpeer->next = curpeers->remote;
1217 curpeers->remote = newpeer;
1218 newpeer->peers = curpeers;
1219 newpeer->conf.file = file;
1220 newpeer->conf.line = linenum;
1221
1222 newpeer->last_change = now.tv_sec;
1223 newpeer->id = strdup(args[1]);
1224
1225 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001226 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001227 if (rport) {
1228 *rport++ = 0;
1229 realport = atol(rport);
1230 }
1231 if (!realport) {
1232 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235 }
1236
Willy Tarreaufab5a432011-03-04 15:31:53 +01001237 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001238 free(raddr);
1239 if (!sk) {
1240 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1241 err_code |= ERR_ALERT | ERR_FATAL;
1242 goto out;
1243 }
1244 newpeer->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001245 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001246
1247 if (strcmp(newpeer->id, localpeer) == 0) {
1248 /* Current is local peer, it define a frontend */
1249 newpeer->local = 1;
1250
1251 if (!curpeers->peers_fe) {
1252 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1253 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1254 err_code |= ERR_ALERT | ERR_ABORT;
1255 goto out;
1256 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001257
Willy Tarreau237250c2011-07-29 01:49:03 +02001258 init_new_proxy(curpeers->peers_fe);
1259 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001260
1261 curpeers->peers_fe->last_change = now.tv_sec;
1262 curpeers->peers_fe->id = strdup(args[1]);
1263 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001264 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001265 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1266 curpeers->peers_fe->timeout.connect = 5000;
1267 curpeers->peers_fe->accept = peer_accept;
1268 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001269 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001270 err_code |= ERR_FATAL;
1271 goto out;
1272 }
1273 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1274 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1275 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1276 curpeers->peers_fe->listen->accept = session_accept;
1277 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1278 curpeers->peers_fe->listen->handler = process_session;
1279 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001280 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1281 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001282 }
1283 }
1284 } /* neither "peer" nor "peers" */
1285 else if (*args[0] != 0) {
1286 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
1289 }
1290
1291out:
1292 return err_code;
1293}
1294
1295
Willy Tarreau3842f002009-06-14 11:39:52 +02001296int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001297{
1298 static struct proxy *curproxy = NULL;
1299 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001300 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001301 int rc;
1302 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001303 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001304 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001305
Willy Tarreau977b8e42006-12-29 14:19:17 +01001306 if (!strcmp(args[0], "listen"))
1307 rc = PR_CAP_LISTEN;
1308 else if (!strcmp(args[0], "frontend"))
1309 rc = PR_CAP_FE | PR_CAP_RS;
1310 else if (!strcmp(args[0], "backend"))
1311 rc = PR_CAP_BE | PR_CAP_RS;
1312 else if (!strcmp(args[0], "ruleset"))
1313 rc = PR_CAP_RS;
1314 else
1315 rc = PR_CAP_NONE;
1316
1317 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318 if (!*args[1]) {
1319 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1320 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1321 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001322 err_code |= ERR_ALERT | ERR_ABORT;
1323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001324 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001325
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001326 err = invalid_char(args[1]);
1327 if (err) {
1328 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1329 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001330 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001331 }
1332
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001333 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1334 /*
1335 * If there are two proxies with the same name only following
1336 * combinations are allowed:
1337 *
1338 * listen backend frontend ruleset
1339 * listen - - - -
1340 * backend - - OK -
1341 * frontend - OK - -
1342 * ruleset - - - -
1343 */
1344
1345 if (!strcmp(curproxy->id, args[1]) &&
1346 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1347 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001348 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1349 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1350 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001351 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001352 }
1353 }
1354
Willy Tarreaubaaee002006-06-26 02:48:02 +02001355 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1356 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001357 err_code |= ERR_ALERT | ERR_ABORT;
1358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001359 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001360
Willy Tarreau97cb7802010-01-03 20:23:58 +01001361 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 curproxy->next = proxy;
1363 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001364 curproxy->conf.file = file;
1365 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001366 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001368 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001369
1370 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001371 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001372 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001373 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001374 err_code |= ERR_FATAL;
1375 goto out;
1376 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001377 new = curproxy->listen;
1378 while (new != last) {
1379 new->conf.file = file;
1380 new->conf.line = linenum;
1381 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001382 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001383 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 }
1385
1386 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001387 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001388 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001389
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001392 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001393 curproxy->no_options = defproxy.no_options;
1394 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001395 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001396 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001397 curproxy->except_net = defproxy.except_net;
1398 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001399 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001400 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001402 if (defproxy.fwdfor_hdr_len) {
1403 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1404 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1405 }
1406
Willy Tarreaub86db342009-11-30 11:50:16 +01001407 if (defproxy.orgto_hdr_len) {
1408 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1409 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1410 }
1411
Willy Tarreau977b8e42006-12-29 14:19:17 +01001412 if (curproxy->cap & PR_CAP_FE) {
1413 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001414 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001415 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001416
1417 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001418 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1419 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001420
1421 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1422 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001423
Willy Tarreau977b8e42006-12-29 14:19:17 +01001424 if (curproxy->cap & PR_CAP_BE) {
1425 curproxy->fullconn = defproxy.fullconn;
1426 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001428 if (defproxy.check_req) {
1429 curproxy->check_req = calloc(1, defproxy.check_len);
1430 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1431 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001432 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001434 if (defproxy.expect_str) {
1435 curproxy->expect_str = strdup(defproxy.expect_str);
1436 if (defproxy.expect_regex) {
1437 /* note: this regex is known to be valid */
1438 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1439 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1440 }
1441 }
1442
Willy Tarreau977b8e42006-12-29 14:19:17 +01001443 if (defproxy.cookie_name)
1444 curproxy->cookie_name = strdup(defproxy.cookie_name);
1445 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001446 if (defproxy.cookie_domain)
1447 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001448
Willy Tarreau31936852010-10-06 16:59:56 +02001449 if (defproxy.cookie_maxidle)
1450 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1451
1452 if (defproxy.cookie_maxlife)
1453 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1454
Emeric Brun647caf12009-06-30 17:57:00 +02001455 if (defproxy.rdp_cookie_name)
1456 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1457 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1458
Willy Tarreau01732802007-11-01 22:48:15 +01001459 if (defproxy.url_param_name)
1460 curproxy->url_param_name = strdup(defproxy.url_param_name);
1461 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001462
Benoitaffb4812009-03-25 13:02:10 +01001463 if (defproxy.hh_name)
1464 curproxy->hh_name = strdup(defproxy.hh_name);
1465 curproxy->hh_len = defproxy.hh_len;
1466 curproxy->hh_match_domain = defproxy.hh_match_domain;
1467
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001468 if (defproxy.iface_name)
1469 curproxy->iface_name = strdup(defproxy.iface_name);
1470 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001473 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001474 if (defproxy.capture_name)
1475 curproxy->capture_name = strdup(defproxy.capture_name);
1476 curproxy->capture_namelen = defproxy.capture_namelen;
1477 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001478 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001479
Willy Tarreau977b8e42006-12-29 14:19:17 +01001480 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001481 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001482 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001483 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001484 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001485 curproxy->uri_auth = defproxy.uri_auth;
1486 curproxy->mon_net = defproxy.mon_net;
1487 curproxy->mon_mask = defproxy.mon_mask;
1488 if (defproxy.monitor_uri)
1489 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1490 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001491 if (defproxy.defbe.name)
1492 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001493 }
1494
1495 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001496 curproxy->timeout.connect = defproxy.timeout.connect;
1497 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001498 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001499 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001500 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001501 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001502 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001503 curproxy->source_addr = defproxy.source_addr;
1504 }
1505
Willy Tarreaubaaee002006-06-26 02:48:02 +02001506 curproxy->mode = defproxy.mode;
1507 curproxy->logfac1 = defproxy.logfac1;
1508 curproxy->logsrv1 = defproxy.logsrv1;
1509 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001510 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001511 curproxy->logfac2 = defproxy.logfac2;
1512 curproxy->logsrv2 = defproxy.logsrv2;
1513 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001514 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001516 curproxy->conf.used_listener_id = EB_ROOT;
1517 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001518
Willy Tarreau93893792009-07-23 13:19:11 +02001519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001520 }
1521 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1522 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001523 /* FIXME-20070101: we should do this too at the end of the
1524 * config parsing to free all default values.
1525 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001526 free(defproxy.check_req);
1527 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001528 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001529 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001530 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001531 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001532 free(defproxy.capture_name);
1533 free(defproxy.monitor_uri);
1534 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001535 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001536 free(defproxy.fwdfor_hdr_name);
1537 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001538 free(defproxy.orgto_hdr_name);
1539 defproxy.orgto_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001540 free(defproxy.expect_str);
1541 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001542
Willy Tarreaua534fea2008-08-03 12:19:50 +02001543 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001544 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001545
Willy Tarreaubaaee002006-06-26 02:48:02 +02001546 /* we cannot free uri_auth because it might already be used */
1547 init_default_instance();
1548 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001549 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001551 }
1552 else if (curproxy == NULL) {
1553 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001554 err_code |= ERR_ALERT | ERR_FATAL;
1555 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001556 }
1557
Willy Tarreau977b8e42006-12-29 14:19:17 +01001558
1559 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001561 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001562 int cur_arg;
1563
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564 if (curproxy == &defproxy) {
1565 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001566 err_code |= ERR_ALERT | ERR_FATAL;
1567 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001569 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001570 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571
Emeric Bruned760922010-10-22 17:59:25 +02001572 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001573 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001574 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001575 err_code |= ERR_ALERT | ERR_FATAL;
1576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001578
1579 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001580
1581 /* NOTE: the following line might create several listeners if there
1582 * are comma-separated IPs or port ranges. So all further processing
1583 * will have to be applied to all listeners created after last_listen.
1584 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001585 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001586 err_code |= ERR_ALERT | ERR_FATAL;
1587 goto out;
1588 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001589
Willy Tarreau90a570f2009-10-04 20:54:54 +02001590 new_listen = curproxy->listen;
1591 while (new_listen != last_listen) {
1592 new_listen->conf.file = file;
1593 new_listen->conf.line = linenum;
1594 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001595 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001596 }
1597
Emeric Bruned760922010-10-22 17:59:25 +02001598 /* Set default global rights and owner for unix bind */
1599 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1600 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1601 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001602 cur_arg = 2;
1603 while (*(args[cur_arg])) {
1604 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1605#ifdef SO_BINDTODEVICE
1606 struct listener *l;
1607
Emeric Bruned760922010-10-22 17:59:25 +02001608 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1609 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1610 file, linenum, args[0], args[cur_arg]);
1611 err_code |= ERR_ALERT | ERR_FATAL;
1612 goto out;
1613 }
1614
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001615 if (!*args[cur_arg + 1]) {
1616 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1617 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001618 err_code |= ERR_ALERT | ERR_FATAL;
1619 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001620 }
1621
1622 for (l = curproxy->listen; l != last_listen; l = l->next)
1623 l->interface = strdup(args[cur_arg + 1]);
1624
1625 global.last_checks |= LSTCHK_NETADM;
1626
1627 cur_arg += 2;
1628 continue;
1629#else
1630 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1631 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001632 err_code |= ERR_ALERT | ERR_FATAL;
1633 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001634#endif
1635 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001636 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1637#ifdef TCP_MAXSEG
1638 struct listener *l;
1639 int mss;
1640
Emeric Bruned760922010-10-22 17:59:25 +02001641 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1642 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1643 file, linenum, args[0], args[cur_arg]);
1644 err_code |= ERR_ALERT | ERR_FATAL;
1645 goto out;
1646 }
1647
Willy Tarreaube1b9182009-06-14 18:48:19 +02001648 if (!*args[cur_arg + 1]) {
1649 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1650 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001653 }
1654
Willy Tarreau48a7e722010-12-24 15:26:39 +01001655 mss = atoi(args[cur_arg + 1]);
1656 if (!mss || abs(mss) > 65535) {
1657 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001658 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001659 err_code |= ERR_ALERT | ERR_FATAL;
1660 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001661 }
1662
1663 for (l = curproxy->listen; l != last_listen; l = l->next)
1664 l->maxseg = mss;
1665
1666 cur_arg += 2;
1667 continue;
1668#else
1669 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1670 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001671 err_code |= ERR_ALERT | ERR_FATAL;
1672 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001673#endif
1674 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001675
1676 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1677#ifdef TCP_DEFER_ACCEPT
1678 struct listener *l;
1679
1680 for (l = curproxy->listen; l != last_listen; l = l->next)
1681 l->options |= LI_O_DEF_ACCEPT;
1682
1683 cur_arg ++;
1684 continue;
1685#else
1686 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1687 file, linenum, args[0], args[cur_arg]);
1688 err_code |= ERR_ALERT | ERR_FATAL;
1689 goto out;
1690#endif
1691 }
1692
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001693 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001694#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001695 struct listener *l;
1696
Emeric Bruned760922010-10-22 17:59:25 +02001697 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1698 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1699 file, linenum, args[0], args[cur_arg]);
1700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
1702 }
1703
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001704 for (l = curproxy->listen; l != last_listen; l = l->next)
1705 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001706
1707 cur_arg ++;
1708 continue;
1709#else
1710 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1711 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001712 err_code |= ERR_ALERT | ERR_FATAL;
1713 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001714#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001715 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001716
Willy Tarreau8a956912010-10-15 14:27:08 +02001717 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1718 struct listener *l;
1719
1720 for (l = curproxy->listen; l != last_listen; l = l->next)
1721 l->options |= LI_O_ACC_PROXY;
1722
1723 cur_arg ++;
1724 continue;
1725 }
1726
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001727 if (!strcmp(args[cur_arg], "name")) {
1728 struct listener *l;
1729
1730 for (l = curproxy->listen; l != last_listen; l = l->next)
1731 l->name = strdup(args[cur_arg + 1]);
1732
1733 cur_arg += 2;
1734 continue;
1735 }
1736
1737 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001738 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001739 struct listener *l;
1740
1741 if (curproxy->listen->next != last_listen) {
1742 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1743 file, linenum, args[cur_arg]);
1744 err_code |= ERR_ALERT | ERR_FATAL;
1745 goto out;
1746 }
1747
1748 if (!*args[cur_arg + 1]) {
1749 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1750 file, linenum, args[cur_arg]);
1751 err_code |= ERR_ALERT | ERR_FATAL;
1752 goto out;
1753 }
1754
1755 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001756 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001757
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001758 if (curproxy->listen->luid <= 0) {
1759 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001760 file, linenum);
1761 err_code |= ERR_ALERT | ERR_FATAL;
1762 goto out;
1763 }
1764
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001765 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1766 if (node) {
1767 l = container_of(node, struct listener, conf.id);
1768 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1769 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
1772 }
1773 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1774
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001775 cur_arg += 2;
1776 continue;
1777 }
1778
Emeric Bruned760922010-10-22 17:59:25 +02001779 if (!strcmp(args[cur_arg], "mode")) {
1780
1781 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1782 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1783 file, linenum, args[0], args[cur_arg]);
1784 err_code |= ERR_ALERT | ERR_FATAL;
1785 goto out;
1786 }
1787
1788 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1789
1790 cur_arg += 2;
1791 continue;
1792 }
1793
1794 if (!strcmp(args[cur_arg], "uid")) {
1795
1796 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1797 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1798 file, linenum, args[0], args[cur_arg]);
1799 err_code |= ERR_ALERT | ERR_FATAL;
1800 goto out;
1801 }
1802
1803 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1804 cur_arg += 2;
1805 continue;
1806 }
1807
1808 if (!strcmp(args[cur_arg], "gid")) {
1809
1810 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1811 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1812 file, linenum, args[0], args[cur_arg]);
1813 err_code |= ERR_ALERT | ERR_FATAL;
1814 goto out;
1815 }
1816
1817 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1818 cur_arg += 2;
1819 continue;
1820 }
1821
1822 if (!strcmp(args[cur_arg], "user")) {
1823 struct passwd *user;
1824
1825 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1826 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1827 file, linenum, args[0], args[cur_arg]);
1828 err_code |= ERR_ALERT | ERR_FATAL;
1829 goto out;
1830 }
1831 user = getpwnam(args[cur_arg + 1]);
1832 if (!user) {
1833 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1834 file, linenum, args[0], args[cur_arg + 1 ]);
1835 err_code |= ERR_ALERT | ERR_FATAL;
1836 goto out;
1837 }
1838
1839 curproxy->listen->perm.ux.uid = user->pw_uid;
1840 cur_arg += 2;
1841 continue;
1842 }
1843
1844 if (!strcmp(args[cur_arg], "group")) {
1845 struct group *group;
1846
1847 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1848 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1849 file, linenum, args[0], args[cur_arg]);
1850 err_code |= ERR_ALERT | ERR_FATAL;
1851 goto out;
1852 }
1853 group = getgrnam(args[cur_arg + 1]);
1854 if (!group) {
1855 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1856 file, linenum, args[0], args[cur_arg + 1 ]);
1857 err_code |= ERR_ALERT | ERR_FATAL;
1858 goto out;
1859 }
1860
1861 curproxy->listen->perm.ux.gid = group->gr_gid;
1862 cur_arg += 2;
1863 continue;
1864 }
1865
Willy Tarreaub48f9582011-09-05 01:17:06 +02001866 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss', 'mode', 'uid', 'gid', 'user', 'group' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001867 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001868 err_code |= ERR_ALERT | ERR_FATAL;
1869 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001870 }
Willy Tarreau93893792009-07-23 13:19:11 +02001871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001872 }
1873 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1874 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1875 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1876 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001877 err_code |= ERR_ALERT | ERR_FATAL;
1878 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001879 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001880 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001881 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001882
Willy Tarreaubaaee002006-06-26 02:48:02 +02001883 /* flush useless bits */
1884 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001886 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001887 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001888 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001889 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001890
Willy Tarreau1c47f852006-07-09 08:22:27 +02001891 if (!*args[1]) {
1892 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1893 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001894 err_code |= ERR_ALERT | ERR_FATAL;
1895 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001896 }
1897
Willy Tarreaua534fea2008-08-03 12:19:50 +02001898 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001899 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001900 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001901 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001902 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1903
Willy Tarreau93893792009-07-23 13:19:11 +02001904 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001905 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1907 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1908 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1909 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1910 else {
1911 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001912 err_code |= ERR_ALERT | ERR_FATAL;
1913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914 }
1915 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001916 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001917 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001918
1919 if (curproxy == &defproxy) {
1920 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1921 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001922 err_code |= ERR_ALERT | ERR_FATAL;
1923 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001924 }
1925
1926 if (!*args[1]) {
1927 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1928 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_ALERT | ERR_FATAL;
1930 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001931 }
1932
1933 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001934 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001935
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001936 if (curproxy->uuid <= 0) {
1937 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001938 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001939 err_code |= ERR_ALERT | ERR_FATAL;
1940 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001941 }
1942
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001943 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1944 if (node) {
1945 struct proxy *target = container_of(node, struct proxy, conf.id);
1946 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1947 file, linenum, proxy_type_str(curproxy), curproxy->id,
1948 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1949 err_code |= ERR_ALERT | ERR_FATAL;
1950 goto out;
1951 }
1952 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001953 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001954 else if (!strcmp(args[0], "description")) {
1955 int i, len=0;
1956 char *d;
1957
Cyril Bonté99ed3272010-01-24 23:29:44 +01001958 if (curproxy == &defproxy) {
1959 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1960 file, linenum, args[0]);
1961 err_code |= ERR_ALERT | ERR_FATAL;
1962 goto out;
1963 }
1964
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001965 if (!*args[1]) {
1966 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1967 file, linenum, args[0]);
1968 return -1;
1969 }
1970
1971 for(i=1; *args[i]; i++)
1972 len += strlen(args[i])+1;
1973
1974 d = (char *)calloc(1, len);
1975 curproxy->desc = d;
1976
1977 d += sprintf(d, "%s", args[1]);
1978 for(i=2; *args[i]; i++)
1979 d += sprintf(d, " %s", args[i]);
1980
1981 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001982 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1983 curproxy->state = PR_STSTOPPED;
1984 }
1985 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1986 curproxy->state = PR_STNEW;
1987 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001988 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1989 int cur_arg = 1;
1990 unsigned int set = 0;
1991
1992 while (*args[cur_arg]) {
1993 int u;
1994 if (strcmp(args[cur_arg], "all") == 0) {
1995 set = 0;
1996 break;
1997 }
1998 else if (strcmp(args[cur_arg], "odd") == 0) {
1999 set |= 0x55555555;
2000 }
2001 else if (strcmp(args[cur_arg], "even") == 0) {
2002 set |= 0xAAAAAAAA;
2003 }
2004 else {
2005 u = str2uic(args[cur_arg]);
2006 if (u < 1 || u > 32) {
2007 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2008 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002009 err_code |= ERR_ALERT | ERR_FATAL;
2010 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002011 }
2012 if (u > global.nbproc) {
2013 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2014 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002015 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002016 }
2017 set |= 1 << (u - 1);
2018 }
2019 cur_arg++;
2020 }
2021 curproxy->bind_proc = set;
2022 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002023 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002024 if (curproxy == &defproxy) {
2025 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002026 err_code |= ERR_ALERT | ERR_FATAL;
2027 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002028 }
2029
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002030 err = invalid_char(args[1]);
2031 if (err) {
2032 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2033 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002035 }
2036
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002037 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2038 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2039 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002040 err_code |= ERR_ALERT | ERR_FATAL;
2041 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002042 }
2043 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002044 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2045 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002046
Willy Tarreau977b8e42006-12-29 14:19:17 +01002047 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002048 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002049
Willy Tarreaubaaee002006-06-26 02:48:02 +02002050 if (*(args[1]) == 0) {
2051 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2052 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002053 err_code |= ERR_ALERT | ERR_FATAL;
2054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002055 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002056
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002057 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002058 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002059 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002060 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002061 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062 curproxy->cookie_name = strdup(args[1]);
2063 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002064
Willy Tarreaubaaee002006-06-26 02:48:02 +02002065 cur_arg = 2;
2066 while (*(args[cur_arg])) {
2067 if (!strcmp(args[cur_arg], "rewrite")) {
2068 curproxy->options |= PR_O_COOK_RW;
2069 }
2070 else if (!strcmp(args[cur_arg], "indirect")) {
2071 curproxy->options |= PR_O_COOK_IND;
2072 }
2073 else if (!strcmp(args[cur_arg], "insert")) {
2074 curproxy->options |= PR_O_COOK_INS;
2075 }
2076 else if (!strcmp(args[cur_arg], "nocache")) {
2077 curproxy->options |= PR_O_COOK_NOC;
2078 }
2079 else if (!strcmp(args[cur_arg], "postonly")) {
2080 curproxy->options |= PR_O_COOK_POST;
2081 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002082 else if (!strcmp(args[cur_arg], "preserve")) {
2083 curproxy->options2 |= PR_O2_COOK_PSV;
2084 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002085 else if (!strcmp(args[cur_arg], "prefix")) {
2086 curproxy->options |= PR_O_COOK_PFX;
2087 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002088 else if (!strcmp(args[cur_arg], "domain")) {
2089 if (!*args[cur_arg + 1]) {
2090 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2091 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002092 err_code |= ERR_ALERT | ERR_FATAL;
2093 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002094 }
2095
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002096 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002097 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002098 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2099 " dots nor does not start with a dot."
2100 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002101 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002102 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002103 }
2104
2105 err = invalid_domainchar(args[cur_arg + 1]);
2106 if (err) {
2107 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2108 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002109 err_code |= ERR_ALERT | ERR_FATAL;
2110 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002111 }
2112
Willy Tarreau68a897b2009-12-03 23:28:34 +01002113 if (!curproxy->cookie_domain) {
2114 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2115 } else {
2116 /* one domain was already specified, add another one by
2117 * building the string which will be returned along with
2118 * the cookie.
2119 */
2120 char *new_ptr;
2121 int new_len = strlen(curproxy->cookie_domain) +
2122 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2123 new_ptr = malloc(new_len);
2124 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2125 free(curproxy->cookie_domain);
2126 curproxy->cookie_domain = new_ptr;
2127 }
Willy Tarreau31936852010-10-06 16:59:56 +02002128 cur_arg++;
2129 }
2130 else if (!strcmp(args[cur_arg], "maxidle")) {
2131 unsigned int maxidle;
2132 const char *res;
2133
2134 if (!*args[cur_arg + 1]) {
2135 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2136 file, linenum, args[cur_arg]);
2137 err_code |= ERR_ALERT | ERR_FATAL;
2138 goto out;
2139 }
2140
2141 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2142 if (res) {
2143 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2144 file, linenum, *res, args[cur_arg]);
2145 err_code |= ERR_ALERT | ERR_FATAL;
2146 goto out;
2147 }
2148 curproxy->cookie_maxidle = maxidle;
2149 cur_arg++;
2150 }
2151 else if (!strcmp(args[cur_arg], "maxlife")) {
2152 unsigned int maxlife;
2153 const char *res;
2154
2155 if (!*args[cur_arg + 1]) {
2156 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2157 file, linenum, args[cur_arg]);
2158 err_code |= ERR_ALERT | ERR_FATAL;
2159 goto out;
2160 }
2161
2162 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2163 if (res) {
2164 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2165 file, linenum, *res, args[cur_arg]);
2166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
2168 }
2169 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002170 cur_arg++;
2171 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002172 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002173 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 +02002174 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 }
2178 cur_arg++;
2179 }
2180 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2181 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2182 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002183 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 }
2185
2186 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2187 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2188 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002189 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002190 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002191
2192 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2193 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2194 file, linenum);
2195 err_code |= ERR_ALERT | ERR_FATAL;
2196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002197 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002198 else if (!strcmp(args[0], "persist")) { /* persist */
2199 if (*(args[1]) == 0) {
2200 Alert("parsing [%s:%d] : missing persist method.\n",
2201 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002202 err_code |= ERR_ALERT | ERR_FATAL;
2203 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002204 }
2205
2206 if (!strncmp(args[1], "rdp-cookie", 10)) {
2207 curproxy->options2 |= PR_O2_RDPC_PRST;
2208
Emeric Brunb982a3d2010-01-04 15:45:53 +01002209 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002210 const char *beg, *end;
2211
2212 beg = args[1] + 11;
2213 end = strchr(beg, ')');
2214
2215 if (!end || end == beg) {
2216 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2217 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002218 err_code |= ERR_ALERT | ERR_FATAL;
2219 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002220 }
2221
2222 free(curproxy->rdp_cookie_name);
2223 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2224 curproxy->rdp_cookie_len = end-beg;
2225 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002226 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002227 free(curproxy->rdp_cookie_name);
2228 curproxy->rdp_cookie_name = strdup("msts");
2229 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2230 }
2231 else { /* syntax */
2232 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2233 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002236 }
2237 }
2238 else {
2239 Alert("parsing [%s:%d] : unknown persist method.\n",
2240 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002241 err_code |= ERR_ALERT | ERR_FATAL;
2242 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002243 }
2244 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002246 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002248 if (curproxy == &defproxy) {
2249 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
2252 }
2253
Willy Tarreau977b8e42006-12-29 14:19:17 +01002254 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002255 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002256
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002258 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002262 }
2263 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002264 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 curproxy->appsession_name = strdup(args[1]);
2266 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2267 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002268 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2269 if (err) {
2270 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2271 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002274 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002275 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002276
Willy Tarreau51041c72007-09-09 21:56:53 +02002277 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2278 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002279 err_code |= ERR_ALERT | ERR_ABORT;
2280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002281 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002282
2283 cur_arg = 6;
2284 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002285 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2286 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002287 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002288 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002289 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002290 } else if (!strcmp(args[cur_arg], "prefix")) {
2291 curproxy->options2 |= PR_O2_AS_PFX;
2292 } else if (!strcmp(args[cur_arg], "mode")) {
2293 if (!*args[cur_arg + 1]) {
2294 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2295 file, linenum, args[0], args[cur_arg]);
2296 err_code |= ERR_ALERT | ERR_FATAL;
2297 goto out;
2298 }
2299
2300 cur_arg++;
2301 if (!strcmp(args[cur_arg], "query-string")) {
2302 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2303 curproxy->options2 |= PR_O2_AS_M_QS;
2304 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2305 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2306 curproxy->options2 |= PR_O2_AS_M_PP;
2307 } else {
2308 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
2311 }
2312 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002313 cur_arg++;
2314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002315 } /* Url App Session */
2316 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002317 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002318 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002319
Willy Tarreaubaaee002006-06-26 02:48:02 +02002320 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002321 if (curproxy == &defproxy) {
2322 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2323 err_code |= ERR_ALERT | ERR_FATAL;
2324 goto out;
2325 }
2326
Willy Tarreaubaaee002006-06-26 02:48:02 +02002327 if (*(args[4]) == 0) {
2328 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2329 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002332 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002333 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 curproxy->capture_name = strdup(args[2]);
2335 curproxy->capture_namelen = strlen(curproxy->capture_name);
2336 curproxy->capture_len = atol(args[4]);
2337 if (curproxy->capture_len >= CAPTURE_LEN) {
2338 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2339 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002340 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 curproxy->capture_len = CAPTURE_LEN - 1;
2342 }
2343 curproxy->to_log |= LW_COOKIE;
2344 }
2345 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2346 struct cap_hdr *hdr;
2347
2348 if (curproxy == &defproxy) {
2349 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 +02002350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002352 }
2353
2354 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2355 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2356 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002357 err_code |= ERR_ALERT | ERR_FATAL;
2358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 }
2360
2361 hdr = calloc(sizeof(struct cap_hdr), 1);
2362 hdr->next = curproxy->req_cap;
2363 hdr->name = strdup(args[3]);
2364 hdr->namelen = strlen(args[3]);
2365 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002366 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002367 hdr->index = curproxy->nb_req_cap++;
2368 curproxy->req_cap = hdr;
2369 curproxy->to_log |= LW_REQHDR;
2370 }
2371 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2372 struct cap_hdr *hdr;
2373
2374 if (curproxy == &defproxy) {
2375 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 +02002376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 }
2379
2380 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2381 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2382 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385 }
2386 hdr = calloc(sizeof(struct cap_hdr), 1);
2387 hdr->next = curproxy->rsp_cap;
2388 hdr->name = strdup(args[3]);
2389 hdr->namelen = strlen(args[3]);
2390 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002391 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 hdr->index = curproxy->nb_rsp_cap++;
2393 curproxy->rsp_cap = hdr;
2394 curproxy->to_log |= LW_RSPHDR;
2395 }
2396 else {
2397 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2398 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 }
2402 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002404 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002406
Willy Tarreaubaaee002006-06-26 02:48:02 +02002407 if (*(args[1]) == 0) {
2408 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2409 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002410 err_code |= ERR_ALERT | ERR_FATAL;
2411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002412 }
2413 curproxy->conn_retries = atol(args[1]);
2414 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002415 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002416 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002417
2418 if (curproxy == &defproxy) {
2419 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
2422 }
2423
Willy Tarreauff011f22011-01-06 17:51:27 +01002424 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 +01002425 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2426 file, linenum, args[0]);
2427 err_code |= ERR_WARN;
2428 }
2429
Willy Tarreauff011f22011-01-06 17:51:27 +01002430 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002431
Willy Tarreauff011f22011-01-06 17:51:27 +01002432 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002433 err_code |= ERR_ALERT | ERR_ABORT;
2434 goto out;
2435 }
2436
Willy Tarreauff011f22011-01-06 17:51:27 +01002437 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2438 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002439 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002440 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002441 if (curproxy == &defproxy) {
2442 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002445 }
2446
Willy Tarreauef6494c2010-01-28 17:12:36 +01002447 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002448 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2449 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002450 err_code |= ERR_ALERT | ERR_FATAL;
2451 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002452 }
2453
Willy Tarreauef6494c2010-01-28 17:12:36 +01002454 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002455 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2456 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002459 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002460
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002461 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002462 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002463 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002464 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002465 struct redirect_rule *rule;
2466 int cur_arg;
2467 int type = REDIRECT_TYPE_NONE;
2468 int code = 302;
2469 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002470 char *cookie = NULL;
2471 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002472 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002473
Cyril Bonté99ed3272010-01-24 23:29:44 +01002474 if (curproxy == &defproxy) {
2475 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
2478 }
2479
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002480 cur_arg = 1;
2481 while (*(args[cur_arg])) {
2482 if (!strcmp(args[cur_arg], "location")) {
2483 if (!*args[cur_arg + 1]) {
2484 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2485 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002486 err_code |= ERR_ALERT | ERR_FATAL;
2487 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002488 }
2489
2490 type = REDIRECT_TYPE_LOCATION;
2491 cur_arg++;
2492 destination = args[cur_arg];
2493 }
2494 else if (!strcmp(args[cur_arg], "prefix")) {
2495 if (!*args[cur_arg + 1]) {
2496 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2497 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002500 }
2501
2502 type = REDIRECT_TYPE_PREFIX;
2503 cur_arg++;
2504 destination = args[cur_arg];
2505 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002506 else if (!strcmp(args[cur_arg], "set-cookie")) {
2507 if (!*args[cur_arg + 1]) {
2508 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2509 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002512 }
2513
2514 cur_arg++;
2515 cookie = args[cur_arg];
2516 cookie_set = 1;
2517 }
2518 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2519 if (!*args[cur_arg + 1]) {
2520 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2521 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002524 }
2525
2526 cur_arg++;
2527 cookie = args[cur_arg];
2528 cookie_set = 0;
2529 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002530 else if (!strcmp(args[cur_arg],"code")) {
2531 if (!*args[cur_arg + 1]) {
2532 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2533 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002534 err_code |= ERR_ALERT | ERR_FATAL;
2535 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002536 }
2537 cur_arg++;
2538 code = atol(args[cur_arg]);
2539 if (code < 301 || code > 303) {
2540 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2541 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002542 err_code |= ERR_ALERT | ERR_FATAL;
2543 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002544 }
2545 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002546 else if (!strcmp(args[cur_arg],"drop-query")) {
2547 flags |= REDIRECT_FLAG_DROP_QS;
2548 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002549 else if (!strcmp(args[cur_arg],"append-slash")) {
2550 flags |= REDIRECT_FLAG_APPEND_SLASH;
2551 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002552 else if (strcmp(args[cur_arg], "if") == 0 ||
2553 strcmp(args[cur_arg], "unless") == 0) {
2554 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2555 if (!cond) {
2556 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2557 file, linenum, args[0]);
2558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
2560 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002561 break;
2562 }
2563 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002564 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 +02002565 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002568 }
2569 cur_arg++;
2570 }
2571
2572 if (type == REDIRECT_TYPE_NONE) {
2573 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2574 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002577 }
2578
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002579 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2580 rule->cond = cond;
2581 rule->rdr_str = strdup(destination);
2582 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002583 if (cookie) {
2584 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002585 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002586 */
2587 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002588 if (cookie_set) {
2589 rule->cookie_str = malloc(rule->cookie_len + 10);
2590 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2591 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2592 rule->cookie_len += 9;
2593 } else {
2594 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002595 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002596 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2597 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002598 }
2599 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002600 rule->type = type;
2601 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002602 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002603 LIST_INIT(&rule->list);
2604 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002605 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2606 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002607 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002608 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002609 struct switching_rule *rule;
2610
Willy Tarreaub099aca2008-10-12 17:26:37 +02002611 if (curproxy == &defproxy) {
2612 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002615 }
2616
Willy Tarreau55ea7572007-06-17 19:56:27 +02002617 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002618 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002619
2620 if (*(args[1]) == 0) {
2621 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002624 }
2625
Willy Tarreauef6494c2010-01-28 17:12:36 +01002626 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002627 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2628 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002629 err_code |= ERR_ALERT | ERR_FATAL;
2630 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002631 }
2632
Willy Tarreauef6494c2010-01-28 17:12:36 +01002633 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002634 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002635 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002636 err_code |= ERR_ALERT | ERR_FATAL;
2637 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002638 }
2639
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002640 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002641
Willy Tarreau55ea7572007-06-17 19:56:27 +02002642 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2643 rule->cond = cond;
2644 rule->be.name = strdup(args[1]);
2645 LIST_INIT(&rule->list);
2646 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2647 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002648 else if ((!strcmp(args[0], "force-persist")) ||
2649 (!strcmp(args[0], "ignore-persist"))) {
2650 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002651
2652 if (curproxy == &defproxy) {
2653 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
2656 }
2657
2658 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2659 err_code |= ERR_WARN;
2660
Willy Tarreauef6494c2010-01-28 17:12:36 +01002661 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002662 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2663 file, linenum, args[0]);
2664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
2666 }
2667
Willy Tarreauef6494c2010-01-28 17:12:36 +01002668 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002669 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2670 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
2673 }
2674
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002675 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002676
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002677 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002678 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002679 if (!strcmp(args[0], "force-persist")) {
2680 rule->type = PERSIST_TYPE_FORCE;
2681 } else {
2682 rule->type = PERSIST_TYPE_IGNORE;
2683 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002684 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002685 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002686 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002687 else if (!strcmp(args[0], "stick-table")) {
2688 int myidx = 1;
2689
Emeric Brun32da3c42010-09-23 18:39:19 +02002690 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002691 curproxy->table.type = (unsigned int)-1;
2692 while (*args[myidx]) {
2693 const char *err;
2694
2695 if (strcmp(args[myidx], "size") == 0) {
2696 myidx++;
2697 if (!*(args[myidx])) {
2698 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2699 file, linenum, args[myidx-1]);
2700 err_code |= ERR_ALERT | ERR_FATAL;
2701 goto out;
2702 }
2703 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2704 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2705 file, linenum, *err, args[myidx-1]);
2706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
2708 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002709 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002710 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002711 else if (strcmp(args[myidx], "peers") == 0) {
2712 myidx++;
2713 if (!*(args[myidx])) {
2714 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2715 file, linenum, args[myidx-1]);
2716 err_code |= ERR_ALERT | ERR_FATAL;
2717 goto out;
2718 }
2719 curproxy->table.peers.name = strdup(args[myidx++]);
2720 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002721 else if (strcmp(args[myidx], "expire") == 0) {
2722 myidx++;
2723 if (!*(args[myidx])) {
2724 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2725 file, linenum, args[myidx-1]);
2726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
2728 }
2729 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2730 if (err) {
2731 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2732 file, linenum, *err, args[myidx-1]);
2733 err_code |= ERR_ALERT | ERR_FATAL;
2734 goto out;
2735 }
2736 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002737 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002738 }
2739 else if (strcmp(args[myidx], "nopurge") == 0) {
2740 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002741 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002742 }
2743 else if (strcmp(args[myidx], "type") == 0) {
2744 myidx++;
2745 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2746 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2747 file, linenum, args[myidx]);
2748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
2750 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002751 /* myidx already points to next arg */
2752 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002753 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002754 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002755 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002756
2757 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002758 nw = args[myidx];
2759 while (*nw) {
2760 /* the "store" keyword supports a comma-separated list */
2761 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002762 sa = NULL; /* store arg */
2763 while (*nw && *nw != ',') {
2764 if (*nw == '(') {
2765 *nw = 0;
2766 sa = ++nw;
2767 while (*nw != ')') {
2768 if (!*nw) {
2769 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2770 file, linenum, args[0], cw);
2771 err_code |= ERR_ALERT | ERR_FATAL;
2772 goto out;
2773 }
2774 nw++;
2775 }
2776 *nw = '\0';
2777 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002778 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002779 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002780 if (*nw)
2781 *nw++ = '\0';
2782 type = stktable_get_data_type(cw);
2783 if (type < 0) {
2784 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2785 file, linenum, args[0], cw);
2786 err_code |= ERR_ALERT | ERR_FATAL;
2787 goto out;
2788 }
Willy Tarreauac782882010-06-20 10:41:54 +02002789
2790 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2791 switch (err) {
2792 case PE_NONE: break;
2793 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002794 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2795 file, linenum, args[0], cw);
2796 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002797 break;
2798
2799 case PE_ARG_MISSING:
2800 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2801 file, linenum, args[0], cw);
2802 err_code |= ERR_ALERT | ERR_FATAL;
2803 goto out;
2804
2805 case PE_ARG_NOT_USED:
2806 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2807 file, linenum, args[0], cw);
2808 err_code |= ERR_ALERT | ERR_FATAL;
2809 goto out;
2810
2811 default:
2812 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2813 file, linenum, args[0], cw);
2814 err_code |= ERR_ALERT | ERR_FATAL;
2815 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002816 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002817 }
2818 myidx++;
2819 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002820 else {
2821 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2822 file, linenum, args[myidx]);
2823 err_code |= ERR_ALERT | ERR_FATAL;
2824 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002825 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002826 }
2827
2828 if (!curproxy->table.size) {
2829 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2830 file, linenum);
2831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
2833 }
2834
2835 if (curproxy->table.type == (unsigned int)-1) {
2836 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2837 file, linenum);
2838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
2840 }
2841 }
2842 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002843 struct sticking_rule *rule;
2844 struct pattern_expr *expr;
2845 int myidx = 0;
2846 const char *name = NULL;
2847 int flags;
2848
2849 if (curproxy == &defproxy) {
2850 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2851 err_code |= ERR_ALERT | ERR_FATAL;
2852 goto out;
2853 }
2854
2855 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2856 err_code |= ERR_WARN;
2857 goto out;
2858 }
2859
2860 myidx++;
2861 if ((strcmp(args[myidx], "store") == 0) ||
2862 (strcmp(args[myidx], "store-request") == 0)) {
2863 myidx++;
2864 flags = STK_IS_STORE;
2865 }
2866 else if (strcmp(args[myidx], "store-response") == 0) {
2867 myidx++;
2868 flags = STK_IS_STORE | STK_ON_RSP;
2869 }
2870 else if (strcmp(args[myidx], "match") == 0) {
2871 myidx++;
2872 flags = STK_IS_MATCH;
2873 }
2874 else if (strcmp(args[myidx], "on") == 0) {
2875 myidx++;
2876 flags = STK_IS_MATCH | STK_IS_STORE;
2877 }
2878 else {
2879 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
2882 }
2883
2884 if (*(args[myidx]) == 0) {
2885 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2886 err_code |= ERR_ALERT | ERR_FATAL;
2887 goto out;
2888 }
2889
Emeric Brun485479d2010-09-23 18:02:19 +02002890 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002891 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002892 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
2895 }
2896
2897 if (flags & STK_ON_RSP) {
2898 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2899 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2900 file, linenum, args[0], expr->fetch->kw);
2901 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002902 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002903 goto out;
2904 }
2905 } else {
2906 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2907 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2908 file, linenum, args[0], expr->fetch->kw);
2909 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002910 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002911 goto out;
2912 }
2913 }
2914
2915 if (strcmp(args[myidx], "table") == 0) {
2916 myidx++;
2917 name = args[myidx++];
2918 }
2919
Willy Tarreauef6494c2010-01-28 17:12:36 +01002920 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2921 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002922 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2923 file, linenum, args[0]);
2924 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002925 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002926 goto out;
2927 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002928 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002929 else if (*(args[myidx])) {
2930 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2931 file, linenum, args[0], args[myidx]);
2932 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002933 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002934 goto out;
2935 }
Emeric Brun97679e72010-09-23 17:56:44 +02002936 if (flags & STK_ON_RSP)
2937 err_code |= warnif_cond_requires_req(cond, file, linenum);
2938 else
2939 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002940
Emeric Brunb982a3d2010-01-04 15:45:53 +01002941 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2942 rule->cond = cond;
2943 rule->expr = expr;
2944 rule->flags = flags;
2945 rule->table.name = name ? strdup(name) : NULL;
2946 LIST_INIT(&rule->list);
2947 if (flags & STK_ON_RSP)
2948 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2949 else
2950 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2951 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002952 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002953 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002954 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002955
Willy Tarreaubaaee002006-06-26 02:48:02 +02002956 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2957 curproxy->uri_auth = NULL; /* we must detach from the default config */
2958
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002959 if (!*args[1]) {
2960 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002961 } else if (!strcmp(args[1], "admin")) {
2962 struct stats_admin_rule *rule;
2963
2964 if (curproxy == &defproxy) {
2965 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2966 err_code |= ERR_ALERT | ERR_FATAL;
2967 goto out;
2968 }
2969
2970 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2971 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2972 err_code |= ERR_ALERT | ERR_ABORT;
2973 goto out;
2974 }
2975
2976 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2977 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2978 file, linenum, args[0], args[1]);
2979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
2981 }
2982 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2983 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2984 file, linenum, args[0], args[1]);
2985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
2987 }
2988
2989 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2990
2991 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2992 rule->cond = cond;
2993 LIST_INIT(&rule->list);
2994 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002995 } else if (!strcmp(args[1], "uri")) {
2996 if (*(args[2]) == 0) {
2997 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002998 err_code |= ERR_ALERT | ERR_FATAL;
2999 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003000 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3001 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003002 err_code |= ERR_ALERT | ERR_ABORT;
3003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 }
3005 } else if (!strcmp(args[1], "realm")) {
3006 if (*(args[2]) == 0) {
3007 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3011 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003012 err_code |= ERR_ALERT | ERR_ABORT;
3013 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003015 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003016 unsigned interval;
3017
3018 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3019 if (err) {
3020 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3021 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003024 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3025 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003026 err_code |= ERR_ALERT | ERR_ABORT;
3027 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003028 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003029 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003030 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003031
3032 if (curproxy == &defproxy) {
3033 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
3036 }
3037
3038 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3039 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3040 err_code |= ERR_ALERT | ERR_ABORT;
3041 goto out;
3042 }
3043
Willy Tarreauff011f22011-01-06 17:51:27 +01003044 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3045 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003046 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3047 file, linenum, args[0]);
3048 err_code |= ERR_WARN;
3049 }
3050
Willy Tarreauff011f22011-01-06 17:51:27 +01003051 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003052
Willy Tarreauff011f22011-01-06 17:51:27 +01003053 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003054 err_code |= ERR_ALERT | ERR_ABORT;
3055 goto out;
3056 }
3057
Willy Tarreauff011f22011-01-06 17:51:27 +01003058 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3059 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003060
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 } else if (!strcmp(args[1], "auth")) {
3062 if (*(args[2]) == 0) {
3063 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3067 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_ABORT;
3069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 }
3071 } else if (!strcmp(args[1], "scope")) {
3072 if (*(args[2]) == 0) {
3073 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003074 err_code |= ERR_ALERT | ERR_FATAL;
3075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003076 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3077 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003078 err_code |= ERR_ALERT | ERR_ABORT;
3079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 }
3081 } else if (!strcmp(args[1], "enable")) {
3082 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3083 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003084 err_code |= ERR_ALERT | ERR_ABORT;
3085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003087 } else if (!strcmp(args[1], "hide-version")) {
3088 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3089 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003090 err_code |= ERR_ALERT | ERR_ABORT;
3091 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003092 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003093 } else if (!strcmp(args[1], "show-legends")) {
3094 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3095 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3096 err_code |= ERR_ALERT | ERR_ABORT;
3097 goto out;
3098 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003099 } else if (!strcmp(args[1], "show-node")) {
3100
3101 if (*args[2]) {
3102 int i;
3103 char c;
3104
3105 for (i=0; args[2][i]; i++) {
3106 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003107 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3108 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003109 break;
3110 }
3111
3112 if (!i || args[2][i]) {
3113 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3114 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3115 file, linenum, args[0], args[1]);
3116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
3118 }
3119 }
3120
3121 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3122 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3123 err_code |= ERR_ALERT | ERR_ABORT;
3124 goto out;
3125 }
3126 } else if (!strcmp(args[1], "show-desc")) {
3127 char *desc = NULL;
3128
3129 if (*args[2]) {
3130 int i, len=0;
3131 char *d;
3132
3133 for(i=2; *args[i]; i++)
3134 len += strlen(args[i])+1;
3135
3136 desc = d = (char *)calloc(1, len);
3137
3138 d += sprintf(d, "%s", args[2]);
3139 for(i=3; *args[i]; i++)
3140 d += sprintf(d, " %s", args[i]);
3141 }
3142
3143 if (!*args[2] && !global.desc)
3144 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3145 file, linenum, args[1]);
3146 else {
3147 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3148 free(desc);
3149 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3150 err_code |= ERR_ALERT | ERR_ABORT;
3151 goto out;
3152 }
3153 free(desc);
3154 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003156stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003157 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 +01003158 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003159 err_code |= ERR_ALERT | ERR_FATAL;
3160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003161 }
3162 }
3163 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003164 int optnum;
3165
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003166 if (*(args[1]) == '\0') {
3167 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3168 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003169 err_code |= ERR_ALERT | ERR_FATAL;
3170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003171 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003172
3173 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3174 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003175 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3176 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3177 file, linenum, cfg_opts[optnum].name);
3178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
3180 }
Willy Tarreau93893792009-07-23 13:19:11 +02003181 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3182 err_code |= ERR_WARN;
3183 goto out;
3184 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003185
Willy Tarreau3842f002009-06-14 11:39:52 +02003186 curproxy->no_options &= ~cfg_opts[optnum].val;
3187 curproxy->options &= ~cfg_opts[optnum].val;
3188
3189 switch (kwm) {
3190 case KWM_STD:
3191 curproxy->options |= cfg_opts[optnum].val;
3192 break;
3193 case KWM_NO:
3194 curproxy->no_options |= cfg_opts[optnum].val;
3195 break;
3196 case KWM_DEF: /* already cleared */
3197 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003198 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003199
Willy Tarreau93893792009-07-23 13:19:11 +02003200 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003201 }
3202 }
3203
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003204 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3205 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003206 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3207 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3208 file, linenum, cfg_opts2[optnum].name);
3209 err_code |= ERR_ALERT | ERR_FATAL;
3210 goto out;
3211 }
Willy Tarreau93893792009-07-23 13:19:11 +02003212 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3213 err_code |= ERR_WARN;
3214 goto out;
3215 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003216
Willy Tarreau3842f002009-06-14 11:39:52 +02003217 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3218 curproxy->options2 &= ~cfg_opts2[optnum].val;
3219
3220 switch (kwm) {
3221 case KWM_STD:
3222 curproxy->options2 |= cfg_opts2[optnum].val;
3223 break;
3224 case KWM_NO:
3225 curproxy->no_options2 |= cfg_opts2[optnum].val;
3226 break;
3227 case KWM_DEF: /* already cleared */
3228 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003229 }
Willy Tarreau93893792009-07-23 13:19:11 +02003230 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003231 }
3232 }
3233
Willy Tarreau3842f002009-06-14 11:39:52 +02003234 if (kwm != KWM_STD) {
3235 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003236 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003239 }
3240
Emeric Brun3a058f32009-06-30 18:26:00 +02003241 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003242 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003243 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003245 if (*(args[2]) != '\0') {
3246 if (!strcmp(args[2], "clf")) {
3247 curproxy->options2 |= PR_O2_CLFLOG;
3248 } else {
3249 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003252 }
3253 }
3254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003255 else if (!strcmp(args[1], "tcplog"))
3256 /* generate a detailed TCP log */
3257 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003258 else if (!strcmp(args[1], "tcpka")) {
3259 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003260 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003261 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003262
3263 if (curproxy->cap & PR_CAP_FE)
3264 curproxy->options |= PR_O_TCP_CLI_KA;
3265 if (curproxy->cap & PR_CAP_BE)
3266 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 }
3268 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003269 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003270 err_code |= ERR_WARN;
3271
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003273 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003274 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003275 curproxy->options2 &= ~PR_O2_CHK_ANY;
3276 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003277 if (!*args[2]) { /* no argument */
3278 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3279 curproxy->check_len = strlen(DEF_CHECK_REQ);
3280 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003281 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 curproxy->check_req = (char *)malloc(reqlen);
3283 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003284 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003286 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 if (*args[4])
3288 reqlen += strlen(args[4]);
3289 else
3290 reqlen += strlen("HTTP/1.0");
3291
3292 curproxy->check_req = (char *)malloc(reqlen);
3293 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003294 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003296 }
3297 else if (!strcmp(args[1], "ssl-hello-chk")) {
3298 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003299 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003300 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003301
Willy Tarreaua534fea2008-08-03 12:19:50 +02003302 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003303 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003304 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003305 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 }
Willy Tarreau23677902007-05-08 23:50:35 +02003307 else if (!strcmp(args[1], "smtpchk")) {
3308 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003309 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003310 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003311 curproxy->options2 &= ~PR_O2_CHK_ANY;
3312 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003313
3314 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3315 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3316 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3317 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3318 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3319 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3320 curproxy->check_req = (char *)malloc(reqlen);
3321 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3322 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3323 } else {
3324 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3325 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3326 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3327 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3328 }
3329 }
3330 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003331 else if (!strcmp(args[1], "pgsql-check")) {
3332 /* use PostgreSQL request to check servers' health */
3333 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3334 err_code |= ERR_WARN;
3335
3336 free(curproxy->check_req);
3337 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003338 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003339 curproxy->options2 |= PR_O2_PGSQL_CHK;
3340
3341 if (*(args[2])) {
3342 int cur_arg = 2;
3343
3344 while (*(args[cur_arg])) {
3345 if (strcmp(args[cur_arg], "user") == 0) {
3346 char * packet;
3347 uint32_t packet_len;
3348 uint32_t pv;
3349
3350 /* suboption header - needs additional argument for it */
3351 if (*(args[cur_arg+1]) == 0) {
3352 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3353 file, linenum, args[0], args[1], args[cur_arg]);
3354 err_code |= ERR_ALERT | ERR_FATAL;
3355 goto out;
3356 }
3357
3358 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3359 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3360 pv = htonl(0x30000); /* protocol version 3.0 */
3361
3362 packet = (char*) calloc(1, packet_len);
3363
3364 memcpy(packet + 4, &pv, 4);
3365
3366 /* copy "user" */
3367 memcpy(packet + 8, "user", 4);
3368
3369 /* copy username */
3370 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3371
3372 free(curproxy->check_req);
3373 curproxy->check_req = packet;
3374 curproxy->check_len = packet_len;
3375
3376 packet_len = htonl(packet_len);
3377 memcpy(packet, &packet_len, 4);
3378 cur_arg += 2;
3379 } else {
3380 /* unknown suboption - catchall */
3381 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3382 file, linenum, args[0], args[1]);
3383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
3385 }
3386 } /* end while loop */
3387 }
3388 }
3389
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003390 else if (!strcmp(args[1], "redis-check")) {
3391 /* use REDIS PING request to check servers' health */
3392 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3393 err_code |= ERR_WARN;
3394
3395 free(curproxy->check_req);
3396 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003397 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003398 curproxy->options2 |= PR_O2_REDIS_CHK;
3399
3400 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3401 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3402 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3403 }
3404
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003405 else if (!strcmp(args[1], "mysql-check")) {
3406 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003407 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3408 err_code |= ERR_WARN;
3409
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003410 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003411 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003412 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003413 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003414
3415 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3416 * const char mysql40_client_auth_pkt[] = {
3417 * "\x0e\x00\x00" // packet length
3418 * "\x01" // packet number
3419 * "\x00\x00" // client capabilities
3420 * "\x00\x00\x01" // max packet
3421 * "haproxy\x00" // username (null terminated string)
3422 * "\x00" // filler (always 0x00)
3423 * "\x01\x00\x00" // packet length
3424 * "\x00" // packet number
3425 * "\x01" // COM_QUIT command
3426 * };
3427 */
3428
3429 if (*(args[2])) {
3430 int cur_arg = 2;
3431
3432 while (*(args[cur_arg])) {
3433 if (strcmp(args[cur_arg], "user") == 0) {
3434 char *mysqluser;
3435 int packetlen, reqlen, userlen;
3436
3437 /* suboption header - needs additional argument for it */
3438 if (*(args[cur_arg+1]) == 0) {
3439 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3440 file, linenum, args[0], args[1], args[cur_arg]);
3441 err_code |= ERR_ALERT | ERR_FATAL;
3442 goto out;
3443 }
3444 mysqluser = args[cur_arg + 1];
3445 userlen = strlen(mysqluser);
3446 packetlen = userlen + 7;
3447 reqlen = packetlen + 9;
3448
3449 free(curproxy->check_req);
3450 curproxy->check_req = (char *)calloc(1, reqlen);
3451 curproxy->check_len = reqlen;
3452
3453 snprintf(curproxy->check_req, 4, "%c%c%c",
3454 ((unsigned char) packetlen & 0xff),
3455 ((unsigned char) (packetlen >> 8) & 0xff),
3456 ((unsigned char) (packetlen >> 16) & 0xff));
3457
3458 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003459 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003460 curproxy->check_req[8] = 1;
3461 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3462 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3463 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3464 cur_arg += 2;
3465 } else {
3466 /* unknown suboption - catchall */
3467 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3468 file, linenum, args[0], args[1]);
3469 err_code |= ERR_ALERT | ERR_FATAL;
3470 goto out;
3471 }
3472 } /* end while loop */
3473 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003474 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003475 else if (!strcmp(args[1], "ldap-check")) {
3476 /* use LDAP request to check servers' health */
3477 free(curproxy->check_req);
3478 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003479 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003480 curproxy->options2 |= PR_O2_LDAP_CHK;
3481
3482 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3483 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3484 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3485 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003486 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003487 int cur_arg;
3488
3489 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3490 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003491 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003492
Willy Tarreau87cf5142011-08-19 22:57:24 +02003493 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003494
3495 free(curproxy->fwdfor_hdr_name);
3496 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3497 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3498
3499 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3500 cur_arg = 2;
3501 while (*(args[cur_arg])) {
3502 if (!strcmp(args[cur_arg], "except")) {
3503 /* suboption except - needs additional argument for it */
3504 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3505 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3506 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003509 }
3510 /* flush useless bits */
3511 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003512 cur_arg += 2;
3513 } else if (!strcmp(args[cur_arg], "header")) {
3514 /* suboption header - needs additional argument for it */
3515 if (*(args[cur_arg+1]) == 0) {
3516 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3517 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003520 }
3521 free(curproxy->fwdfor_hdr_name);
3522 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3523 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3524 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003525 } else if (!strcmp(args[cur_arg], "if-none")) {
3526 curproxy->options &= ~PR_O_FF_ALWAYS;
3527 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003528 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003529 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003530 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003531 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003532 err_code |= ERR_ALERT | ERR_FATAL;
3533 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003534 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003535 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003536 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003537 else if (!strcmp(args[1], "originalto")) {
3538 int cur_arg;
3539
3540 /* insert x-original-to field, but not for the IP address listed as an except.
3541 * set default options (ie: bitfield, header name, etc)
3542 */
3543
3544 curproxy->options |= PR_O_ORGTO;
3545
3546 free(curproxy->orgto_hdr_name);
3547 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3548 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3549
Willy Tarreau87cf5142011-08-19 22:57:24 +02003550 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003551 cur_arg = 2;
3552 while (*(args[cur_arg])) {
3553 if (!strcmp(args[cur_arg], "except")) {
3554 /* suboption except - needs additional argument for it */
3555 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3556 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3557 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003558 err_code |= ERR_ALERT | ERR_FATAL;
3559 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003560 }
3561 /* flush useless bits */
3562 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3563 cur_arg += 2;
3564 } else if (!strcmp(args[cur_arg], "header")) {
3565 /* suboption header - needs additional argument for it */
3566 if (*(args[cur_arg+1]) == 0) {
3567 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3568 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003569 err_code |= ERR_ALERT | ERR_FATAL;
3570 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003571 }
3572 free(curproxy->orgto_hdr_name);
3573 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3574 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3575 cur_arg += 2;
3576 } else {
3577 /* unknown suboption - catchall */
3578 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3579 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003582 }
3583 } /* end while loop */
3584 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003585 else {
3586 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003589 }
Willy Tarreau93893792009-07-23 13:19:11 +02003590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003592 else if (!strcmp(args[0], "default_backend")) {
3593 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003594 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003595
3596 if (*(args[1]) == 0) {
3597 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003598 err_code |= ERR_ALERT | ERR_FATAL;
3599 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003600 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003601 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003602 curproxy->defbe.name = strdup(args[1]);
3603 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003604 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003605 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003607
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003608 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3609 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003610 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611 /* enable reconnections to dispatch */
3612 curproxy->options |= PR_O_REDISP;
3613 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003614 else if (!strcmp(args[0], "http-check")) {
3615 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003616 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003617
3618 if (strcmp(args[1], "disable-on-404") == 0) {
3619 /* enable a graceful server shutdown on an HTTP 404 response */
3620 curproxy->options |= PR_O_DISABLE404;
3621 }
Willy Tarreauef781042010-01-27 11:53:01 +01003622 else if (strcmp(args[1], "send-state") == 0) {
3623 /* enable emission of the apparent state of a server in HTTP checks */
3624 curproxy->options2 |= PR_O2_CHK_SNDST;
3625 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003626 else if (strcmp(args[1], "expect") == 0) {
3627 const char *ptr_arg;
3628 int cur_arg;
3629
3630 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3631 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3632 err_code |= ERR_ALERT | ERR_FATAL;
3633 goto out;
3634 }
3635
3636 cur_arg = 2;
3637 /* consider exclamation marks, sole or at the beginning of a word */
3638 while (*(ptr_arg = args[cur_arg])) {
3639 while (*ptr_arg == '!') {
3640 curproxy->options2 ^= PR_O2_EXP_INV;
3641 ptr_arg++;
3642 }
3643 if (*ptr_arg)
3644 break;
3645 cur_arg++;
3646 }
3647 /* now ptr_arg points to the beginning of a word past any possible
3648 * exclamation mark, and cur_arg is the argument which holds this word.
3649 */
3650 if (strcmp(ptr_arg, "status") == 0) {
3651 if (!*(args[cur_arg + 1])) {
3652 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3653 file, linenum, args[0], args[1], ptr_arg);
3654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
3656 }
3657 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003658 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003659 curproxy->expect_str = strdup(args[cur_arg + 1]);
3660 }
3661 else if (strcmp(ptr_arg, "string") == 0) {
3662 if (!*(args[cur_arg + 1])) {
3663 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3664 file, linenum, args[0], args[1], ptr_arg);
3665 err_code |= ERR_ALERT | ERR_FATAL;
3666 goto out;
3667 }
3668 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003669 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003670 curproxy->expect_str = strdup(args[cur_arg + 1]);
3671 }
3672 else if (strcmp(ptr_arg, "rstatus") == 0) {
3673 if (!*(args[cur_arg + 1])) {
3674 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3675 file, linenum, args[0], args[1], ptr_arg);
3676 err_code |= ERR_ALERT | ERR_FATAL;
3677 goto out;
3678 }
3679 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003680 free(curproxy->expect_str);
3681 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3682 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003683 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3684 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3685 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3686 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
3689 }
3690 }
3691 else if (strcmp(ptr_arg, "rstring") == 0) {
3692 if (!*(args[cur_arg + 1])) {
3693 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3694 file, linenum, args[0], args[1], ptr_arg);
3695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
3697 }
3698 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003699 free(curproxy->expect_str);
3700 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3701 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003702 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3703 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3704 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3705 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3706 err_code |= ERR_ALERT | ERR_FATAL;
3707 goto out;
3708 }
3709 }
3710 else {
3711 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3712 file, linenum, args[0], args[1], ptr_arg);
3713 err_code |= ERR_ALERT | ERR_FATAL;
3714 goto out;
3715 }
3716 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003717 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003718 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'send-state', 'expect'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003721 }
3722 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003723 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003724 if (curproxy == &defproxy) {
3725 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003728 }
3729
Willy Tarreaub80c2302007-11-30 20:51:32 +01003730 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003731 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003732
3733 if (strcmp(args[1], "fail") == 0) {
3734 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003735 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003736 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3737 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003740 }
3741
Willy Tarreauef6494c2010-01-28 17:12:36 +01003742 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003743 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3744 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_ALERT | ERR_FATAL;
3746 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003747 }
3748 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3749 }
3750 else {
3751 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003754 }
3755 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003756#ifdef TPROXY
3757 else if (!strcmp(args[0], "transparent")) {
3758 /* enable transparent proxy connections */
3759 curproxy->options |= PR_O_TRANSP;
3760 }
3761#endif
3762 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003763 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003764 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003765
Willy Tarreaubaaee002006-06-26 02:48:02 +02003766 if (*(args[1]) == 0) {
3767 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003770 }
3771 curproxy->maxconn = atol(args[1]);
3772 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003773 else if (!strcmp(args[0], "backlog")) { /* backlog */
3774 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003775 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003776
3777 if (*(args[1]) == 0) {
3778 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003781 }
3782 curproxy->backlog = atol(args[1]);
3783 }
Willy Tarreau86034312006-12-29 00:10:33 +01003784 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003785 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003787
Willy Tarreau86034312006-12-29 00:10:33 +01003788 if (*(args[1]) == 0) {
3789 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003790 err_code |= ERR_ALERT | ERR_FATAL;
3791 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003792 }
3793 curproxy->fullconn = atol(args[1]);
3794 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3796 if (*(args[1]) == 0) {
3797 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003800 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003801 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3802 if (err) {
3803 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3804 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003805 err_code |= ERR_ALERT | ERR_FATAL;
3806 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003807 }
3808 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 }
3810 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003811 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003812 if (curproxy == &defproxy) {
3813 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003814 err_code |= ERR_ALERT | ERR_FATAL;
3815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003816 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003817 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003819
Willy Tarreaubaaee002006-06-26 02:48:02 +02003820 if (strchr(args[1], ':') == NULL) {
3821 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003825 sk = str2sa(args[1]);
3826 if (!sk) {
3827 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
3830 }
3831 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003832 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 }
3834 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003835 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003836 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003837
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003838 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003839 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3840 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003843 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003845 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3846 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3847 err_code |= ERR_WARN;
3848
3849 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3850 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3851 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3852 }
3853 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3854 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3855 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3856 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003857 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3858 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3859 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3860 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003861 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003862 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003863 err_code |= ERR_ALERT | ERR_FATAL;
3864 goto out;
3865 }
3866 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003867 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003869 char *rport, *raddr;
3870 short realport = 0;
3871 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003872
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003873 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003874 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003877 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003878 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003879 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003880
3881 if (!*args[2]) {
3882 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3883 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003884 err_code |= ERR_ALERT | ERR_FATAL;
3885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003887
3888 err = invalid_char(args[1]);
3889 if (err) {
3890 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3891 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003894 }
3895
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003896 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003897 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003898
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003899 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3900 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3901 err_code |= ERR_ALERT | ERR_ABORT;
3902 goto out;
3903 }
3904
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003905 /* the servers are linked backwards first */
3906 newsrv->next = curproxy->srv;
3907 curproxy->srv = newsrv;
3908 newsrv->proxy = curproxy;
3909 newsrv->conf.file = file;
3910 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003911
Simon Hormanaf514952011-06-21 14:34:57 +09003912 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003913 LIST_INIT(&newsrv->pendconns);
3914 do_check = 0;
3915 newsrv->state = SRV_RUNNING; /* early server setup */
3916 newsrv->last_change = now.tv_sec;
3917 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003918
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003919 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003920 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003921 * - IP: => port=+0, relative
3922 * - IP:N => port=N, absolute
3923 * - IP:+N => port=+N, relative
3924 * - IP:-N => port=-N, relative
3925 */
3926 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003927 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003928 if (rport) {
3929 *rport++ = 0;
3930 realport = atol(rport);
3931 if (!isdigit((unsigned char)*rport))
3932 newsrv->state |= SRV_MAPPORTS;
3933 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003934 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003935
Willy Tarreaufab5a432011-03-04 15:31:53 +01003936 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003937 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003938 if (!sk) {
3939 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
3942 }
3943 newsrv->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02003944 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003945
3946 newsrv->check_port = curproxy->defsrv.check_port;
3947 newsrv->inter = curproxy->defsrv.inter;
3948 newsrv->fastinter = curproxy->defsrv.fastinter;
3949 newsrv->downinter = curproxy->defsrv.downinter;
3950 newsrv->rise = curproxy->defsrv.rise;
3951 newsrv->fall = curproxy->defsrv.fall;
3952 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3953 newsrv->minconn = curproxy->defsrv.minconn;
3954 newsrv->maxconn = curproxy->defsrv.maxconn;
3955 newsrv->slowstart = curproxy->defsrv.slowstart;
3956 newsrv->onerror = curproxy->defsrv.onerror;
3957 newsrv->consecutive_errors_limit
3958 = curproxy->defsrv.consecutive_errors_limit;
3959 newsrv->uweight = newsrv->iweight
3960 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003961
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003962 newsrv->curfd = -1; /* no health-check in progress */
3963 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003964
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003965 cur_arg = 3;
3966 } else {
3967 newsrv = &curproxy->defsrv;
3968 cur_arg = 1;
3969 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003970
Willy Tarreaubaaee002006-06-26 02:48:02 +02003971 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003972 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003973 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003974
3975 if (!*args[cur_arg + 1]) {
3976 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3977 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003978 err_code |= ERR_ALERT | ERR_FATAL;
3979 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003980 }
3981
3982 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003983 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003984
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003985 if (newsrv->puid <= 0) {
3986 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003987 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003990 }
3991
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003992 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3993 if (node) {
3994 struct server *target = container_of(node, struct server, conf.id);
3995 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3996 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
3999 }
4000 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004001 cur_arg += 2;
4002 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004003 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004 newsrv->cookie = strdup(args[cur_arg + 1]);
4005 newsrv->cklen = strlen(args[cur_arg + 1]);
4006 cur_arg += 2;
4007 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004008 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004009 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4010 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4011 cur_arg += 2;
4012 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004013 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004014 if (!*args[cur_arg + 1]) {
4015 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4016 file, linenum, args[cur_arg]);
4017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
4019 }
4020
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004022 if (newsrv->rise <= 0) {
4023 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4024 file, linenum, args[cur_arg]);
4025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
4027 }
4028
Willy Tarreau96839092010-03-29 10:02:24 +02004029 if (newsrv->health)
4030 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031 cur_arg += 2;
4032 }
4033 else if (!strcmp(args[cur_arg], "fall")) {
4034 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004035
4036 if (!*args[cur_arg + 1]) {
4037 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4038 file, linenum, args[cur_arg]);
4039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
4041 }
4042
4043 if (newsrv->fall <= 0) {
4044 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4045 file, linenum, args[cur_arg]);
4046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
4048 }
4049
Willy Tarreaubaaee002006-06-26 02:48:02 +02004050 cur_arg += 2;
4051 }
4052 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004053 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4054 if (err) {
4055 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4056 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004057 err_code |= ERR_ALERT | ERR_FATAL;
4058 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004059 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004060 if (val <= 0) {
4061 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4062 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004063 err_code |= ERR_ALERT | ERR_FATAL;
4064 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004065 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004066 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004067 cur_arg += 2;
4068 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004069 else if (!strcmp(args[cur_arg], "fastinter")) {
4070 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4071 if (err) {
4072 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4073 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004076 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004077 if (val <= 0) {
4078 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4079 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004080 err_code |= ERR_ALERT | ERR_FATAL;
4081 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004082 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004083 newsrv->fastinter = val;
4084 cur_arg += 2;
4085 }
4086 else if (!strcmp(args[cur_arg], "downinter")) {
4087 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4088 if (err) {
4089 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4090 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004091 err_code |= ERR_ALERT | ERR_FATAL;
4092 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004093 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004094 if (val <= 0) {
4095 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4096 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004099 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004100 newsrv->downinter = val;
4101 cur_arg += 2;
4102 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004103 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004104 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004105 if (!sk) {
4106 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
4109 }
4110 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004111 cur_arg += 2;
4112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004113 else if (!strcmp(args[cur_arg], "port")) {
4114 newsrv->check_port = atol(args[cur_arg + 1]);
4115 cur_arg += 2;
4116 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004117 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004118 newsrv->state |= SRV_BACKUP;
4119 cur_arg ++;
4120 }
Simon Hormanfa461682011-06-25 09:39:49 +09004121 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4122 newsrv->state |= SRV_NON_STICK;
4123 cur_arg ++;
4124 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004125 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4126 newsrv->state |= SRV_SEND_PROXY;
4127 cur_arg ++;
4128 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004129 else if (!strcmp(args[cur_arg], "weight")) {
4130 int w;
4131 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004132 if (w < 0 || w > 256) {
4133 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004134 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004135 err_code |= ERR_ALERT | ERR_FATAL;
4136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004137 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004138 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004139 cur_arg += 2;
4140 }
4141 else if (!strcmp(args[cur_arg], "minconn")) {
4142 newsrv->minconn = atol(args[cur_arg + 1]);
4143 cur_arg += 2;
4144 }
4145 else if (!strcmp(args[cur_arg], "maxconn")) {
4146 newsrv->maxconn = atol(args[cur_arg + 1]);
4147 cur_arg += 2;
4148 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004149 else if (!strcmp(args[cur_arg], "maxqueue")) {
4150 newsrv->maxqueue = atol(args[cur_arg + 1]);
4151 cur_arg += 2;
4152 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004153 else if (!strcmp(args[cur_arg], "slowstart")) {
4154 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004155 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004156 if (err) {
4157 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4158 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004159 err_code |= ERR_ALERT | ERR_FATAL;
4160 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004161 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004162 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004163 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4164 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004165 err_code |= ERR_ALERT | ERR_FATAL;
4166 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004167 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004168 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004169 cur_arg += 2;
4170 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004171 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004172
4173 if (!*args[cur_arg + 1]) {
4174 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4175 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004178 }
4179
4180 newsrv->trackit = strdup(args[cur_arg + 1]);
4181
4182 cur_arg += 2;
4183 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004184 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004185 global.maxsock++;
4186 do_check = 1;
4187 cur_arg += 1;
4188 }
Willy Tarreau96839092010-03-29 10:02:24 +02004189 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4190 newsrv->state |= SRV_MAINTAIN;
4191 newsrv->state &= ~SRV_RUNNING;
4192 newsrv->health = 0;
4193 cur_arg += 1;
4194 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004195 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004196 if (!strcmp(args[cur_arg + 1], "none"))
4197 newsrv->observe = HANA_OBS_NONE;
4198 else if (!strcmp(args[cur_arg + 1], "layer4"))
4199 newsrv->observe = HANA_OBS_LAYER4;
4200 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4201 if (curproxy->mode != PR_MODE_HTTP) {
4202 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4203 file, linenum, args[cur_arg + 1]);
4204 err_code |= ERR_ALERT;
4205 }
4206 newsrv->observe = HANA_OBS_LAYER7;
4207 }
4208 else {
4209 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004210 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004211 file, linenum, args[cur_arg], args[cur_arg + 1]);
4212 err_code |= ERR_ALERT | ERR_FATAL;
4213 goto out;
4214 }
4215
4216 cur_arg += 2;
4217 }
4218 else if (!strcmp(args[cur_arg], "on-error")) {
4219 if (!strcmp(args[cur_arg + 1], "fastinter"))
4220 newsrv->onerror = HANA_ONERR_FASTINTER;
4221 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4222 newsrv->onerror = HANA_ONERR_FAILCHK;
4223 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4224 newsrv->onerror = HANA_ONERR_SUDDTH;
4225 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4226 newsrv->onerror = HANA_ONERR_MARKDWN;
4227 else {
4228 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004229 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004230 file, linenum, args[cur_arg], args[cur_arg + 1]);
4231 err_code |= ERR_ALERT | ERR_FATAL;
4232 goto out;
4233 }
4234
4235 cur_arg += 2;
4236 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004237 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4238 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4239 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4240 else {
4241 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4242 file, linenum, args[cur_arg], args[cur_arg + 1]);
4243 err_code |= ERR_ALERT | ERR_FATAL;
4244 goto out;
4245 }
4246
4247 cur_arg += 2;
4248 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004249 else if (!strcmp(args[cur_arg], "error-limit")) {
4250 if (!*args[cur_arg + 1]) {
4251 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4252 file, linenum, args[cur_arg]);
4253 err_code |= ERR_ALERT | ERR_FATAL;
4254 goto out;
4255 }
4256
4257 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4258
4259 if (newsrv->consecutive_errors_limit <= 0) {
4260 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4261 file, linenum, args[cur_arg]);
4262 err_code |= ERR_ALERT | ERR_FATAL;
4263 goto out;
4264 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004265 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004266 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004267 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004268 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004269 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004270
Willy Tarreaubaaee002006-06-26 02:48:02 +02004271 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004272#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004273 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004274 file, linenum, "source", "usesrc");
4275#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004276 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004277 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004278#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004279 err_code |= ERR_ALERT | ERR_FATAL;
4280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004281 }
4282 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004283 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4284 if (!sk) {
4285 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4286 err_code |= ERR_ALERT | ERR_FATAL;
4287 goto out;
4288 }
4289 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004290
4291 if (port_low != port_high) {
4292 int i;
4293 if (port_low <= 0 || port_low > 65535 ||
4294 port_high <= 0 || port_high > 65535 ||
4295 port_low > port_high) {
4296 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4297 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004298 err_code |= ERR_ALERT | ERR_FATAL;
4299 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004300 }
4301 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4302 for (i = 0; i < newsrv->sport_range->size; i++)
4303 newsrv->sport_range->ports[i] = port_low + i;
4304 }
4305
Willy Tarreaubaaee002006-06-26 02:48:02 +02004306 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004307 while (*(args[cur_arg])) {
4308 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004309#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4310#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004311 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4312 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4313 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004314 err_code |= ERR_ALERT | ERR_FATAL;
4315 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004316 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004317#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004318 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004319 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004320 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004323 }
4324 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004325 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004326 newsrv->state |= SRV_TPROXY_CLI;
4327 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004328 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004329 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004330 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4331 char *name, *end;
4332
4333 name = args[cur_arg+1] + 7;
4334 while (isspace(*name))
4335 name++;
4336
4337 end = name;
4338 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4339 end++;
4340
4341 newsrv->state &= ~SRV_TPROXY_MASK;
4342 newsrv->state |= SRV_TPROXY_DYN;
4343 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4344 newsrv->bind_hdr_len = end - name;
4345 memcpy(newsrv->bind_hdr_name, name, end - name);
4346 newsrv->bind_hdr_name[end-name] = '\0';
4347 newsrv->bind_hdr_occ = -1;
4348
4349 /* now look for an occurrence number */
4350 while (isspace(*end))
4351 end++;
4352 if (*end == ',') {
4353 end++;
4354 name = end;
4355 if (*end == '-')
4356 end++;
4357 while (isdigit(*end))
4358 end++;
4359 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4360 }
4361
4362 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4363 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4364 " occurrences values smaller than %d.\n",
4365 file, linenum, MAX_HDR_HISTORY);
4366 err_code |= ERR_ALERT | ERR_FATAL;
4367 goto out;
4368 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004369 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004370 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004371 if (!sk) {
4372 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4373 err_code |= ERR_ALERT | ERR_FATAL;
4374 goto out;
4375 }
4376 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004377 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004378 }
4379 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004380#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004381 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004382#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004383 cur_arg += 2;
4384 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004385#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004386 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004387 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004388 err_code |= ERR_ALERT | ERR_FATAL;
4389 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004390#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4391 } /* "usesrc" */
4392
4393 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4394#ifdef SO_BINDTODEVICE
4395 if (!*args[cur_arg + 1]) {
4396 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4397 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004400 }
4401 if (newsrv->iface_name)
4402 free(newsrv->iface_name);
4403
4404 newsrv->iface_name = strdup(args[cur_arg + 1]);
4405 newsrv->iface_len = strlen(newsrv->iface_name);
4406 global.last_checks |= LSTCHK_NETADM;
4407#else
4408 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4409 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004410 err_code |= ERR_ALERT | ERR_FATAL;
4411 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004412#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004413 cur_arg += 2;
4414 continue;
4415 }
4416 /* this keyword in not an option of "source" */
4417 break;
4418 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004419 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004420 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004421 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4422 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004423 err_code |= ERR_ALERT | ERR_FATAL;
4424 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004426 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004427 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004428 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 +01004429 file, linenum, newsrv->id);
4430 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004431 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 +01004432 file, linenum);
4433
Willy Tarreau93893792009-07-23 13:19:11 +02004434 err_code |= ERR_ALERT | ERR_FATAL;
4435 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004436 }
4437 }
4438
4439 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004440 if (newsrv->trackit) {
4441 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4442 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004443 err_code |= ERR_ALERT | ERR_FATAL;
4444 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004445 }
4446
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004447 /* try to get the port from check_addr if check_port not set */
4448 if (!newsrv->check_port)
4449 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004450
Willy Tarreaubaaee002006-06-26 02:48:02 +02004451 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4452 newsrv->check_port = realport; /* by default */
4453 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004454 /* not yet valid, because no port was set on
4455 * the server either. We'll check if we have
4456 * a known port on the first listener.
4457 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004458 struct listener *l = curproxy->listen;
4459 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4460 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004461 }
4462 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004463 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4464 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004465 err_code |= ERR_ALERT | ERR_FATAL;
4466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004467 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004468
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004469 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004470 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004471 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4472 err_code |= ERR_ALERT | ERR_ABORT;
4473 goto out;
4474 }
4475
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004476 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004477 newsrv->state |= SRV_CHECKED;
4478 }
4479
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004480 if (!defsrv) {
4481 if (newsrv->state & SRV_BACKUP)
4482 curproxy->srv_bck++;
4483 else
4484 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004485
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004486 newsrv->prev_state = newsrv->state;
4487 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004488 }
4489 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004490 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004491 int facility;
4492
4493 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4494 curproxy->logfac1 = global.logfac1;
4495 curproxy->logsrv1 = global.logsrv1;
4496 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004497 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004498 curproxy->logfac2 = global.logfac2;
4499 curproxy->logsrv2 = global.logsrv2;
4500 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004501 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004502 }
4503 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004504 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505
4506 facility = get_log_facility(args[2]);
4507 if (facility < 0) {
4508 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4509 exit(1);
4510 }
4511
4512 level = 7; /* max syslog level = debug */
4513 if (*(args[3])) {
4514 level = get_log_level(args[3]);
4515 if (level < 0) {
4516 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4517 exit(1);
4518 }
4519 }
4520
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004521 minlvl = 0; /* limit syslog level to this level (emerg) */
4522 if (*(args[4])) {
4523 minlvl = get_log_level(args[4]);
4524 if (level < 0) {
4525 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4526 exit(1);
4527 }
4528 }
4529
Robert Tsai81ae1952007-12-05 10:47:29 +01004530 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004531 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004532 if (!sk) {
4533 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004534 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
4537 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004538 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004539 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004540 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004541 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004542 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4543 err_code |= ERR_ALERT | ERR_FATAL;
4544 goto out;
4545 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004546 logsrv.addr = *sk;
4547 if (!get_host_port(&logsrv.addr))
4548 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004550
4551 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004552 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004553 curproxy->logfac1 = facility;
4554 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004555 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004556 }
4557 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004558 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004559 curproxy->logfac2 = facility;
4560 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004561 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004562 }
4563 else {
4564 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004567 }
4568 }
4569 else {
4570 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4571 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004572 err_code |= ERR_ALERT | ERR_FATAL;
4573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004574 }
4575 }
4576 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004577 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004578 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004579
Willy Tarreau977b8e42006-12-29 14:19:17 +01004580 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004581 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004582
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004584 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4585 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004586 err_code |= ERR_ALERT | ERR_FATAL;
4587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004588 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004589
4590 /* we must first clear any optional default setting */
4591 curproxy->options &= ~PR_O_TPXY_MASK;
4592 free(curproxy->iface_name);
4593 curproxy->iface_name = NULL;
4594 curproxy->iface_len = 0;
4595
Willy Tarreaud5191e72010-02-09 20:50:45 +01004596 sk = str2sa(args[1]);
4597 if (!sk) {
4598 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
4601 }
4602 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004603 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004604
4605 cur_arg = 2;
4606 while (*(args[cur_arg])) {
4607 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004608#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4609#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004610 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4611 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4612 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004613 err_code |= ERR_ALERT | ERR_FATAL;
4614 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004615 }
4616#endif
4617 if (!*args[cur_arg + 1]) {
4618 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4619 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004620 err_code |= ERR_ALERT | ERR_FATAL;
4621 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004622 }
4623
4624 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004625 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004626 curproxy->options |= PR_O_TPXY_CLI;
4627 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004628 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004629 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004630 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4631 char *name, *end;
4632
4633 name = args[cur_arg+1] + 7;
4634 while (isspace(*name))
4635 name++;
4636
4637 end = name;
4638 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4639 end++;
4640
4641 curproxy->options &= ~PR_O_TPXY_MASK;
4642 curproxy->options |= PR_O_TPXY_DYN;
4643 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4644 curproxy->bind_hdr_len = end - name;
4645 memcpy(curproxy->bind_hdr_name, name, end - name);
4646 curproxy->bind_hdr_name[end-name] = '\0';
4647 curproxy->bind_hdr_occ = -1;
4648
4649 /* now look for an occurrence number */
4650 while (isspace(*end))
4651 end++;
4652 if (*end == ',') {
4653 end++;
4654 name = end;
4655 if (*end == '-')
4656 end++;
4657 while (isdigit(*end))
4658 end++;
4659 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4660 }
4661
4662 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4663 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4664 " occurrences values smaller than %d.\n",
4665 file, linenum, MAX_HDR_HISTORY);
4666 err_code |= ERR_ALERT | ERR_FATAL;
4667 goto out;
4668 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004669 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004670 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004671 if (!sk) {
4672 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4673 err_code |= ERR_ALERT | ERR_FATAL;
4674 goto out;
4675 }
4676 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004677 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004678 }
4679 global.last_checks |= LSTCHK_NETADM;
4680#if !defined(CONFIG_HAP_LINUX_TPROXY)
4681 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004682#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004683#else /* no TPROXY support */
4684 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004685 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004686 err_code |= ERR_ALERT | ERR_FATAL;
4687 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004688#endif
4689 cur_arg += 2;
4690 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004691 }
4692
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004693 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4694#ifdef SO_BINDTODEVICE
4695 if (!*args[cur_arg + 1]) {
4696 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4697 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004698 err_code |= ERR_ALERT | ERR_FATAL;
4699 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004700 }
4701 if (curproxy->iface_name)
4702 free(curproxy->iface_name);
4703
4704 curproxy->iface_name = strdup(args[cur_arg + 1]);
4705 curproxy->iface_len = strlen(curproxy->iface_name);
4706 global.last_checks |= LSTCHK_NETADM;
4707#else
4708 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4709 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004710 err_code |= ERR_ALERT | ERR_FATAL;
4711 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004712#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004713 cur_arg += 2;
4714 continue;
4715 }
4716 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4717 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004720 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004721 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004722 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4723 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4724 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004725 err_code |= ERR_ALERT | ERR_FATAL;
4726 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004728 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004729 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004730 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4731 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004732 err_code |= ERR_ALERT | ERR_FATAL;
4733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004734 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004735
4736 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4737 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004738 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004739 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004741 }
4742 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004743 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4744 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004745 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004746 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004748 }
4749 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004750 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4751 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004752 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004753 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004754 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004755 }
4756 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004757 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4758 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004759 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004760 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004762 }
4763 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004764 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4765 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004766 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004767 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004770 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004771 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4772 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004773 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004774 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004775 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004776 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004777 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004778 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4779 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004780 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004781 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004782 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004783 }
4784 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004785 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4786 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004787 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004788 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004789 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004790 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004791 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004792 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4794 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004795 err_code |= ERR_ALERT | ERR_FATAL;
4796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004797 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004798
4799 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4800 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004801 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004802 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004804 }
4805 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004806 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4807 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004808 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004809 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004811 }
4812 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004813 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4814 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004815 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004816 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004818 }
4819 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004820 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4821 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004822 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004823 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004825 }
4826 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004827 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4828 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004829 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004830 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004832 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004833 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004834 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4835 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004836 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004837 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004838 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004841 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004842
Willy Tarreaubaaee002006-06-26 02:48:02 +02004843 if (curproxy == &defproxy) {
4844 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004845 err_code |= ERR_ALERT | ERR_FATAL;
4846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004847 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004848 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004849 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004850
Willy Tarreaubaaee002006-06-26 02:48:02 +02004851 if (*(args[1]) == 0) {
4852 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004853 err_code |= ERR_ALERT | ERR_FATAL;
4854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004856
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004857 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4858 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4859 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4860 file, linenum, args[0]);
4861 err_code |= ERR_ALERT | ERR_FATAL;
4862 goto out;
4863 }
4864 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4865 }
4866 else if (*args[2]) {
4867 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4868 file, linenum, args[0], args[2]);
4869 err_code |= ERR_ALERT | ERR_FATAL;
4870 goto out;
4871 }
4872
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004873 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004874 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004875 wl->s = strdup(args[1]);
4876 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004877 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 }
4879 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004880 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004881 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4882 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
Willy Tarreauade5ec42010-01-28 19:33:49 +01004887 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4888 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004889 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004890 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004892 }
4893 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004894 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4895 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004896 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004897 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004899 }
4900 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004901 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4902 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004903 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004904 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 }
4907 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004908 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004909 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4910 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004911 err_code |= ERR_ALERT | ERR_FATAL;
4912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913 }
4914
Willy Tarreauade5ec42010-01-28 19:33:49 +01004915 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4916 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004917 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004918 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 }
4921 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004922 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4923 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004924 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004925 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004927 }
4928 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004929 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4930 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004931 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004932 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004934 }
4935 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004936 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004937
Willy Tarreaubaaee002006-06-26 02:48:02 +02004938 if (curproxy == &defproxy) {
4939 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004940 err_code |= ERR_ALERT | ERR_FATAL;
4941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004942 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004943 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004944 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 if (*(args[1]) == 0) {
4947 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 }
4951
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004952 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4953 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4954 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4955 file, linenum, args[0]);
4956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
4958 }
4959 err_code |= warnif_cond_requires_req(cond, file, linenum);
4960 }
4961 else if (*args[2]) {
4962 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4963 file, linenum, args[0], args[2]);
4964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
4966 }
4967
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004968 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004969 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004970 wl->s = strdup(args[1]);
4971 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 }
4973 else if (!strcmp(args[0], "errorloc") ||
4974 !strcmp(args[0], "errorloc302") ||
4975 !strcmp(args[0], "errorloc303")) { /* error location */
4976 int errnum, errlen;
4977 char *err;
4978
Willy Tarreau977b8e42006-12-29 14:19:17 +01004979 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004980 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004981
Willy Tarreaubaaee002006-06-26 02:48:02 +02004982 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004983 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004984 err_code |= ERR_ALERT | ERR_FATAL;
4985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004986 }
4987
4988 errnum = atol(args[1]);
4989 if (!strcmp(args[0], "errorloc303")) {
4990 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4991 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4992 } else {
4993 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4994 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4995 }
4996
Willy Tarreau0f772532006-12-23 20:51:41 +01004997 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4998 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004999 chunk_destroy(&curproxy->errmsg[rc]);
5000 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005001 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005002 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005004
5005 if (rc >= HTTP_ERR_SIZE) {
5006 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5007 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005008 free(err);
5009 }
5010 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005011 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5012 int errnum, errlen, fd;
5013 char *err;
5014 struct stat stat;
5015
5016 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005017 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005018
5019 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005020 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005023 }
5024
5025 fd = open(args[2], O_RDONLY);
5026 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5027 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5028 file, linenum, args[2], args[1]);
5029 if (fd >= 0)
5030 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005033 }
5034
Willy Tarreau27a674e2009-08-17 07:23:33 +02005035 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005036 errlen = stat.st_size;
5037 } else {
5038 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005039 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005040 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005041 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005042 }
5043
5044 err = malloc(errlen); /* malloc() must succeed during parsing */
5045 errnum = read(fd, err, errlen);
5046 if (errnum != errlen) {
5047 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5048 file, linenum, args[2], args[1]);
5049 close(fd);
5050 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005053 }
5054 close(fd);
5055
5056 errnum = atol(args[1]);
5057 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5058 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005059 chunk_destroy(&curproxy->errmsg[rc]);
5060 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005061 break;
5062 }
5063 }
5064
5065 if (rc >= HTTP_ERR_SIZE) {
5066 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5067 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005069 free(err);
5070 }
5071 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005072 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005073 struct cfg_kw_list *kwl;
5074 int index;
5075
5076 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5077 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5078 if (kwl->kw[index].section != CFG_LISTEN)
5079 continue;
5080 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5081 /* prepare error message just in case */
5082 snprintf(trash, sizeof(trash),
5083 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005084 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5085 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005086 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005089 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005090 else if (rc > 0) {
5091 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005092 err_code |= ERR_WARN;
5093 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005094 }
Willy Tarreau93893792009-07-23 13:19:11 +02005095 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005096 }
5097 }
5098 }
5099
Willy Tarreau6daf3432008-01-22 16:44:08 +01005100 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005103 }
Willy Tarreau93893792009-07-23 13:19:11 +02005104 out:
5105 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005106}
5107
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005108int
5109cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5110{
5111
5112 int err_code = 0;
5113 const char *err;
5114
5115 if (!strcmp(args[0], "userlist")) { /* new userlist */
5116 struct userlist *newul;
5117
5118 if (!*args[1]) {
5119 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5120 file, linenum, args[0]);
5121 err_code |= ERR_ALERT | ERR_FATAL;
5122 goto out;
5123 }
5124
5125 err = invalid_char(args[1]);
5126 if (err) {
5127 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5128 file, linenum, *err, args[0], args[1]);
5129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
5131 }
5132
5133 for (newul = userlist; newul; newul = newul->next)
5134 if (!strcmp(newul->name, args[1])) {
5135 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5136 file, linenum, args[1]);
5137 err_code |= ERR_WARN;
5138 goto out;
5139 }
5140
5141 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5142 if (!newul) {
5143 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5144 err_code |= ERR_ALERT | ERR_ABORT;
5145 goto out;
5146 }
5147
5148 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5149 newul->name = strdup(args[1]);
5150
5151 if (!newul->groupusers | !newul->name) {
5152 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5153 err_code |= ERR_ALERT | ERR_ABORT;
5154 goto out;
5155 }
5156
5157 newul->next = userlist;
5158 userlist = newul;
5159
5160 } else if (!strcmp(args[0], "group")) { /* new group */
5161 int cur_arg, i;
5162 const char *err;
5163
5164 if (!*args[1]) {
5165 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5166 file, linenum, args[0]);
5167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
5169 }
5170
5171 err = invalid_char(args[1]);
5172 if (err) {
5173 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5174 file, linenum, *err, args[0], args[1]);
5175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
5177 }
5178
5179 for(i = 0; i < userlist->grpcnt; i++)
5180 if (!strcmp(userlist->groups[i], args[1])) {
5181 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5182 file, linenum, args[1], userlist->name);
5183 err_code |= ERR_ALERT;
5184 goto out;
5185 }
5186
5187 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5188 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5189 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
5192 }
5193
5194 cur_arg = 2;
5195
5196 while (*args[cur_arg]) {
5197 if (!strcmp(args[cur_arg], "users")) {
5198 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5199 cur_arg += 2;
5200 continue;
5201 } else {
5202 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5203 file, linenum, args[0]);
5204 err_code |= ERR_ALERT | ERR_FATAL;
5205 goto out;
5206 }
5207 }
5208
5209 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5210 } else if (!strcmp(args[0], "user")) { /* new user */
5211 struct auth_users *newuser;
5212 int cur_arg;
5213
5214 if (!*args[1]) {
5215 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5216 file, linenum, args[0]);
5217 err_code |= ERR_ALERT | ERR_FATAL;
5218 goto out;
5219 }
5220
5221 for (newuser = userlist->users; newuser; newuser = newuser->next)
5222 if (!strcmp(newuser->user, args[1])) {
5223 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5224 file, linenum, args[1], userlist->name);
5225 err_code |= ERR_ALERT;
5226 goto out;
5227 }
5228
5229 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5230 if (!newuser) {
5231 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5232 err_code |= ERR_ALERT | ERR_ABORT;
5233 goto out;
5234 }
5235
5236 newuser->user = strdup(args[1]);
5237
5238 newuser->next = userlist->users;
5239 userlist->users = newuser;
5240
5241 cur_arg = 2;
5242
5243 while (*args[cur_arg]) {
5244 if (!strcmp(args[cur_arg], "password")) {
5245#ifndef CONFIG_HAP_CRYPT
5246 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5247 file, linenum);
5248 err_code |= ERR_ALERT;
5249#endif
5250 newuser->pass = strdup(args[cur_arg + 1]);
5251 cur_arg += 2;
5252 continue;
5253 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5254 newuser->pass = strdup(args[cur_arg + 1]);
5255 newuser->flags |= AU_O_INSECURE;
5256 cur_arg += 2;
5257 continue;
5258 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005259 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005260 cur_arg += 2;
5261 continue;
5262 } else {
5263 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5264 file, linenum, args[0]);
5265 err_code |= ERR_ALERT | ERR_FATAL;
5266 goto out;
5267 }
5268 }
5269 } else {
5270 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5271 err_code |= ERR_ALERT | ERR_FATAL;
5272 }
5273
5274out:
5275 return err_code;
5276}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005277
5278/*
5279 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005280 * Returns the error code, 0 if OK, or any combination of :
5281 * - ERR_ABORT: must abort ASAP
5282 * - ERR_FATAL: we can continue parsing but not start the service
5283 * - ERR_WARN: a warning has been emitted
5284 * - ERR_ALERT: an alert has been emitted
5285 * Only the two first ones can stop processing, the two others are just
5286 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005287 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005288int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005290 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291 FILE *f;
5292 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005293 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005294 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 if ((f=fopen(file,"r")) == NULL)
5297 return -1;
5298
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005299 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005300 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005301 char *end;
5302 char *args[MAX_LINE_ARGS + 1];
5303 char *line = thisline;
5304
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 linenum++;
5306
5307 end = line + strlen(line);
5308
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005309 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5310 /* Check if we reached the limit and the last char is not \n.
5311 * Watch out for the last line without the terminating '\n'!
5312 */
5313 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005314 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005315 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005316 }
5317
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005319 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320 line++;
5321
5322 arg = 0;
5323 args[arg] = line;
5324
5325 while (*line && arg < MAX_LINE_ARGS) {
5326 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5327 * C equivalent value. Other combinations left unchanged (eg: \1).
5328 */
5329 if (*line == '\\') {
5330 int skip = 0;
5331 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5332 *line = line[1];
5333 skip = 1;
5334 }
5335 else if (line[1] == 'r') {
5336 *line = '\r';
5337 skip = 1;
5338 }
5339 else if (line[1] == 'n') {
5340 *line = '\n';
5341 skip = 1;
5342 }
5343 else if (line[1] == 't') {
5344 *line = '\t';
5345 skip = 1;
5346 }
5347 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005348 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005349 unsigned char hex1, hex2;
5350 hex1 = toupper(line[2]) - '0';
5351 hex2 = toupper(line[3]) - '0';
5352 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5353 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5354 *line = (hex1<<4) + hex2;
5355 skip = 3;
5356 }
5357 else {
5358 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005359 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 }
5361 }
5362 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005363 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 end -= skip;
5365 }
5366 line++;
5367 }
5368 else if (*line == '#' || *line == '\n' || *line == '\r') {
5369 /* end of string, end of loop */
5370 *line = 0;
5371 break;
5372 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005373 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005374 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005375 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005376 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005377 line++;
5378 args[++arg] = line;
5379 }
5380 else {
5381 line++;
5382 }
5383 }
5384
5385 /* empty line */
5386 if (!**args)
5387 continue;
5388
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005389 if (*line) {
5390 /* we had to stop due to too many args.
5391 * Let's terminate the string, print the offending part then cut the
5392 * last arg.
5393 */
5394 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5395 line++;
5396 *line = '\0';
5397
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005398 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005399 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005400 err_code |= ERR_ALERT | ERR_FATAL;
5401 args[arg] = line;
5402 }
5403
Willy Tarreau540abe42007-05-02 20:50:16 +02005404 /* zero out remaining args and ensure that at least one entry
5405 * is zeroed out.
5406 */
5407 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005408 args[arg] = line;
5409 }
5410
Willy Tarreau3842f002009-06-14 11:39:52 +02005411 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005412 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005413 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005414 for (arg=0; *args[arg+1]; arg++)
5415 args[arg] = args[arg+1]; // shift args after inversion
5416 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005417 else if (!strcmp(args[0], "default")) {
5418 kwm = KWM_DEF;
5419 for (arg=0; *args[arg+1]; arg++)
5420 args[arg] = args[arg+1]; // shift args after inversion
5421 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005422
Willy Tarreau3842f002009-06-14 11:39:52 +02005423 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5424 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005425 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005426 }
5427
Willy Tarreau977b8e42006-12-29 14:19:17 +01005428 if (!strcmp(args[0], "listen") ||
5429 !strcmp(args[0], "frontend") ||
5430 !strcmp(args[0], "backend") ||
5431 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005432 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005433 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005434 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005435 cursection = strdup(args[0]);
5436 }
5437 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005438 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005439 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005440 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005441 }
5442 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005443 confsect = CFG_USERLIST;
5444 free(cursection);
5445 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005446 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005447 else if (!strcmp(args[0], "peers")) {
5448 confsect = CFG_PEERS;
5449 free(cursection);
5450 cursection = strdup(args[0]);
5451 }
5452
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453 /* else it's a section keyword */
5454
5455 switch (confsect) {
5456 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005457 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005458 break;
5459 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005460 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005461 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005462 case CFG_USERLIST:
5463 err_code |= cfg_parse_users(file, linenum, args, kwm);
5464 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005465 case CFG_PEERS:
5466 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5467 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005469 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005470 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005471 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005472
5473 if (err_code & ERR_ABORT)
5474 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005475 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005476 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005477 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005478 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005479 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005480}
5481
Willy Tarreaubb925012009-07-23 13:36:36 +02005482/*
5483 * Returns the error code, 0 if OK, or any combination of :
5484 * - ERR_ABORT: must abort ASAP
5485 * - ERR_FATAL: we can continue parsing but not start the service
5486 * - ERR_WARN: a warning has been emitted
5487 * - ERR_ALERT: an alert has been emitted
5488 * Only the two first ones can stop processing, the two others are just
5489 * indicators.
5490 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005491int check_config_validity()
5492{
5493 int cfgerr = 0;
5494 struct proxy *curproxy = NULL;
5495 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005496 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005497 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005498 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499
5500 /*
5501 * Now, check for the integrity of all that we have collected.
5502 */
5503
5504 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005505 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005506
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005507 /* first, we will invert the proxy list order */
5508 curproxy = NULL;
5509 while (proxy) {
5510 struct proxy *next;
5511
5512 next = proxy->next;
5513 proxy->next = curproxy;
5514 curproxy = proxy;
5515 if (!next)
5516 break;
5517 proxy = next;
5518 }
5519
Willy Tarreaubaaee002006-06-26 02:48:02 +02005520 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005521 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005522 err_code |= ERR_ALERT | ERR_FATAL;
5523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005524 }
5525
5526 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005527 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005528 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005529 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005530 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005531 unsigned int next_id;
5532
5533 if (!curproxy->uuid) {
5534 /* proxy ID not set, use automatic numbering with first
5535 * spare entry starting with next_pxid.
5536 */
5537 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5538 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5539 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005540 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005541 next_pxid++;
5542
Willy Tarreau55ea7572007-06-17 19:56:27 +02005543
Willy Tarreaubaaee002006-06-26 02:48:02 +02005544 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005545 /* ensure we don't keep listeners uselessly bound */
5546 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005547 curproxy = curproxy->next;
5548 continue;
5549 }
5550
Willy Tarreauff01a212009-03-15 13:46:16 +01005551 switch (curproxy->mode) {
5552 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005553 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005554 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005555 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5556 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005557 cfgerr++;
5558 }
5559
5560 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005561 Warning("config : servers will be ignored for %s '%s'.\n",
5562 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005563 break;
5564
5565 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005566 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005567 break;
5568
5569 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005570 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005571 break;
5572 }
5573
5574 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005575 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5576 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005577 cfgerr++;
5578 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005579
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005580 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005581 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005582 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005583 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5584 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005585 cfgerr++;
5586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005587#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005588 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005589 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5590 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005591 cfgerr++;
5592 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005593#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005594 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005595 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5596 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005597 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005598 }
5599 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005600 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005601 /* If no LB algo is set in a backend, and we're not in
5602 * transparent mode, dispatch mode nor proxy mode, we
5603 * want to use balance roundrobin by default.
5604 */
5605 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5606 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607 }
5608 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005609
Willy Tarreau1620ec32011-08-06 17:05:02 +02005610 if (curproxy->options & PR_O_DISPATCH)
5611 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5612 else if (curproxy->options & PR_O_HTTP_PROXY)
5613 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5614 else if (curproxy->options & PR_O_TRANSP)
5615 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005616
Willy Tarreau1620ec32011-08-06 17:05:02 +02005617 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5618 if (curproxy->options & PR_O_DISABLE404) {
5619 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5620 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5621 err_code |= ERR_WARN;
5622 curproxy->options &= ~PR_O_DISABLE404;
5623 }
5624 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5625 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5626 "send-state", proxy_type_str(curproxy), curproxy->id);
5627 err_code |= ERR_WARN;
5628 curproxy->options &= ~PR_O2_CHK_SNDST;
5629 }
Willy Tarreauef781042010-01-27 11:53:01 +01005630 }
5631
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005632 /* if a default backend was specified, let's find it */
5633 if (curproxy->defbe.name) {
5634 struct proxy *target;
5635
Alex Williams96532db2009-11-01 21:27:13 -05005636 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005637 if (!target) {
5638 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5639 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005640 cfgerr++;
5641 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005642 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5643 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005644 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005645 } else {
5646 free(curproxy->defbe.name);
5647 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005648 /* we force the backend to be present on at least all of
5649 * the frontend's processes.
5650 */
5651 target->bind_proc = curproxy->bind_proc ?
5652 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005653 }
5654 }
5655
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005656 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005657 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5658 /* map jump target for ACT_SETBE in req_rep chain */
5659 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005660 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005661 struct proxy *target;
5662
Willy Tarreaua496b602006-12-17 23:15:24 +01005663 if (exp->action != ACT_SETBE)
5664 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005665
Alex Williams96532db2009-11-01 21:27:13 -05005666 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005667 if (!target) {
5668 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5669 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005670 cfgerr++;
5671 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005672 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5673 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005674 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005675 } else {
5676 free((void *)exp->replace);
5677 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005678 /* we force the backend to be present on at least all of
5679 * the frontend's processes.
5680 */
5681 target->bind_proc = curproxy->bind_proc ?
5682 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005683 }
5684 }
5685 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005686
5687 /* find the target proxy for 'use_backend' rules */
5688 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005689 struct proxy *target;
5690
Alex Williams96532db2009-11-01 21:27:13 -05005691 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005692
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005693 if (!target) {
5694 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5695 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005696 cfgerr++;
5697 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005698 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5699 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005700 cfgerr++;
5701 } else {
5702 free((void *)rule->be.name);
5703 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005704 /* we force the backend to be present on at least all of
5705 * the frontend's processes.
5706 */
5707 target->bind_proc = curproxy->bind_proc ?
5708 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005709 }
5710 }
5711
Emeric Brunb982a3d2010-01-04 15:45:53 +01005712 /* find the target table for 'stick' rules */
5713 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5714 struct proxy *target;
5715
Emeric Brun1d33b292010-01-04 15:47:17 +01005716 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5717 if (mrule->flags & STK_IS_STORE)
5718 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5719
Emeric Brunb982a3d2010-01-04 15:45:53 +01005720 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005721 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005722 else
5723 target = curproxy;
5724
5725 if (!target) {
5726 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5727 curproxy->id, mrule->table.name);
5728 cfgerr++;
5729 }
5730 else if (target->table.size == 0) {
5731 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5732 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5733 cfgerr++;
5734 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005735 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005736 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5737 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5738 cfgerr++;
5739 }
5740 else {
5741 free((void *)mrule->table.name);
5742 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005743 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005744 }
5745 }
5746
5747 /* find the target table for 'store response' rules */
5748 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5749 struct proxy *target;
5750
Emeric Brun1d33b292010-01-04 15:47:17 +01005751 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5752
Emeric Brunb982a3d2010-01-04 15:45:53 +01005753 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005754 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005755 else
5756 target = curproxy;
5757
5758 if (!target) {
5759 Alert("Proxy '%s': unable to find store table '%s'.\n",
5760 curproxy->id, mrule->table.name);
5761 cfgerr++;
5762 }
5763 else if (target->table.size == 0) {
5764 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5765 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5766 cfgerr++;
5767 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005768 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005769 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5770 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5771 cfgerr++;
5772 }
5773 else {
5774 free((void *)mrule->table.name);
5775 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005776 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005777 }
5778 }
5779
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005780 /* find the target table for 'tcp-request' layer 4 rules */
5781 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5782 struct proxy *target;
5783
Willy Tarreau56123282010-08-06 19:06:56 +02005784 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005785 continue;
5786
5787 if (trule->act_prm.trk_ctr.table.n)
5788 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5789 else
5790 target = curproxy;
5791
5792 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005793 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5794 curproxy->id, trule->act_prm.trk_ctr.table.n,
5795 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005796 cfgerr++;
5797 }
5798 else if (target->table.size == 0) {
5799 Alert("Proxy '%s': table '%s' used but not configured.\n",
5800 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5801 cfgerr++;
5802 }
5803 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005804 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 +02005805 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5806 cfgerr++;
5807 }
5808 else {
5809 free(trule->act_prm.trk_ctr.table.n);
5810 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005811 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005812 * to pass a list of counters to track and allocate them right here using
5813 * stktable_alloc_data_type().
5814 */
5815 }
5816 }
5817
Willy Tarreaud1f96522010-08-03 19:34:32 +02005818 /* find the target table for 'tcp-request' layer 6 rules */
5819 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5820 struct proxy *target;
5821
Willy Tarreau56123282010-08-06 19:06:56 +02005822 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005823 continue;
5824
5825 if (trule->act_prm.trk_ctr.table.n)
5826 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5827 else
5828 target = curproxy;
5829
5830 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005831 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5832 curproxy->id, trule->act_prm.trk_ctr.table.n,
5833 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005834 cfgerr++;
5835 }
5836 else if (target->table.size == 0) {
5837 Alert("Proxy '%s': table '%s' used but not configured.\n",
5838 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5839 cfgerr++;
5840 }
5841 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005842 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 +02005843 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5844 cfgerr++;
5845 }
5846 else {
5847 free(trule->act_prm.trk_ctr.table.n);
5848 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005849 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005850 * to pass a list of counters to track and allocate them right here using
5851 * stktable_alloc_data_type().
5852 */
5853 }
5854 }
5855
Emeric Brun32da3c42010-09-23 18:39:19 +02005856 if (curproxy->table.peers.name) {
5857 struct peers *curpeers = peers;
5858
5859 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5860 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5861 free((void *)curproxy->table.peers.name);
5862 curproxy->table.peers.p = peers;
5863 break;
5864 }
5865 }
5866
5867 if (!curpeers) {
5868 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5869 curproxy->id, curproxy->table.peers.name);
5870 cfgerr++;
5871 }
5872 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02005873 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
5874 curproxy->id, localpeer, curpeers->id);
Emeric Brun32da3c42010-09-23 18:39:19 +02005875 cfgerr++;
5876 }
5877 }
5878
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005879 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005880 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005881 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5882 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5883 "proxy", curproxy->id);
5884 cfgerr++;
5885 goto out_uri_auth_compat;
5886 }
5887
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005888 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005889 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005890 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005891 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005892
Willy Tarreau95fa4692010-02-01 13:05:50 +01005893 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5894 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005895
5896 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005897 uri_auth_compat_req[i++] = "realm";
5898 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5899 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005900
Willy Tarreau95fa4692010-02-01 13:05:50 +01005901 uri_auth_compat_req[i++] = "unless";
5902 uri_auth_compat_req[i++] = "{";
5903 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5904 uri_auth_compat_req[i++] = "}";
5905 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005906
Willy Tarreauff011f22011-01-06 17:51:27 +01005907 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5908 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005909 cfgerr++;
5910 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005911 }
5912
Willy Tarreauff011f22011-01-06 17:51:27 +01005913 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005914
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005915 if (curproxy->uri_auth->auth_realm) {
5916 free(curproxy->uri_auth->auth_realm);
5917 curproxy->uri_auth->auth_realm = NULL;
5918 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005919
5920 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005921 }
5922out_uri_auth_compat:
5923
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005924 cfgerr += acl_find_targets(curproxy);
5925
Willy Tarreau2738a142006-07-08 17:28:09 +02005926 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005927 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005928 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005929 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005930 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005931 " | While not properly invalid, you will certainly encounter various problems\n"
5932 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005933 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005934 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005935 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005936 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005937
Willy Tarreau1fa31262007-12-03 00:36:16 +01005938 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5939 * We must still support older configurations, so let's find out whether those
5940 * parameters have been set or must be copied from contimeouts.
5941 */
5942 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005943 if (!curproxy->timeout.tarpit ||
5944 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005945 /* tarpit timeout not set. We search in the following order:
5946 * default.tarpit, curr.connect, default.connect.
5947 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005948 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005949 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005950 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005951 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005952 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005953 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005954 }
5955 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005956 (!curproxy->timeout.queue ||
5957 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005958 /* queue timeout not set. We search in the following order:
5959 * default.queue, curr.connect, default.connect.
5960 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005961 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005962 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005963 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005964 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005965 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005966 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005967 }
5968 }
5969
Willy Tarreau1620ec32011-08-06 17:05:02 +02005970 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005971 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5972 curproxy->check_req = (char *)malloc(curproxy->check_len);
5973 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005974 }
5975
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005976 /* The small pools required for the capture lists */
5977 if (curproxy->nb_req_cap)
5978 curproxy->req_cap_pool = create_pool("ptrcap",
5979 curproxy->nb_req_cap * sizeof(char *),
5980 MEM_F_SHARED);
5981 if (curproxy->nb_rsp_cap)
5982 curproxy->rsp_cap_pool = create_pool("ptrcap",
5983 curproxy->nb_rsp_cap * sizeof(char *),
5984 MEM_F_SHARED);
5985
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005986 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5987 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5988 MEM_F_SHARED);
5989
Willy Tarreaubaaee002006-06-26 02:48:02 +02005990 /* first, we will invert the servers list order */
5991 newsrv = NULL;
5992 while (curproxy->srv) {
5993 struct server *next;
5994
5995 next = curproxy->srv->next;
5996 curproxy->srv->next = newsrv;
5997 newsrv = curproxy->srv;
5998 if (!next)
5999 break;
6000 curproxy->srv = next;
6001 }
6002
Willy Tarreaudd701652010-05-25 23:03:02 +02006003 /* assign automatic UIDs to servers which don't have one yet */
6004 next_id = 1;
6005 newsrv = curproxy->srv;
6006 while (newsrv != NULL) {
6007 if (!newsrv->puid) {
6008 /* server ID not set, use automatic numbering with first
6009 * spare entry starting with next_svid.
6010 */
6011 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6012 newsrv->conf.id.key = newsrv->puid = next_id;
6013 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6014 }
6015 next_id++;
6016 newsrv = newsrv->next;
6017 }
6018
Willy Tarreau20697042007-11-15 23:26:18 +01006019 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006020 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006021
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006022 /* We have to initialize the server lookup mechanism depending
6023 * on what LB algorithm was choosen.
6024 */
6025
6026 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6027 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6028 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006029 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6030 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6031 init_server_map(curproxy);
6032 } else {
6033 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6034 fwrr_init_server_groups(curproxy);
6035 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006036 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006037
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006038 case BE_LB_KIND_LC:
6039 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006040 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006041 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006042
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006043 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006044 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6045 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6046 chash_init_server_tree(curproxy);
6047 } else {
6048 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6049 init_server_map(curproxy);
6050 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006051 break;
6052 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006053
6054 if (curproxy->options & PR_O_LOGASAP)
6055 curproxy->to_log &= ~LW_BYTES;
6056
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006057 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6058 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6059 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6060 proxy_type_str(curproxy), curproxy->id);
6061 err_code |= ERR_WARN;
6062 }
6063
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006064 if (curproxy->mode != PR_MODE_HTTP) {
6065 int optnum;
6066
6067 if (curproxy->options & PR_O_COOK_ANY) {
6068 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6069 proxy_type_str(curproxy), curproxy->id);
6070 err_code |= ERR_WARN;
6071 }
6072
6073 if (curproxy->uri_auth) {
6074 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6075 proxy_type_str(curproxy), curproxy->id);
6076 err_code |= ERR_WARN;
6077 curproxy->uri_auth = NULL;
6078 }
6079
Willy Tarreau87cf5142011-08-19 22:57:24 +02006080 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006081 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6082 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6083 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006084 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006085 }
6086
6087 if (curproxy->options & PR_O_ORGTO) {
6088 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6089 "originalto", proxy_type_str(curproxy), curproxy->id);
6090 err_code |= ERR_WARN;
6091 curproxy->options &= ~PR_O_ORGTO;
6092 }
6093
6094 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6095 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6096 (curproxy->cap & cfg_opts[optnum].cap) &&
6097 (curproxy->options & cfg_opts[optnum].val)) {
6098 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6099 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6100 err_code |= ERR_WARN;
6101 curproxy->options &= ~cfg_opts[optnum].val;
6102 }
6103 }
6104
6105 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6106 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6107 (curproxy->cap & cfg_opts2[optnum].cap) &&
6108 (curproxy->options2 & cfg_opts2[optnum].val)) {
6109 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6110 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6111 err_code |= ERR_WARN;
6112 curproxy->options2 &= ~cfg_opts2[optnum].val;
6113 }
6114 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006115
Willy Tarreauefa5f512010-03-30 20:13:29 +02006116#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006117 if (curproxy->bind_hdr_occ) {
6118 curproxy->bind_hdr_occ = 0;
6119 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6120 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6121 err_code |= ERR_WARN;
6122 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006123#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006124 }
6125
Willy Tarreaubaaee002006-06-26 02:48:02 +02006126 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006127 * ensure that we're not cross-dressing a TCP server into HTTP.
6128 */
6129 newsrv = curproxy->srv;
6130 while (newsrv != NULL) {
6131 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006132 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6133 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006134 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006135 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006136
Willy Tarreauefa5f512010-03-30 20:13:29 +02006137#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006138 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6139 newsrv->bind_hdr_occ = 0;
6140 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6141 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6142 err_code |= ERR_WARN;
6143 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006144#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006145 newsrv = newsrv->next;
6146 }
6147
6148 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006149 * If this server supports a maxconn parameter, it needs a dedicated
6150 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006151 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006152 */
6153 newsrv = curproxy->srv;
6154 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006155 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006156 /* Only 'minconn' was specified, or it was higher than or equal
6157 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6158 * this will avoid further useless expensive computations.
6159 */
6160 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006161 } else if (newsrv->maxconn && !newsrv->minconn) {
6162 /* minconn was not specified, so we set it to maxconn */
6163 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006164 }
6165
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006166 if (newsrv->trackit) {
6167 struct proxy *px;
6168 struct server *srv;
6169 char *pname, *sname;
6170
6171 pname = newsrv->trackit;
6172 sname = strrchr(pname, '/');
6173
6174 if (sname)
6175 *sname++ = '\0';
6176 else {
6177 sname = pname;
6178 pname = NULL;
6179 }
6180
6181 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006182 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006183 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006184 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6185 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006186 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006187 cfgerr++;
6188 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006189 }
6190 } else
6191 px = curproxy;
6192
6193 srv = findserver(px, sname);
6194 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006195 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6196 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006197 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006198 cfgerr++;
6199 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006200 }
6201
6202 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006203 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006204 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006205 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006206 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006207 cfgerr++;
6208 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006209 }
6210
6211 if (curproxy != px &&
6212 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006213 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006214 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006215 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006216 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006217 cfgerr++;
6218 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006219 }
6220
6221 newsrv->tracked = srv;
6222 newsrv->tracknext = srv->tracknext;
6223 srv->tracknext = newsrv;
6224
6225 free(newsrv->trackit);
6226 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006227 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006228 newsrv = newsrv->next;
6229 }
6230
Willy Tarreauc1a21672009-08-16 22:37:44 +02006231 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006232 curproxy->accept = frontend_accept;
6233
Willy Tarreauc1a21672009-08-16 22:37:44 +02006234 if (curproxy->tcp_req.inspect_delay ||
6235 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006236 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006237
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006238 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006239 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006240 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006241 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006242
6243 /* both TCP and HTTP must check switching rules */
6244 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6245 }
6246
6247 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006248 if (curproxy->tcp_req.inspect_delay ||
6249 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6250 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6251
Emeric Brun97679e72010-09-23 17:56:44 +02006252 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6253 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6254
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006255 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006256 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006257 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006258 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006259
6260 /* If the backend does requires RDP cookie persistence, we have to
6261 * enable the corresponding analyser.
6262 */
6263 if (curproxy->options2 & PR_O2_RDPC_PRST)
6264 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6265 }
6266
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006267 listener = NULL;
6268 while (curproxy->listen) {
6269 struct listener *next;
6270
6271 next = curproxy->listen->next;
6272 curproxy->listen->next = listener;
6273 listener = curproxy->listen;
6274
6275 if (!next)
6276 break;
6277
6278 curproxy->listen = next;
6279 }
6280
Willy Tarreaue6b98942007-10-29 01:09:36 +01006281 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006282 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006283 listener = curproxy->listen;
6284 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006285 if (!listener->luid) {
6286 /* listener ID not set, use automatic numbering with first
6287 * spare entry starting with next_luid.
6288 */
6289 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6290 listener->conf.id.key = listener->luid = next_id;
6291 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006292 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006293 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006294
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006295 /* enable separate counters */
6296 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6297 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6298 if (!listener->name) {
6299 sprintf(trash, "sock-%d", listener->luid);
6300 listener->name = strdup(trash);
6301 }
6302 }
6303
Willy Tarreaue6b98942007-10-29 01:09:36 +01006304 if (curproxy->options & PR_O_TCP_NOLING)
6305 listener->options |= LI_O_NOLINGER;
6306 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006307 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006308 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006309 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006310 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006311 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006312 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006313
Willy Tarreau8a956912010-10-15 14:27:08 +02006314 if (listener->options & LI_O_ACC_PROXY)
6315 listener->analysers |= AN_REQ_DECODE_PROXY;
6316
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006317 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6318 listener->options |= LI_O_TCP_RULES;
6319
Willy Tarreaude3041d2010-05-31 10:56:17 +02006320 if (curproxy->mon_mask.s_addr)
6321 listener->options |= LI_O_CHK_MONNET;
6322
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006323 /* smart accept mode is automatic in HTTP mode */
6324 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6325 (curproxy->mode == PR_MODE_HTTP &&
6326 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6327 listener->options |= LI_O_NOQUICKACK;
6328
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006329 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006330 listener = listener->next;
6331 }
6332
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006333 /* Check multi-process mode compatibility for the current proxy */
6334 if (global.nbproc > 1) {
6335 int nbproc = 0;
6336 if (curproxy->bind_proc) {
6337 int proc;
6338 for (proc = 0; proc < global.nbproc; proc++) {
6339 if (curproxy->bind_proc & (1 << proc)) {
6340 nbproc++;
6341 }
6342 }
6343 } else {
6344 nbproc = global.nbproc;
6345 }
6346 if (curproxy->table.peers.name) {
6347 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6348 curproxy->id);
6349 cfgerr++;
6350 }
6351 if (nbproc > 1) {
6352 if (curproxy->uri_auth) {
6353 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6354 curproxy->id);
6355 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6356 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6357 curproxy->id);
6358 }
6359 }
6360 if (curproxy->appsession_name) {
6361 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6362 curproxy->id);
6363 }
6364 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6365 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6366 curproxy->id);
6367 }
6368 }
6369 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006370
6371 /* create the task associated with the proxy */
6372 curproxy->task = task_new();
6373 if (curproxy->task) {
6374 curproxy->task->context = curproxy;
6375 curproxy->task->process = manage_proxy;
6376 /* no need to queue, it will be done automatically if some
6377 * listener gets limited.
6378 */
6379 curproxy->task->expire = TICK_ETERNITY;
6380 } else {
6381 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6382 curproxy->id);
6383 cfgerr++;
6384 }
6385
Willy Tarreaubaaee002006-06-26 02:48:02 +02006386 curproxy = curproxy->next;
6387 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006388
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006389 /* Check multi-process mode compatibility */
6390 if (global.nbproc > 1) {
6391 if (global.stats_fe) {
6392 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6393 }
6394 }
6395
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006396 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6397 struct auth_users *curuser;
6398 int g;
6399
6400 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6401 unsigned int group_mask = 0;
6402 char *group = NULL;
6403
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006404 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006405 continue;
6406
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006407 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006408
6409 for (g = 0; g < curuserlist->grpcnt; g++)
6410 if (!strcmp(curuserlist->groups[g], group))
6411 break;
6412
6413 if (g == curuserlist->grpcnt) {
6414 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6415 curuserlist->name, group, curuser->user);
6416 err_code |= ERR_ALERT | ERR_FATAL;
6417 goto out;
6418 }
6419
6420 group_mask |= (1 << g);
6421 }
6422
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006423 free(curuser->u.groups);
6424 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006425 }
6426
6427 for (g = 0; g < curuserlist->grpcnt; g++) {
6428 char *user = NULL;
6429
6430 if (!curuserlist->groupusers[g])
6431 continue;
6432
6433 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6434 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6435 if (!strcmp(curuser->user, user))
6436 break;
6437
6438 if (!curuser) {
6439 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6440 curuserlist->name, user, curuserlist->groups[g]);
6441 err_code |= ERR_ALERT | ERR_FATAL;
6442 goto out;
6443 }
6444
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006445 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006446 }
6447
6448 free(curuserlist->groupusers[g]);
6449 }
6450
6451 free(curuserlist->groupusers);
6452
6453#ifdef DEBUG_AUTH
6454 for (g = 0; g < curuserlist->grpcnt; g++) {
6455 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6456
6457 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6458 if (curuser->group_mask & (1 << g))
6459 fprintf(stderr, " %s", curuser->user);
6460 }
6461
6462 fprintf(stderr, "\n");
6463 }
6464#endif
6465
Willy Tarreaufbb78422011-06-05 15:38:35 +02006466 }
6467
6468 /* automatically compute fullconn if not set. We must not do it in the
6469 * loop above because cross-references are not yet fully resolved.
6470 */
6471 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6472 /* If <fullconn> is not set, let's set it to 10% of the sum of
6473 * the possible incoming frontend's maxconns.
6474 */
6475 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6476 struct proxy *fe;
6477 int total = 0;
6478
6479 /* sum up the number of maxconns of frontends which
6480 * reference this backend at least once or which are
6481 * the same one ('listen').
6482 */
6483 for (fe = proxy; fe; fe = fe->next) {
6484 struct switching_rule *rule;
6485 struct hdr_exp *exp;
6486 int found = 0;
6487
6488 if (!(fe->cap & PR_CAP_FE))
6489 continue;
6490
6491 if (fe == curproxy) /* we're on a "listen" instance */
6492 found = 1;
6493
6494 if (fe->defbe.be == curproxy) /* "default_backend" */
6495 found = 1;
6496
6497 /* check if a "use_backend" rule matches */
6498 if (!found) {
6499 list_for_each_entry(rule, &fe->switching_rules, list) {
6500 if (rule->be.backend == curproxy) {
6501 found = 1;
6502 break;
6503 }
6504 }
6505 }
6506
6507 /* check if a "reqsetbe" rule matches */
6508 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6509 if (exp->action == ACT_SETBE &&
6510 (struct proxy *)exp->replace == curproxy) {
6511 found = 1;
6512 break;
6513 }
6514 }
6515
6516 /* now we've checked all possible ways to reference a backend
6517 * from a frontend.
6518 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006519 if (!found)
6520 continue;
6521 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006522 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006523 /* we have the sum of the maxconns in <total>. We only
6524 * keep 10% of that sum to set the default fullconn, with
6525 * a hard minimum of 1 (to avoid a divide by zero).
6526 */
6527 curproxy->fullconn = (total + 9) / 10;
6528 if (!curproxy->fullconn)
6529 curproxy->fullconn = 1;
6530 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006531 }
6532
Willy Tarreau056f5682010-06-06 15:51:11 +02006533 /* initialize stick-tables on backend capable proxies. This must not
6534 * be done earlier because the data size may be discovered while parsing
6535 * other proxies.
6536 */
6537 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006538 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006539
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006540 /*
6541 * Recount currently required checks.
6542 */
6543
6544 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6545 int optnum;
6546
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006547 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6548 if (curproxy->options & cfg_opts[optnum].val)
6549 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006550
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006551 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6552 if (curproxy->options2 & cfg_opts2[optnum].val)
6553 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006554 }
6555
Willy Tarreau122541c2011-09-07 21:24:49 +02006556 if (peers) {
6557 struct peers *curpeers = peers, **last;
6558 struct peer *p, *pb;
6559
6560 /* Remove all peers sections which don't have a valid listener.
6561 * This can happen when a peers section is never referenced and
6562 * does not contain a local peer.
6563 */
6564 last = &peers;
6565 while (*last) {
6566 curpeers = *last;
6567 if (curpeers->peers_fe) {
6568 last = &curpeers->next;
6569 continue;
6570 }
6571
6572 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6573 curpeers->id, localpeer);
6574
6575 p = curpeers->remote;
6576 while (p) {
6577 pb = p->next;
6578 free(p->id);
6579 free(p);
6580 p = pb;
6581 }
6582
6583 /* Destroy and unlink this curpeers section.
6584 * Note: curpeers is backed up into *last.
6585 */
6586 free(curpeers->id);
6587 curpeers = curpeers->next;
6588 free(*last);
6589 *last = curpeers;
6590 }
6591 }
6592
Willy Tarreaubb925012009-07-23 13:36:36 +02006593 if (cfgerr > 0)
6594 err_code |= ERR_ALERT | ERR_FATAL;
6595 out:
6596 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006597}
6598
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006599/*
6600 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6601 * parsing sessions.
6602 */
6603void cfg_register_keywords(struct cfg_kw_list *kwl)
6604{
6605 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6606}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006607
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006608/*
6609 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6610 */
6611void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6612{
6613 LIST_DEL(&kwl->list);
6614 LIST_INIT(&kwl->list);
6615}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006616
6617/*
6618 * Local variables:
6619 * c-indent-level: 8
6620 * c-basic-offset: 8
6621 * End:
6622 */