blob: 1e3a92cf1316899bf7bdc171c3eec0c13130433f [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020047#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020048#include <proto/lb_fwlc.h>
49#include <proto/lb_fwrr.h>
50#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010052#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020053#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010054#include <proto/protocols.h>
55#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020056#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010057#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010058#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020059#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010061#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010063#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064
65
Willy Tarreauf3c69202006-07-09 16:42:34 +020066/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
67 * ssl-hello-chk option to ensure that the remote server speaks SSL.
68 *
69 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
70 */
71const char sslv3_client_hello_pkt[] = {
72 "\x16" /* ContentType : 0x16 = Hanshake */
73 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
74 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
75 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
76 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
77 "\x03\x00" /* Hello Version : 0x0300 = v3 */
78 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
79 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
80 "\x00" /* Session ID length : empty (no session ID) */
81 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
82 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
83 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
84 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
85 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
86 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
87 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
88 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
89 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
90 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
91 "\x00\x38" "\x00\x39" "\x00\x3A"
92 "\x01" /* Compression Length : 0x01 = 1 byte for types */
93 "\x00" /* Compression Type : 0x00 = NULL compression */
94};
95
Willy Tarreau3842f002009-06-14 11:39:52 +020096/* various keyword modifiers */
97enum kw_mod {
98 KWM_STD = 0, /* normal */
99 KWM_NO, /* "no" prefixed before the keyword */
100 KWM_DEF, /* "default" prefixed before the keyword */
101};
102
Willy Tarreau13943ab2006-12-31 00:24:10 +0100103/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100104struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100105 const char *name;
106 unsigned int val;
107 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100108 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100109 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100110};
111
112/* proxy->options */
113static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100115 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
116 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
117 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
118 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
119 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
120 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
121 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
122 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
125 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
127 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
128 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
129 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
130 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100131#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100132 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100133#else
134 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100135#endif
136
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100137 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138};
139
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140/* proxy->options2 */
141static const struct cfg_opt cfg_opts2[] =
142{
143#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
145 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100147#else
148 { "splice-request", 0, 0, 0, 0 },
149 { "splice-response", 0, 0, 0, 0 },
150 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
153 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
154 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
155 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
156 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
157 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
158 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
160 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
161 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200162 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200163 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100164 { NULL, 0, 0, 0 }
165};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166
Willy Tarreau6daf3432008-01-22 16:44:08 +0100167static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
169int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100170int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200172/* List head of all known configuration keywords */
173static struct cfg_kw_list cfg_keywords = {
174 .list = LIST_HEAD_INIT(cfg_keywords.list)
175};
176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177/*
178 * converts <str> to a list of listeners which are dynamically allocated.
179 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
180 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
181 * - <port> is a numerical port from 1 to 65535 ;
182 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
183 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200184 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100186static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187{
188 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100189 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200190 int port, end;
191
192 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 while (next && *next) {
195 struct sockaddr_storage ss;
196
197 str = next;
198 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100199 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 *next++ = 0;
201 }
202
Emeric Bruned760922010-10-22 17:59:25 +0200203 if (*str == '/') {
204 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
205 /* so compute max path */
206 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
207 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
Emeric Bruned760922010-10-22 17:59:25 +0200209 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100210 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
211 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200212 goto fail;
213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200216 ss.ss_family = AF_UNIX;
217 if (global.unix_bind.prefix) {
218 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
219 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 }
Emeric Bruned760922010-10-22 17:59:25 +0200221 else {
222 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
223 }
224 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 }
226 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100227 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100229 ss2 = str2sa_range(str, &port, &end);
230 if (!ss2) {
231 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
232 file, line, str);
233 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 if (!port) {
237 Alert("parsing [%s:%d] : missing port number: '%s'\n",
238 file, line, str);
239 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 /* OK the address looks correct */
243 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Emeric Bruned760922010-10-22 17:59:25 +0200245 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100246 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
247 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200248 goto fail;
249 }
250
251 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100252 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
253 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200254 goto fail;
255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256 }
257
258 for (; port <= end; port++) {
259 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200260 l->next = curproxy->listen;
261 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
263 l->fd = -1;
264 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100265 l->state = LI_INIT;
266
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100267 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100269 tcpv4_add_listener(l);
270 }
Emeric Bruned760922010-10-22 17:59:25 +0200271 else if (ss.ss_family == AF_INET6) {
272 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
273 tcpv6_add_listener(l);
274 }
275 else {
276 l->perm.ux.gid = l->perm.ux.uid = -1;
277 l->perm.ux.mode = 0;
278 uxst_add_listener(l);
279 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200280
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200281 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100282 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283 } /* end for(port) */
284 } /* end while(next) */
285 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200286 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200287 fail:
288 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200289 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290}
291
Willy Tarreau977b8e42006-12-29 14:19:17 +0100292/*
293 * Sends a warning if proxy <proxy> does not have at least one of the
294 * capabilities in <cap>. An optionnal <hint> may be added at the end
295 * of the warning to help the user. Returns 1 if a warning was emitted
296 * or 0 if the condition is valid.
297 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100298int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299{
300 char *msg;
301
302 switch (cap) {
303 case PR_CAP_BE: msg = "no backend"; break;
304 case PR_CAP_FE: msg = "no frontend"; break;
305 case PR_CAP_RS: msg = "no ruleset"; break;
306 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
307 default: msg = "not enough"; break;
308 }
309
310 if (!(proxy->cap & cap)) {
311 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100312 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100313 return 1;
314 }
315 return 0;
316}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317
Willy Tarreau61d18892009-03-31 10:49:21 +0200318/* Report a warning if a rule is placed after a 'block' rule.
319 * Return 1 if the warning has been emitted, otherwise 0.
320 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100321int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200322{
323 if (!LIST_ISEMPTY(&proxy->block_cond)) {
324 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
325 file, line, arg);
326 return 1;
327 }
328 return 0;
329}
330
331/* Report a warning if a rule is placed after a reqrewrite rule.
332 * Return 1 if the warning has been emitted, otherwise 0.
333 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100334int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200335{
336 if (proxy->req_exp) {
337 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
338 file, line, arg);
339 return 1;
340 }
341 return 0;
342}
343
344/* Report a warning if a rule is placed after a reqadd rule.
345 * Return 1 if the warning has been emitted, otherwise 0.
346 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100347int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200348{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100349 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200350 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
351 file, line, arg);
352 return 1;
353 }
354 return 0;
355}
356
357/* Report a warning if a rule is placed after a redirect rule.
358 * Return 1 if the warning has been emitted, otherwise 0.
359 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100360int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200361{
362 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
363 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
364 file, line, arg);
365 return 1;
366 }
367 return 0;
368}
369
370/* Report a warning if a rule is placed after a 'use_backend' rule.
371 * Return 1 if the warning has been emitted, otherwise 0.
372 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100373int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200374{
375 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
376 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
377 file, line, arg);
378 return 1;
379 }
380 return 0;
381}
382
383/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
387 warnif_rule_after_reqadd(proxy, file, line, arg) ||
388 warnif_rule_after_redirect(proxy, file, line, arg) ||
389 warnif_rule_after_use_backend(proxy, file, line, arg);
390}
391
392/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
395 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
396 warnif_rule_after_redirect(proxy, file, line, arg) ||
397 warnif_rule_after_use_backend(proxy, file, line, arg);
398}
399
400/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 return warnif_rule_after_redirect(proxy, file, line, arg) ||
404 warnif_rule_after_use_backend(proxy, file, line, arg);
405}
406
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100407/* Report it if a request ACL condition uses some response-only parameters. It
408 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
409 * Note that <cond> may be NULL and then will be ignored.
410 */
411static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
412{
413 struct acl *acl;
414
415 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
416 return 0;
417
418 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
419 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
420 file, line, acl ? acl->name : "(unknown)");
421 return ERR_WARN;
422}
423
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100424/* Report it if a request ACL condition uses some request-only volatile parameters.
425 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
426 * Note that <cond> may be NULL and then will be ignored.
427 */
428static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
429{
430 struct acl *acl;
431
432 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
433 return 0;
434
435 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
436 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
437 file, line, acl ? acl->name : "(unknown)");
438 return ERR_WARN;
439}
440
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100441
Willy Tarreaubaaee002006-06-26 02:48:02 +0200442/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 * parse a line in a <global> section. Returns the error code, 0 if OK, or
444 * any combination of :
445 * - ERR_ABORT: must abort ASAP
446 * - ERR_FATAL: we can continue parsing but not start the service
447 * - ERR_WARN: a warning has been emitted
448 * - ERR_ALERT: an alert has been emitted
449 * Only the two first ones can stop processing, the two others are just
450 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200451 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200452int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453{
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455
456 if (!strcmp(args[0], "global")) { /* new section */
457 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200459 }
460 else if (!strcmp(args[0], "daemon")) {
461 global.mode |= MODE_DAEMON;
462 }
463 else if (!strcmp(args[0], "debug")) {
464 global.mode |= MODE_DEBUG;
465 }
466 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100467 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200469 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100470 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200471 }
472 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100473 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100476 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200477 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100478 else if (!strcmp(args[0], "nosplice")) {
479 global.tune.options &= ~GTUNE_USE_SPLICE;
480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481 else if (!strcmp(args[0], "quiet")) {
482 global.mode |= MODE_QUIET;
483 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200484 else if (!strcmp(args[0], "tune.maxpollevents")) {
485 if (global.tune.maxpollevents != 0) {
486 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200487 err_code |= ERR_ALERT;
488 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200489 }
490 if (*(args[1]) == 0) {
491 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200492 err_code |= ERR_ALERT | ERR_FATAL;
493 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200494 }
495 global.tune.maxpollevents = atol(args[1]);
496 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100497 else if (!strcmp(args[0], "tune.maxaccept")) {
498 if (global.tune.maxaccept != 0) {
499 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200500 err_code |= ERR_ALERT;
501 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100502 }
503 if (*(args[1]) == 0) {
504 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100507 }
508 global.tune.maxaccept = atol(args[1]);
509 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200510 else if (!strcmp(args[0], "tune.chksize")) {
511 if (*(args[1]) == 0) {
512 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
513 err_code |= ERR_ALERT | ERR_FATAL;
514 goto out;
515 }
516 global.tune.chksize = atol(args[1]);
517 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200518 else if (!strcmp(args[0], "tune.bufsize")) {
519 if (*(args[1]) == 0) {
520 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT | ERR_FATAL;
522 goto out;
523 }
524 global.tune.bufsize = atol(args[1]);
525 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
526 global.tune.maxrewrite = global.tune.bufsize / 2;
527 }
528 else if (!strcmp(args[0], "tune.maxrewrite")) {
529 if (*(args[1]) == 0) {
530 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
531 err_code |= ERR_ALERT | ERR_FATAL;
532 goto out;
533 }
534 global.tune.maxrewrite = atol(args[1]);
535 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
536 global.tune.maxrewrite = global.tune.bufsize / 2;
537 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100538 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
539 if (global.tune.client_rcvbuf != 0) {
540 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
541 err_code |= ERR_ALERT;
542 goto out;
543 }
544 if (*(args[1]) == 0) {
545 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
546 err_code |= ERR_ALERT | ERR_FATAL;
547 goto out;
548 }
549 global.tune.client_rcvbuf = atol(args[1]);
550 }
551 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
552 if (global.tune.server_rcvbuf != 0) {
553 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT;
555 goto out;
556 }
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.server_rcvbuf = atol(args[1]);
563 }
564 else if (!strcmp(args[0], "tune.sndbuf.client")) {
565 if (global.tune.client_sndbuf != 0) {
566 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
567 err_code |= ERR_ALERT;
568 goto out;
569 }
570 if (*(args[1]) == 0) {
571 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
572 err_code |= ERR_ALERT | ERR_FATAL;
573 goto out;
574 }
575 global.tune.client_sndbuf = atol(args[1]);
576 }
577 else if (!strcmp(args[0], "tune.sndbuf.server")) {
578 if (global.tune.server_sndbuf != 0) {
579 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT;
581 goto out;
582 }
583 if (*(args[1]) == 0) {
584 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
585 err_code |= ERR_ALERT | ERR_FATAL;
586 goto out;
587 }
588 global.tune.server_sndbuf = atol(args[1]);
589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 else if (!strcmp(args[0], "uid")) {
591 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200592 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200593 err_code |= ERR_ALERT;
594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
596 if (*(args[1]) == 0) {
597 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200598 err_code |= ERR_ALERT | ERR_FATAL;
599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 }
601 global.uid = atol(args[1]);
602 }
603 else if (!strcmp(args[0], "gid")) {
604 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200605 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200606 err_code |= ERR_ALERT;
607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 }
609 if (*(args[1]) == 0) {
610 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200611 err_code |= ERR_ALERT | ERR_FATAL;
612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 }
614 global.gid = atol(args[1]);
615 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200616 /* user/group name handling */
617 else if (!strcmp(args[0], "user")) {
618 struct passwd *ha_user;
619 if (global.uid != 0) {
620 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
622 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200623 }
624 errno = 0;
625 ha_user = getpwnam(args[1]);
626 if (ha_user != NULL) {
627 global.uid = (int)ha_user->pw_uid;
628 }
629 else {
630 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200631 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200632 }
633 }
634 else if (!strcmp(args[0], "group")) {
635 struct group *ha_group;
636 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200637 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200638 err_code |= ERR_ALERT;
639 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200640 }
641 errno = 0;
642 ha_group = getgrnam(args[1]);
643 if (ha_group != NULL) {
644 global.gid = (int)ha_group->gr_gid;
645 }
646 else {
647 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200648 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200649 }
650 }
651 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 else if (!strcmp(args[0], "nbproc")) {
653 if (global.nbproc != 0) {
654 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200655 err_code |= ERR_ALERT;
656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 }
658 if (*(args[1]) == 0) {
659 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT | ERR_FATAL;
661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 }
663 global.nbproc = atol(args[1]);
664 }
665 else if (!strcmp(args[0], "maxconn")) {
666 if (global.maxconn != 0) {
667 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200668 err_code |= ERR_ALERT;
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 }
671 if (*(args[1]) == 0) {
672 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT | ERR_FATAL;
674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 }
676 global.maxconn = atol(args[1]);
677#ifdef SYSTEM_MAXCONN
678 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
679 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
680 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200681 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
683#endif /* SYSTEM_MAXCONN */
684 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100685 else if (!strcmp(args[0], "maxpipes")) {
686 if (global.maxpipes != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT;
689 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100695 }
696 global.maxpipes = atol(args[1]);
697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 else if (!strcmp(args[0], "ulimit-n")) {
699 if (global.rlimit_nofile != 0) {
700 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT;
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 }
704 if (*(args[1]) == 0) {
705 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200708 }
709 global.rlimit_nofile = atol(args[1]);
710 }
711 else if (!strcmp(args[0], "chroot")) {
712 if (global.chroot != NULL) {
713 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200714 err_code |= ERR_ALERT;
715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716 }
717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722 global.chroot = strdup(args[1]);
723 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200724 else if (!strcmp(args[0], "description")) {
725 int i, len=0;
726 char *d;
727
728 if (!*args[1]) {
729 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
730 file, linenum, args[0]);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734
735 for(i=1; *args[i]; i++)
736 len += strlen(args[i])+1;
737
738 if (global.desc)
739 free(global.desc);
740
741 global.desc = d = (char *)calloc(1, len);
742
743 d += sprintf(d, "%s", args[1]);
744 for(i=2; *args[i]; i++)
745 d += sprintf(d, " %s", args[i]);
746 }
747 else if (!strcmp(args[0], "node")) {
748 int i;
749 char c;
750
751 for (i=0; args[1][i]; i++) {
752 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100753 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
754 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200755 break;
756 }
757
758 if (!i || args[1][i]) {
759 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
760 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
761 file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765
766 if (global.node)
767 free(global.node);
768
769 global.node = strdup(args[1]);
770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 else if (!strcmp(args[0], "pidfile")) {
772 if (global.pidfile != NULL) {
773 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT;
775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 }
782 global.pidfile = strdup(args[1]);
783 }
Emeric Bruned760922010-10-22 17:59:25 +0200784 else if (!strcmp(args[0], "unix-bind")) {
785 int cur_arg = 1;
786 while (*(args[cur_arg])) {
787 if (!strcmp(args[cur_arg], "prefix")) {
788 if (global.unix_bind.prefix != NULL) {
789 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
790 err_code |= ERR_ALERT;
791 cur_arg += 2;
792 continue;
793 }
794
795 if (*(args[cur_arg+1]) == 0) {
796 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800 global.unix_bind.prefix = strdup(args[cur_arg+1]);
801 cur_arg += 2;
802 continue;
803 }
804
805 if (!strcmp(args[cur_arg], "mode")) {
806
807 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
808 cur_arg += 2;
809 continue;
810 }
811
812 if (!strcmp(args[cur_arg], "uid")) {
813
814 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
815 cur_arg += 2;
816 continue;
817 }
818
819 if (!strcmp(args[cur_arg], "gid")) {
820
821 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
822 cur_arg += 2;
823 continue;
824 }
825
826 if (!strcmp(args[cur_arg], "user")) {
827 struct passwd *user;
828
829 user = getpwnam(args[cur_arg + 1]);
830 if (!user) {
831 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
832 file, linenum, args[0], args[cur_arg + 1 ]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
836
837 global.unix_bind.ux.uid = user->pw_uid;
838 cur_arg += 2;
839 continue;
840 }
841
842 if (!strcmp(args[cur_arg], "group")) {
843 struct group *group;
844
845 group = getgrnam(args[cur_arg + 1]);
846 if (!group) {
847 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
848 file, linenum, args[0], args[cur_arg + 1 ]);
849 err_code |= ERR_ALERT | ERR_FATAL;
850 goto out;
851 }
852
853 global.unix_bind.ux.gid = group->gr_gid;
854 cur_arg += 2;
855 continue;
856 }
857
858 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
859 file, linenum, args[0]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
862 }
863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200864 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100865 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200866 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867
868 if (*(args[1]) == 0 || *(args[2]) == 0) {
869 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872 }
873
874 facility = get_log_facility(args[2]);
875 if (facility < 0) {
876 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200877 err_code |= ERR_ALERT | ERR_FATAL;
878 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879 }
880
881 level = 7; /* max syslog level = debug */
882 if (*(args[3])) {
883 level = get_log_level(args[3]);
884 if (level < 0) {
885 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200886 err_code |= ERR_ALERT | ERR_FATAL;
887 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888 }
889 }
890
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200891 minlvl = 0; /* limit syslog level to this level (emerg) */
892 if (*(args[4])) {
893 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200894 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200895 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200896 err_code |= ERR_ALERT | ERR_FATAL;
897 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200898 }
899 }
900
Robert Tsai81ae1952007-12-05 10:47:29 +0100901 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100902 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100903 if (!sk) {
904 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100905 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100909 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100910 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100911 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100912 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100913 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100917 logsrv.addr = *sk;
918 if (!get_host_port(&logsrv.addr))
919 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921
922 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100923 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 global.logfac1 = facility;
925 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200926 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100929 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 global.logfac2 = facility;
931 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200932 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 }
934 else {
935 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200936 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200938 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100939 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
940 char *name;
941 int len;
942
943 if (global.log_send_hostname != NULL) {
944 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
945 err_code |= ERR_ALERT;
946 goto out;
947 }
948
949 if (*(args[1]))
950 name = args[1];
951 else
952 name = hostname;
953
954 len = strlen(name);
955
956 /* We'll add a space after the name to respect the log format */
957 free(global.log_send_hostname);
958 global.log_send_hostname = malloc(len + 2);
959 snprintf(global.log_send_hostname, len + 2, "%s ", name);
960 }
Kevinm48936af2010-12-22 16:08:21 +0000961 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
962 if (*(args[1]) == 0) {
963 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
966 }
967 free(global.log_tag);
968 global.log_tag = strdup(args[1]);
969 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200970 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
971 if (global.spread_checks != 0) {
972 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200973 err_code |= ERR_ALERT;
974 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200975 }
976 if (*(args[1]) == 0) {
977 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200980 }
981 global.spread_checks = atol(args[1]);
982 if (global.spread_checks < 0 || global.spread_checks > 50) {
983 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200984 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 }
987 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200988 struct cfg_kw_list *kwl;
989 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200990 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200991
992 list_for_each_entry(kwl, &cfg_keywords.list, list) {
993 for (index = 0; kwl->kw[index].kw != NULL; index++) {
994 if (kwl->kw[index].section != CFG_GLOBAL)
995 continue;
996 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
997 /* prepare error message just in case */
998 snprintf(trash, sizeof(trash),
999 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001000 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1001 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001002 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001003 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001004 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001005 else if (rc > 0) {
1006 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001007 err_code |= ERR_WARN;
1008 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001009 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001010 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001011 }
1012 }
1013 }
1014
Willy Tarreaubaaee002006-06-26 02:48:02 +02001015 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001016 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001018
Willy Tarreau058e9072009-07-20 09:30:05 +02001019 out:
1020 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021}
1022
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001023void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001024{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001025 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026 defproxy.mode = PR_MODE_TCP;
1027 defproxy.state = PR_STNEW;
1028 defproxy.maxconn = cfg_maxpconn;
1029 defproxy.conn_retries = CONN_RETRIES;
1030 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001031
1032 defproxy.defsrv.inter = DEF_CHKINTR;
1033 defproxy.defsrv.fastinter = 0;
1034 defproxy.defsrv.downinter = 0;
1035 defproxy.defsrv.rise = DEF_RISETIME;
1036 defproxy.defsrv.fall = DEF_FALLTIME;
1037 defproxy.defsrv.check_port = 0;
1038 defproxy.defsrv.maxqueue = 0;
1039 defproxy.defsrv.minconn = 0;
1040 defproxy.defsrv.maxconn = 0;
1041 defproxy.defsrv.slowstart = 0;
1042 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1043 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1044 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045}
1046
Willy Tarreauade5ec42010-01-28 19:33:49 +01001047
1048static int create_cond_regex_rule(const char *file, int line,
1049 struct proxy *px, int dir, int action, int flags,
1050 const char *cmd, const char *reg, const char *repl,
1051 const char **cond_start)
1052{
1053 regex_t *preg = NULL;
1054 const char *err;
1055 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001056 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001057
1058 if (px == &defproxy) {
1059 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1060 err_code |= ERR_ALERT | ERR_FATAL;
1061 goto err;
1062 }
1063
1064 if (*reg == 0) {
1065 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto err;
1068 }
1069
1070 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1071 err_code |= ERR_WARN;
1072
Willy Tarreau5321c422010-01-28 20:35:13 +01001073 if (cond_start &&
1074 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1075 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1076 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1077 file, line, cmd);
1078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto err;
1080 }
1081 }
1082 else if (cond_start && **cond_start) {
1083 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1084 file, line, cmd, *cond_start);
1085 err_code |= ERR_ALERT | ERR_FATAL;
1086 goto err;
1087 }
1088
1089 if (dir == ACL_DIR_REQ)
1090 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001091 else
1092 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001093
Willy Tarreauade5ec42010-01-28 19:33:49 +01001094 preg = calloc(1, sizeof(regex_t));
1095 if (!preg) {
1096 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1097 err_code = ERR_ALERT | ERR_FATAL;
1098 goto err;
1099 }
1100
1101 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1102 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1103 err_code = ERR_ALERT | ERR_FATAL;
1104 goto err;
1105 }
1106
1107 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001108 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001109 if (repl && err) {
1110 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1111 file, line, cmd, *err);
1112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto err;
1114 }
1115
1116 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1117 err_code |= ERR_WARN;
1118
1119 return err_code;
1120 err:
1121 free(preg);
1122 return err_code;
1123}
1124
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001126 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001127 * Returns the error code, 0 if OK, or any combination of :
1128 * - ERR_ABORT: must abort ASAP
1129 * - ERR_FATAL: we can continue parsing but not start the service
1130 * - ERR_WARN: a warning has been emitted
1131 * - ERR_ALERT: an alert has been emitted
1132 * Only the two first ones can stop processing, the two others are just
1133 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001134 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001135int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1136{
1137 static struct peers *curpeers = NULL;
1138 struct peer *newpeer = NULL;
1139 const char *err;
1140 int err_code = 0;
1141
1142 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1143
1144 err = invalid_char(args[1]);
1145 if (err) {
1146 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1147 file, linenum, *err, args[0], args[1]);
1148 err_code |= ERR_ALERT | ERR_FATAL;
1149 }
1150
1151 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1152 /*
1153 * If there are two proxies with the same name only following
1154 * combinations are allowed:
1155 */
1156 if (strcmp(curpeers->id, args[1]) == 0) {
1157 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1158 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1159 err_code |= ERR_WARN;
1160 }
1161 }
1162
1163 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1164 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1165 err_code |= ERR_ALERT | ERR_ABORT;
1166 goto out;
1167 }
1168
1169 curpeers->next = peers;
1170 peers = curpeers;
1171 curpeers->conf.file = file;
1172 curpeers->conf.line = linenum;
1173 curpeers->last_change = now.tv_sec;
1174 curpeers->id = strdup(args[1]);
1175 }
1176 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1177 char *rport, *raddr;
1178 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001179 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001180
1181 if (!*args[2]) {
1182 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1183 file, linenum, args[0]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187
1188 err = invalid_char(args[1]);
1189 if (err) {
1190 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1191 file, linenum, *err, args[1]);
1192 err_code |= ERR_ALERT | ERR_FATAL;
1193 goto out;
1194 }
1195
1196 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1197 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1198 err_code |= ERR_ALERT | ERR_ABORT;
1199 goto out;
1200 }
1201
1202 /* the peers are linked backwards first */
1203 curpeers->count++;
1204 newpeer->next = curpeers->remote;
1205 curpeers->remote = newpeer;
1206 newpeer->peers = curpeers;
1207 newpeer->conf.file = file;
1208 newpeer->conf.line = linenum;
1209
1210 newpeer->last_change = now.tv_sec;
1211 newpeer->id = strdup(args[1]);
1212
1213 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001214 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001215 if (rport) {
1216 *rport++ = 0;
1217 realport = atol(rport);
1218 }
1219 if (!realport) {
1220 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1221 err_code |= ERR_ALERT | ERR_FATAL;
1222 goto out;
1223 }
1224
Willy Tarreaufab5a432011-03-04 15:31:53 +01001225 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001226 free(raddr);
1227 if (!sk) {
1228 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1229 err_code |= ERR_ALERT | ERR_FATAL;
1230 goto out;
1231 }
1232 newpeer->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001233
1234 switch (newpeer->addr.ss_family) {
1235 case AF_INET:
1236 ((struct sockaddr_in *)&newpeer->addr)->sin_port = htons(realport);
1237 break;
1238 case AF_INET6:
1239 ((struct sockaddr_in6 *)&newpeer->addr)->sin6_port = htons(realport);
1240 break;
1241 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001242
1243 if (strcmp(newpeer->id, localpeer) == 0) {
1244 /* Current is local peer, it define a frontend */
1245 newpeer->local = 1;
1246
1247 if (!curpeers->peers_fe) {
1248 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1249 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1250 err_code |= ERR_ALERT | ERR_ABORT;
1251 goto out;
1252 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001253
Willy Tarreau237250c2011-07-29 01:49:03 +02001254 init_new_proxy(curpeers->peers_fe);
1255 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001256
1257 curpeers->peers_fe->last_change = now.tv_sec;
1258 curpeers->peers_fe->id = strdup(args[1]);
1259 curpeers->peers_fe->cap = PR_CAP_FE;
1260 curpeers->peers_fe->maxconn = 65000;
1261 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1262 curpeers->peers_fe->timeout.connect = 5000;
1263 curpeers->peers_fe->accept = peer_accept;
1264 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001265 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001266 err_code |= ERR_FATAL;
1267 goto out;
1268 }
1269 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1270 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1271 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1272 curpeers->peers_fe->listen->accept = session_accept;
1273 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1274 curpeers->peers_fe->listen->handler = process_session;
1275 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1276 }
1277 }
1278 } /* neither "peer" nor "peers" */
1279 else if (*args[0] != 0) {
1280 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1281 err_code |= ERR_ALERT | ERR_FATAL;
1282 goto out;
1283 }
1284
1285out:
1286 return err_code;
1287}
1288
1289
Willy Tarreau3842f002009-06-14 11:39:52 +02001290int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001291{
1292 static struct proxy *curproxy = NULL;
1293 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001294 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001295 int rc;
1296 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001297 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001298 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001299
Willy Tarreau977b8e42006-12-29 14:19:17 +01001300 if (!strcmp(args[0], "listen"))
1301 rc = PR_CAP_LISTEN;
1302 else if (!strcmp(args[0], "frontend"))
1303 rc = PR_CAP_FE | PR_CAP_RS;
1304 else if (!strcmp(args[0], "backend"))
1305 rc = PR_CAP_BE | PR_CAP_RS;
1306 else if (!strcmp(args[0], "ruleset"))
1307 rc = PR_CAP_RS;
1308 else
1309 rc = PR_CAP_NONE;
1310
1311 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001312 if (!*args[1]) {
1313 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1314 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1315 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001316 err_code |= ERR_ALERT | ERR_ABORT;
1317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001319
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001320 err = invalid_char(args[1]);
1321 if (err) {
1322 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1323 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001324 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001325 }
1326
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001327 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1328 /*
1329 * If there are two proxies with the same name only following
1330 * combinations are allowed:
1331 *
1332 * listen backend frontend ruleset
1333 * listen - - - -
1334 * backend - - OK -
1335 * frontend - OK - -
1336 * ruleset - - - -
1337 */
1338
1339 if (!strcmp(curproxy->id, args[1]) &&
1340 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1341 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001342 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1343 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1344 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001345 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001346 }
1347 }
1348
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1350 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001351 err_code |= ERR_ALERT | ERR_ABORT;
1352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001354
Willy Tarreau97cb7802010-01-03 20:23:58 +01001355 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001356 curproxy->next = proxy;
1357 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001358 curproxy->conf.file = file;
1359 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001360 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001361 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001362 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363
1364 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001365 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001366 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001367 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001368 err_code |= ERR_FATAL;
1369 goto out;
1370 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001371 new = curproxy->listen;
1372 while (new != last) {
1373 new->conf.file = file;
1374 new->conf.line = linenum;
1375 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001376 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001377 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378 }
1379
1380 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001381 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001382 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001383
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001386 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001387 curproxy->no_options = defproxy.no_options;
1388 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001389 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001390 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001391 curproxy->except_net = defproxy.except_net;
1392 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001393 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001394 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001396 if (defproxy.fwdfor_hdr_len) {
1397 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1398 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1399 }
1400
Willy Tarreaub86db342009-11-30 11:50:16 +01001401 if (defproxy.orgto_hdr_len) {
1402 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1403 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1404 }
1405
Willy Tarreau977b8e42006-12-29 14:19:17 +01001406 if (curproxy->cap & PR_CAP_FE) {
1407 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001408 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001409 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001410
1411 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001412 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1413 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001414
1415 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1416 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001417
Willy Tarreau977b8e42006-12-29 14:19:17 +01001418 if (curproxy->cap & PR_CAP_BE) {
1419 curproxy->fullconn = defproxy.fullconn;
1420 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001422 if (defproxy.check_req) {
1423 curproxy->check_req = calloc(1, defproxy.check_len);
1424 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1425 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001426 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001428 if (defproxy.expect_str) {
1429 curproxy->expect_str = strdup(defproxy.expect_str);
1430 if (defproxy.expect_regex) {
1431 /* note: this regex is known to be valid */
1432 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1433 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1434 }
1435 }
1436
Willy Tarreau977b8e42006-12-29 14:19:17 +01001437 if (defproxy.cookie_name)
1438 curproxy->cookie_name = strdup(defproxy.cookie_name);
1439 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001440 if (defproxy.cookie_domain)
1441 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001442
Willy Tarreau31936852010-10-06 16:59:56 +02001443 if (defproxy.cookie_maxidle)
1444 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1445
1446 if (defproxy.cookie_maxlife)
1447 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1448
Emeric Brun647caf12009-06-30 17:57:00 +02001449 if (defproxy.rdp_cookie_name)
1450 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1451 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1452
Willy Tarreau01732802007-11-01 22:48:15 +01001453 if (defproxy.url_param_name)
1454 curproxy->url_param_name = strdup(defproxy.url_param_name);
1455 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001456
Benoitaffb4812009-03-25 13:02:10 +01001457 if (defproxy.hh_name)
1458 curproxy->hh_name = strdup(defproxy.hh_name);
1459 curproxy->hh_len = defproxy.hh_len;
1460 curproxy->hh_match_domain = defproxy.hh_match_domain;
1461
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001462 if (defproxy.iface_name)
1463 curproxy->iface_name = strdup(defproxy.iface_name);
1464 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001466
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001467 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001468 if (defproxy.capture_name)
1469 curproxy->capture_name = strdup(defproxy.capture_name);
1470 curproxy->capture_namelen = defproxy.capture_namelen;
1471 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473
Willy Tarreau977b8e42006-12-29 14:19:17 +01001474 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001475 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001476 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001477 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001478 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001479 curproxy->uri_auth = defproxy.uri_auth;
1480 curproxy->mon_net = defproxy.mon_net;
1481 curproxy->mon_mask = defproxy.mon_mask;
1482 if (defproxy.monitor_uri)
1483 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1484 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001485 if (defproxy.defbe.name)
1486 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001487 }
1488
1489 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001490 curproxy->timeout.connect = defproxy.timeout.connect;
1491 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001492 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001493 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001494 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001495 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001496 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001497 curproxy->source_addr = defproxy.source_addr;
1498 }
1499
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500 curproxy->mode = defproxy.mode;
1501 curproxy->logfac1 = defproxy.logfac1;
1502 curproxy->logsrv1 = defproxy.logsrv1;
1503 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001504 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001505 curproxy->logfac2 = defproxy.logfac2;
1506 curproxy->logsrv2 = defproxy.logsrv2;
1507 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001508 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001509 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001510 curproxy->conf.used_listener_id = EB_ROOT;
1511 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001512
Willy Tarreau93893792009-07-23 13:19:11 +02001513 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001514 }
1515 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1516 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001517 /* FIXME-20070101: we should do this too at the end of the
1518 * config parsing to free all default values.
1519 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001520 free(defproxy.check_req);
1521 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001522 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001523 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001524 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001525 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001526 free(defproxy.capture_name);
1527 free(defproxy.monitor_uri);
1528 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001529 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001530 free(defproxy.fwdfor_hdr_name);
1531 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001532 free(defproxy.orgto_hdr_name);
1533 defproxy.orgto_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001534 free(defproxy.expect_str);
1535 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001536
Willy Tarreaua534fea2008-08-03 12:19:50 +02001537 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001538 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001539
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540 /* we cannot free uri_auth because it might already be used */
1541 init_default_instance();
1542 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001543 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545 }
1546 else if (curproxy == NULL) {
1547 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001548 err_code |= ERR_ALERT | ERR_FATAL;
1549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001550 }
1551
Willy Tarreau977b8e42006-12-29 14:19:17 +01001552
1553 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001555 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001556 int cur_arg;
1557
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558 if (curproxy == &defproxy) {
1559 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001560 err_code |= ERR_ALERT | ERR_FATAL;
1561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001563 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001564 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565
Emeric Bruned760922010-10-22 17:59:25 +02001566 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001567 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001569 err_code |= ERR_ALERT | ERR_FATAL;
1570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001572
1573 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001574
1575 /* NOTE: the following line might create several listeners if there
1576 * are comma-separated IPs or port ranges. So all further processing
1577 * will have to be applied to all listeners created after last_listen.
1578 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001579 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001580 err_code |= ERR_ALERT | ERR_FATAL;
1581 goto out;
1582 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001583
Willy Tarreau90a570f2009-10-04 20:54:54 +02001584 new_listen = curproxy->listen;
1585 while (new_listen != last_listen) {
1586 new_listen->conf.file = file;
1587 new_listen->conf.line = linenum;
1588 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001589 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001590 }
1591
Emeric Bruned760922010-10-22 17:59:25 +02001592 /* Set default global rights and owner for unix bind */
1593 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1594 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1595 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001596 cur_arg = 2;
1597 while (*(args[cur_arg])) {
1598 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1599#ifdef SO_BINDTODEVICE
1600 struct listener *l;
1601
Emeric Bruned760922010-10-22 17:59:25 +02001602 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1603 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1604 file, linenum, args[0], args[cur_arg]);
1605 err_code |= ERR_ALERT | ERR_FATAL;
1606 goto out;
1607 }
1608
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001609 if (!*args[cur_arg + 1]) {
1610 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1611 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001612 err_code |= ERR_ALERT | ERR_FATAL;
1613 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001614 }
1615
1616 for (l = curproxy->listen; l != last_listen; l = l->next)
1617 l->interface = strdup(args[cur_arg + 1]);
1618
1619 global.last_checks |= LSTCHK_NETADM;
1620
1621 cur_arg += 2;
1622 continue;
1623#else
1624 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1625 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001626 err_code |= ERR_ALERT | ERR_FATAL;
1627 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001628#endif
1629 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001630 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1631#ifdef TCP_MAXSEG
1632 struct listener *l;
1633 int mss;
1634
Emeric Bruned760922010-10-22 17:59:25 +02001635 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1636 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1637 file, linenum, args[0], args[cur_arg]);
1638 err_code |= ERR_ALERT | ERR_FATAL;
1639 goto out;
1640 }
1641
Willy Tarreaube1b9182009-06-14 18:48:19 +02001642 if (!*args[cur_arg + 1]) {
1643 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1644 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001645 err_code |= ERR_ALERT | ERR_FATAL;
1646 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001647 }
1648
Willy Tarreau48a7e722010-12-24 15:26:39 +01001649 mss = atoi(args[cur_arg + 1]);
1650 if (!mss || abs(mss) > 65535) {
1651 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001652 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001653 err_code |= ERR_ALERT | ERR_FATAL;
1654 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001655 }
1656
1657 for (l = curproxy->listen; l != last_listen; l = l->next)
1658 l->maxseg = mss;
1659
1660 cur_arg += 2;
1661 continue;
1662#else
1663 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1664 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001665 err_code |= ERR_ALERT | ERR_FATAL;
1666 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001667#endif
1668 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001669
1670 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1671#ifdef TCP_DEFER_ACCEPT
1672 struct listener *l;
1673
1674 for (l = curproxy->listen; l != last_listen; l = l->next)
1675 l->options |= LI_O_DEF_ACCEPT;
1676
1677 cur_arg ++;
1678 continue;
1679#else
1680 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1681 file, linenum, args[0], args[cur_arg]);
1682 err_code |= ERR_ALERT | ERR_FATAL;
1683 goto out;
1684#endif
1685 }
1686
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001687 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001688#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001689 struct listener *l;
1690
Emeric Bruned760922010-10-22 17:59:25 +02001691 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1692 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1693 file, linenum, args[0], args[cur_arg]);
1694 err_code |= ERR_ALERT | ERR_FATAL;
1695 goto out;
1696 }
1697
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001698 for (l = curproxy->listen; l != last_listen; l = l->next)
1699 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001700
1701 cur_arg ++;
1702 continue;
1703#else
1704 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1705 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001706 err_code |= ERR_ALERT | ERR_FATAL;
1707 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001708#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001709 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001710
Willy Tarreau8a956912010-10-15 14:27:08 +02001711 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1712 struct listener *l;
1713
1714 for (l = curproxy->listen; l != last_listen; l = l->next)
1715 l->options |= LI_O_ACC_PROXY;
1716
1717 cur_arg ++;
1718 continue;
1719 }
1720
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001721 if (!strcmp(args[cur_arg], "name")) {
1722 struct listener *l;
1723
1724 for (l = curproxy->listen; l != last_listen; l = l->next)
1725 l->name = strdup(args[cur_arg + 1]);
1726
1727 cur_arg += 2;
1728 continue;
1729 }
1730
1731 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001732 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001733 struct listener *l;
1734
1735 if (curproxy->listen->next != last_listen) {
1736 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1737 file, linenum, args[cur_arg]);
1738 err_code |= ERR_ALERT | ERR_FATAL;
1739 goto out;
1740 }
1741
1742 if (!*args[cur_arg + 1]) {
1743 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1744 file, linenum, args[cur_arg]);
1745 err_code |= ERR_ALERT | ERR_FATAL;
1746 goto out;
1747 }
1748
1749 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001750 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001751
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001752 if (curproxy->listen->luid <= 0) {
1753 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001754 file, linenum);
1755 err_code |= ERR_ALERT | ERR_FATAL;
1756 goto out;
1757 }
1758
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001759 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1760 if (node) {
1761 l = container_of(node, struct listener, conf.id);
1762 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1763 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
1766 }
1767 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1768
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001769 cur_arg += 2;
1770 continue;
1771 }
1772
Emeric Bruned760922010-10-22 17:59:25 +02001773 if (!strcmp(args[cur_arg], "mode")) {
1774
1775 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1776 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1777 file, linenum, args[0], args[cur_arg]);
1778 err_code |= ERR_ALERT | ERR_FATAL;
1779 goto out;
1780 }
1781
1782 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1783
1784 cur_arg += 2;
1785 continue;
1786 }
1787
1788 if (!strcmp(args[cur_arg], "uid")) {
1789
1790 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1791 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1792 file, linenum, args[0], args[cur_arg]);
1793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796
1797 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1798 cur_arg += 2;
1799 continue;
1800 }
1801
1802 if (!strcmp(args[cur_arg], "gid")) {
1803
1804 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1805 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1806 file, linenum, args[0], args[cur_arg]);
1807 err_code |= ERR_ALERT | ERR_FATAL;
1808 goto out;
1809 }
1810
1811 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1812 cur_arg += 2;
1813 continue;
1814 }
1815
1816 if (!strcmp(args[cur_arg], "user")) {
1817 struct passwd *user;
1818
1819 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1820 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1821 file, linenum, args[0], args[cur_arg]);
1822 err_code |= ERR_ALERT | ERR_FATAL;
1823 goto out;
1824 }
1825 user = getpwnam(args[cur_arg + 1]);
1826 if (!user) {
1827 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1828 file, linenum, args[0], args[cur_arg + 1 ]);
1829 err_code |= ERR_ALERT | ERR_FATAL;
1830 goto out;
1831 }
1832
1833 curproxy->listen->perm.ux.uid = user->pw_uid;
1834 cur_arg += 2;
1835 continue;
1836 }
1837
1838 if (!strcmp(args[cur_arg], "group")) {
1839 struct group *group;
1840
1841 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1842 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1843 file, linenum, args[0], args[cur_arg]);
1844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
1846 }
1847 group = getgrnam(args[cur_arg + 1]);
1848 if (!group) {
1849 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1850 file, linenum, args[0], args[cur_arg + 1 ]);
1851 err_code |= ERR_ALERT | ERR_FATAL;
1852 goto out;
1853 }
1854
1855 curproxy->listen->perm.ux.gid = group->gr_gid;
1856 cur_arg += 2;
1857 continue;
1858 }
1859
Willy Tarreau8a956912010-10-15 14:27:08 +02001860 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001861 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001862 err_code |= ERR_ALERT | ERR_FATAL;
1863 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001864 }
Willy Tarreau93893792009-07-23 13:19:11 +02001865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001866 }
1867 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1868 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1869 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1870 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001871 err_code |= ERR_ALERT | ERR_FATAL;
1872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001873 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001874 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001875 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001876
Willy Tarreaubaaee002006-06-26 02:48:02 +02001877 /* flush useless bits */
1878 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001880 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001881 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001882 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001883 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001884
Willy Tarreau1c47f852006-07-09 08:22:27 +02001885 if (!*args[1]) {
1886 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1887 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001888 err_code |= ERR_ALERT | ERR_FATAL;
1889 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001890 }
1891
Willy Tarreaua534fea2008-08-03 12:19:50 +02001892 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001893 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001894 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001895 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001896 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1897
Willy Tarreau93893792009-07-23 13:19:11 +02001898 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1901 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1902 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1903 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1904 else {
1905 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001906 err_code |= ERR_ALERT | ERR_FATAL;
1907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001908 }
1909 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001910 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001911 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001912
1913 if (curproxy == &defproxy) {
1914 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1915 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001916 err_code |= ERR_ALERT | ERR_FATAL;
1917 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001918 }
1919
1920 if (!*args[1]) {
1921 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1922 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001923 err_code |= ERR_ALERT | ERR_FATAL;
1924 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001925 }
1926
1927 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001928 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001929
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001930 if (curproxy->uuid <= 0) {
1931 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001932 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001933 err_code |= ERR_ALERT | ERR_FATAL;
1934 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001935 }
1936
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001937 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1938 if (node) {
1939 struct proxy *target = container_of(node, struct proxy, conf.id);
1940 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1941 file, linenum, proxy_type_str(curproxy), curproxy->id,
1942 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1943 err_code |= ERR_ALERT | ERR_FATAL;
1944 goto out;
1945 }
1946 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001947 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001948 else if (!strcmp(args[0], "description")) {
1949 int i, len=0;
1950 char *d;
1951
Cyril Bonté99ed3272010-01-24 23:29:44 +01001952 if (curproxy == &defproxy) {
1953 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1954 file, linenum, args[0]);
1955 err_code |= ERR_ALERT | ERR_FATAL;
1956 goto out;
1957 }
1958
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001959 if (!*args[1]) {
1960 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1961 file, linenum, args[0]);
1962 return -1;
1963 }
1964
1965 for(i=1; *args[i]; i++)
1966 len += strlen(args[i])+1;
1967
1968 d = (char *)calloc(1, len);
1969 curproxy->desc = d;
1970
1971 d += sprintf(d, "%s", args[1]);
1972 for(i=2; *args[i]; i++)
1973 d += sprintf(d, " %s", args[i]);
1974
1975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1977 curproxy->state = PR_STSTOPPED;
1978 }
1979 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1980 curproxy->state = PR_STNEW;
1981 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001982 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1983 int cur_arg = 1;
1984 unsigned int set = 0;
1985
1986 while (*args[cur_arg]) {
1987 int u;
1988 if (strcmp(args[cur_arg], "all") == 0) {
1989 set = 0;
1990 break;
1991 }
1992 else if (strcmp(args[cur_arg], "odd") == 0) {
1993 set |= 0x55555555;
1994 }
1995 else if (strcmp(args[cur_arg], "even") == 0) {
1996 set |= 0xAAAAAAAA;
1997 }
1998 else {
1999 u = str2uic(args[cur_arg]);
2000 if (u < 1 || u > 32) {
2001 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2002 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002003 err_code |= ERR_ALERT | ERR_FATAL;
2004 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002005 }
2006 if (u > global.nbproc) {
2007 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2008 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002009 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002010 }
2011 set |= 1 << (u - 1);
2012 }
2013 cur_arg++;
2014 }
2015 curproxy->bind_proc = set;
2016 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002017 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002018 if (curproxy == &defproxy) {
2019 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002020 err_code |= ERR_ALERT | ERR_FATAL;
2021 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002022 }
2023
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002024 err = invalid_char(args[1]);
2025 if (err) {
2026 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2027 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002028 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002029 }
2030
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002031 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2032 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2033 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_ALERT | ERR_FATAL;
2035 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002036 }
2037 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002038 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2039 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002040
Willy Tarreau977b8e42006-12-29 14:19:17 +01002041 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002042 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002043
Willy Tarreaubaaee002006-06-26 02:48:02 +02002044 if (*(args[1]) == 0) {
2045 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2046 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002047 err_code |= ERR_ALERT | ERR_FATAL;
2048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002050
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002051 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002052 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002053 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002054 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002055 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002056 curproxy->cookie_name = strdup(args[1]);
2057 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002058
Willy Tarreaubaaee002006-06-26 02:48:02 +02002059 cur_arg = 2;
2060 while (*(args[cur_arg])) {
2061 if (!strcmp(args[cur_arg], "rewrite")) {
2062 curproxy->options |= PR_O_COOK_RW;
2063 }
2064 else if (!strcmp(args[cur_arg], "indirect")) {
2065 curproxy->options |= PR_O_COOK_IND;
2066 }
2067 else if (!strcmp(args[cur_arg], "insert")) {
2068 curproxy->options |= PR_O_COOK_INS;
2069 }
2070 else if (!strcmp(args[cur_arg], "nocache")) {
2071 curproxy->options |= PR_O_COOK_NOC;
2072 }
2073 else if (!strcmp(args[cur_arg], "postonly")) {
2074 curproxy->options |= PR_O_COOK_POST;
2075 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002076 else if (!strcmp(args[cur_arg], "preserve")) {
2077 curproxy->options2 |= PR_O2_COOK_PSV;
2078 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002079 else if (!strcmp(args[cur_arg], "prefix")) {
2080 curproxy->options |= PR_O_COOK_PFX;
2081 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002082 else if (!strcmp(args[cur_arg], "domain")) {
2083 if (!*args[cur_arg + 1]) {
2084 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2085 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002086 err_code |= ERR_ALERT | ERR_FATAL;
2087 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002088 }
2089
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002090 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002091 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002092 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2093 " dots nor does not start with a dot."
2094 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002095 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002096 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002097 }
2098
2099 err = invalid_domainchar(args[cur_arg + 1]);
2100 if (err) {
2101 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2102 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002103 err_code |= ERR_ALERT | ERR_FATAL;
2104 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002105 }
2106
Willy Tarreau68a897b2009-12-03 23:28:34 +01002107 if (!curproxy->cookie_domain) {
2108 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2109 } else {
2110 /* one domain was already specified, add another one by
2111 * building the string which will be returned along with
2112 * the cookie.
2113 */
2114 char *new_ptr;
2115 int new_len = strlen(curproxy->cookie_domain) +
2116 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2117 new_ptr = malloc(new_len);
2118 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2119 free(curproxy->cookie_domain);
2120 curproxy->cookie_domain = new_ptr;
2121 }
Willy Tarreau31936852010-10-06 16:59:56 +02002122 cur_arg++;
2123 }
2124 else if (!strcmp(args[cur_arg], "maxidle")) {
2125 unsigned int maxidle;
2126 const char *res;
2127
2128 if (!*args[cur_arg + 1]) {
2129 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2130 file, linenum, args[cur_arg]);
2131 err_code |= ERR_ALERT | ERR_FATAL;
2132 goto out;
2133 }
2134
2135 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2136 if (res) {
2137 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2138 file, linenum, *res, args[cur_arg]);
2139 err_code |= ERR_ALERT | ERR_FATAL;
2140 goto out;
2141 }
2142 curproxy->cookie_maxidle = maxidle;
2143 cur_arg++;
2144 }
2145 else if (!strcmp(args[cur_arg], "maxlife")) {
2146 unsigned int maxlife;
2147 const char *res;
2148
2149 if (!*args[cur_arg + 1]) {
2150 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2151 file, linenum, args[cur_arg]);
2152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
2154 }
2155
2156 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2157 if (res) {
2158 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2159 file, linenum, *res, args[cur_arg]);
2160 err_code |= ERR_ALERT | ERR_FATAL;
2161 goto out;
2162 }
2163 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002164 cur_arg++;
2165 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002166 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002167 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002168 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002169 err_code |= ERR_ALERT | ERR_FATAL;
2170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171 }
2172 cur_arg++;
2173 }
2174 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2175 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2176 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002177 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002178 }
2179
2180 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2181 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2182 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002183 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002185
2186 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2187 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2188 file, linenum);
2189 err_code |= ERR_ALERT | ERR_FATAL;
2190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002191 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002192 else if (!strcmp(args[0], "persist")) { /* persist */
2193 if (*(args[1]) == 0) {
2194 Alert("parsing [%s:%d] : missing persist method.\n",
2195 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002196 err_code |= ERR_ALERT | ERR_FATAL;
2197 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002198 }
2199
2200 if (!strncmp(args[1], "rdp-cookie", 10)) {
2201 curproxy->options2 |= PR_O2_RDPC_PRST;
2202
Emeric Brunb982a3d2010-01-04 15:45:53 +01002203 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002204 const char *beg, *end;
2205
2206 beg = args[1] + 11;
2207 end = strchr(beg, ')');
2208
2209 if (!end || end == beg) {
2210 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2211 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002214 }
2215
2216 free(curproxy->rdp_cookie_name);
2217 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2218 curproxy->rdp_cookie_len = end-beg;
2219 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002220 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002221 free(curproxy->rdp_cookie_name);
2222 curproxy->rdp_cookie_name = strdup("msts");
2223 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2224 }
2225 else { /* syntax */
2226 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2227 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002230 }
2231 }
2232 else {
2233 Alert("parsing [%s:%d] : unknown persist method.\n",
2234 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002235 err_code |= ERR_ALERT | ERR_FATAL;
2236 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002237 }
2238 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002239 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002240 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002242 if (curproxy == &defproxy) {
2243 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2244 err_code |= ERR_ALERT | ERR_FATAL;
2245 goto out;
2246 }
2247
Willy Tarreau977b8e42006-12-29 14:19:17 +01002248 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002250
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002252 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_ALERT | ERR_FATAL;
2255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 }
2257 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002258 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 curproxy->appsession_name = strdup(args[1]);
2260 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2261 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002262 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2263 if (err) {
2264 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2265 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002266 err_code |= ERR_ALERT | ERR_FATAL;
2267 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002268 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002269 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002270
Willy Tarreau51041c72007-09-09 21:56:53 +02002271 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2272 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002273 err_code |= ERR_ALERT | ERR_ABORT;
2274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002276
2277 cur_arg = 6;
2278 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002279 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2280 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002281 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002282 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002283 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002284 } else if (!strcmp(args[cur_arg], "prefix")) {
2285 curproxy->options2 |= PR_O2_AS_PFX;
2286 } else if (!strcmp(args[cur_arg], "mode")) {
2287 if (!*args[cur_arg + 1]) {
2288 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2289 file, linenum, args[0], args[cur_arg]);
2290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
2292 }
2293
2294 cur_arg++;
2295 if (!strcmp(args[cur_arg], "query-string")) {
2296 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2297 curproxy->options2 |= PR_O2_AS_M_QS;
2298 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2299 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2300 curproxy->options2 |= PR_O2_AS_M_PP;
2301 } else {
2302 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
2305 }
2306 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002307 cur_arg++;
2308 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 } /* Url App Session */
2310 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002311 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002312 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002313
Willy Tarreaubaaee002006-06-26 02:48:02 +02002314 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002315 if (curproxy == &defproxy) {
2316 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2317 err_code |= ERR_ALERT | ERR_FATAL;
2318 goto out;
2319 }
2320
Willy Tarreaubaaee002006-06-26 02:48:02 +02002321 if (*(args[4]) == 0) {
2322 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2323 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002327 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 curproxy->capture_name = strdup(args[2]);
2329 curproxy->capture_namelen = strlen(curproxy->capture_name);
2330 curproxy->capture_len = atol(args[4]);
2331 if (curproxy->capture_len >= CAPTURE_LEN) {
2332 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2333 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002334 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 curproxy->capture_len = CAPTURE_LEN - 1;
2336 }
2337 curproxy->to_log |= LW_COOKIE;
2338 }
2339 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2340 struct cap_hdr *hdr;
2341
2342 if (curproxy == &defproxy) {
2343 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 }
2347
2348 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2349 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2350 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002351 err_code |= ERR_ALERT | ERR_FATAL;
2352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 }
2354
2355 hdr = calloc(sizeof(struct cap_hdr), 1);
2356 hdr->next = curproxy->req_cap;
2357 hdr->name = strdup(args[3]);
2358 hdr->namelen = strlen(args[3]);
2359 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002360 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 hdr->index = curproxy->nb_req_cap++;
2362 curproxy->req_cap = hdr;
2363 curproxy->to_log |= LW_REQHDR;
2364 }
2365 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2366 struct cap_hdr *hdr;
2367
2368 if (curproxy == &defproxy) {
2369 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_ALERT | ERR_FATAL;
2371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 }
2373
2374 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2375 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2376 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002377 err_code |= ERR_ALERT | ERR_FATAL;
2378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 }
2380 hdr = calloc(sizeof(struct cap_hdr), 1);
2381 hdr->next = curproxy->rsp_cap;
2382 hdr->name = strdup(args[3]);
2383 hdr->namelen = strlen(args[3]);
2384 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002385 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 hdr->index = curproxy->nb_rsp_cap++;
2387 curproxy->rsp_cap = hdr;
2388 curproxy->to_log |= LW_RSPHDR;
2389 }
2390 else {
2391 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2392 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 }
2396 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002398 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002400
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 if (*(args[1]) == 0) {
2402 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2403 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 }
2407 curproxy->conn_retries = atol(args[1]);
2408 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002409 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002410 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002411
2412 if (curproxy == &defproxy) {
2413 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2414 err_code |= ERR_ALERT | ERR_FATAL;
2415 goto out;
2416 }
2417
Willy Tarreauff011f22011-01-06 17:51:27 +01002418 if (!LIST_ISEMPTY(&curproxy->http_req_rules) && !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002419 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2420 file, linenum, args[0]);
2421 err_code |= ERR_WARN;
2422 }
2423
Willy Tarreauff011f22011-01-06 17:51:27 +01002424 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002425
Willy Tarreauff011f22011-01-06 17:51:27 +01002426 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002427 err_code |= ERR_ALERT | ERR_ABORT;
2428 goto out;
2429 }
2430
Willy Tarreauff011f22011-01-06 17:51:27 +01002431 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2432 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002433 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002434 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002435 if (curproxy == &defproxy) {
2436 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002439 }
2440
Willy Tarreauef6494c2010-01-28 17:12:36 +01002441 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002442 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2443 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002444 err_code |= ERR_ALERT | ERR_FATAL;
2445 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002446 }
2447
Willy Tarreauef6494c2010-01-28 17:12:36 +01002448 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002449 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2450 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_ALERT | ERR_FATAL;
2452 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002453 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002454
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002455 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002456 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002457 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002458 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002459 struct redirect_rule *rule;
2460 int cur_arg;
2461 int type = REDIRECT_TYPE_NONE;
2462 int code = 302;
2463 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002464 char *cookie = NULL;
2465 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002466 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002467
Cyril Bonté99ed3272010-01-24 23:29:44 +01002468 if (curproxy == &defproxy) {
2469 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
2472 }
2473
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002474 cur_arg = 1;
2475 while (*(args[cur_arg])) {
2476 if (!strcmp(args[cur_arg], "location")) {
2477 if (!*args[cur_arg + 1]) {
2478 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2479 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002482 }
2483
2484 type = REDIRECT_TYPE_LOCATION;
2485 cur_arg++;
2486 destination = args[cur_arg];
2487 }
2488 else if (!strcmp(args[cur_arg], "prefix")) {
2489 if (!*args[cur_arg + 1]) {
2490 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2491 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002494 }
2495
2496 type = REDIRECT_TYPE_PREFIX;
2497 cur_arg++;
2498 destination = args[cur_arg];
2499 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002500 else if (!strcmp(args[cur_arg], "set-cookie")) {
2501 if (!*args[cur_arg + 1]) {
2502 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2503 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002506 }
2507
2508 cur_arg++;
2509 cookie = args[cur_arg];
2510 cookie_set = 1;
2511 }
2512 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2513 if (!*args[cur_arg + 1]) {
2514 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2515 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002516 err_code |= ERR_ALERT | ERR_FATAL;
2517 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002518 }
2519
2520 cur_arg++;
2521 cookie = args[cur_arg];
2522 cookie_set = 0;
2523 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002524 else if (!strcmp(args[cur_arg],"code")) {
2525 if (!*args[cur_arg + 1]) {
2526 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2527 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002530 }
2531 cur_arg++;
2532 code = atol(args[cur_arg]);
2533 if (code < 301 || code > 303) {
2534 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2535 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002536 err_code |= ERR_ALERT | ERR_FATAL;
2537 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002538 }
2539 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002540 else if (!strcmp(args[cur_arg],"drop-query")) {
2541 flags |= REDIRECT_FLAG_DROP_QS;
2542 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002543 else if (!strcmp(args[cur_arg],"append-slash")) {
2544 flags |= REDIRECT_FLAG_APPEND_SLASH;
2545 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002546 else if (strcmp(args[cur_arg], "if") == 0 ||
2547 strcmp(args[cur_arg], "unless") == 0) {
2548 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2549 if (!cond) {
2550 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2551 file, linenum, args[0]);
2552 err_code |= ERR_ALERT | ERR_FATAL;
2553 goto out;
2554 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002555 break;
2556 }
2557 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002558 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002559 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002562 }
2563 cur_arg++;
2564 }
2565
2566 if (type == REDIRECT_TYPE_NONE) {
2567 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2568 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002571 }
2572
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002573 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2574 rule->cond = cond;
2575 rule->rdr_str = strdup(destination);
2576 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002577 if (cookie) {
2578 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002579 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002580 */
2581 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002582 if (cookie_set) {
2583 rule->cookie_str = malloc(rule->cookie_len + 10);
2584 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2585 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2586 rule->cookie_len += 9;
2587 } else {
2588 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002589 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002590 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2591 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002592 }
2593 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002594 rule->type = type;
2595 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002596 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002597 LIST_INIT(&rule->list);
2598 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002599 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2600 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002601 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002602 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002603 struct switching_rule *rule;
2604
Willy Tarreaub099aca2008-10-12 17:26:37 +02002605 if (curproxy == &defproxy) {
2606 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002609 }
2610
Willy Tarreau55ea7572007-06-17 19:56:27 +02002611 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002613
2614 if (*(args[1]) == 0) {
2615 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002616 err_code |= ERR_ALERT | ERR_FATAL;
2617 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002618 }
2619
Willy Tarreauef6494c2010-01-28 17:12:36 +01002620 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002621 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2622 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002625 }
2626
Willy Tarreauef6494c2010-01-28 17:12:36 +01002627 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002628 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002629 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002632 }
2633
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002634 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002635
Willy Tarreau55ea7572007-06-17 19:56:27 +02002636 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2637 rule->cond = cond;
2638 rule->be.name = strdup(args[1]);
2639 LIST_INIT(&rule->list);
2640 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2641 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002642 else if ((!strcmp(args[0], "force-persist")) ||
2643 (!strcmp(args[0], "ignore-persist"))) {
2644 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002645
2646 if (curproxy == &defproxy) {
2647 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
2650 }
2651
2652 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2653 err_code |= ERR_WARN;
2654
Willy Tarreauef6494c2010-01-28 17:12:36 +01002655 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002656 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2657 file, linenum, args[0]);
2658 err_code |= ERR_ALERT | ERR_FATAL;
2659 goto out;
2660 }
2661
Willy Tarreauef6494c2010-01-28 17:12:36 +01002662 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002663 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2664 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002665 err_code |= ERR_ALERT | ERR_FATAL;
2666 goto out;
2667 }
2668
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002669 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002670
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002671 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002672 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002673 if (!strcmp(args[0], "force-persist")) {
2674 rule->type = PERSIST_TYPE_FORCE;
2675 } else {
2676 rule->type = PERSIST_TYPE_IGNORE;
2677 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002678 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002679 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002680 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002681 else if (!strcmp(args[0], "stick-table")) {
2682 int myidx = 1;
2683
Emeric Brun32da3c42010-09-23 18:39:19 +02002684 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002685 curproxy->table.type = (unsigned int)-1;
2686 while (*args[myidx]) {
2687 const char *err;
2688
2689 if (strcmp(args[myidx], "size") == 0) {
2690 myidx++;
2691 if (!*(args[myidx])) {
2692 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2693 file, linenum, args[myidx-1]);
2694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
2696 }
2697 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2698 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2699 file, linenum, *err, args[myidx-1]);
2700 err_code |= ERR_ALERT | ERR_FATAL;
2701 goto out;
2702 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002703 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002704 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002705 else if (strcmp(args[myidx], "peers") == 0) {
2706 myidx++;
2707 if (!*(args[myidx])) {
2708 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2709 file, linenum, args[myidx-1]);
2710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
2712 }
2713 curproxy->table.peers.name = strdup(args[myidx++]);
2714 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002715 else if (strcmp(args[myidx], "expire") == 0) {
2716 myidx++;
2717 if (!*(args[myidx])) {
2718 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2719 file, linenum, args[myidx-1]);
2720 err_code |= ERR_ALERT | ERR_FATAL;
2721 goto out;
2722 }
2723 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2724 if (err) {
2725 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2726 file, linenum, *err, args[myidx-1]);
2727 err_code |= ERR_ALERT | ERR_FATAL;
2728 goto out;
2729 }
2730 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002731 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002732 }
2733 else if (strcmp(args[myidx], "nopurge") == 0) {
2734 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002735 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002736 }
2737 else if (strcmp(args[myidx], "type") == 0) {
2738 myidx++;
2739 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2740 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2741 file, linenum, args[myidx]);
2742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
2744 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002745 /* myidx already points to next arg */
2746 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002747 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002748 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002749 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002750
2751 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002752 nw = args[myidx];
2753 while (*nw) {
2754 /* the "store" keyword supports a comma-separated list */
2755 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002756 sa = NULL; /* store arg */
2757 while (*nw && *nw != ',') {
2758 if (*nw == '(') {
2759 *nw = 0;
2760 sa = ++nw;
2761 while (*nw != ')') {
2762 if (!*nw) {
2763 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2764 file, linenum, args[0], cw);
2765 err_code |= ERR_ALERT | ERR_FATAL;
2766 goto out;
2767 }
2768 nw++;
2769 }
2770 *nw = '\0';
2771 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002772 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002773 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002774 if (*nw)
2775 *nw++ = '\0';
2776 type = stktable_get_data_type(cw);
2777 if (type < 0) {
2778 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2779 file, linenum, args[0], cw);
2780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
2782 }
Willy Tarreauac782882010-06-20 10:41:54 +02002783
2784 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2785 switch (err) {
2786 case PE_NONE: break;
2787 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002788 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2789 file, linenum, args[0], cw);
2790 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002791 break;
2792
2793 case PE_ARG_MISSING:
2794 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2795 file, linenum, args[0], cw);
2796 err_code |= ERR_ALERT | ERR_FATAL;
2797 goto out;
2798
2799 case PE_ARG_NOT_USED:
2800 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2801 file, linenum, args[0], cw);
2802 err_code |= ERR_ALERT | ERR_FATAL;
2803 goto out;
2804
2805 default:
2806 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2807 file, linenum, args[0], cw);
2808 err_code |= ERR_ALERT | ERR_FATAL;
2809 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002810 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002811 }
2812 myidx++;
2813 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002814 else {
2815 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2816 file, linenum, args[myidx]);
2817 err_code |= ERR_ALERT | ERR_FATAL;
2818 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002819 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002820 }
2821
2822 if (!curproxy->table.size) {
2823 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2824 file, linenum);
2825 err_code |= ERR_ALERT | ERR_FATAL;
2826 goto out;
2827 }
2828
2829 if (curproxy->table.type == (unsigned int)-1) {
2830 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2831 file, linenum);
2832 err_code |= ERR_ALERT | ERR_FATAL;
2833 goto out;
2834 }
2835 }
2836 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002837 struct sticking_rule *rule;
2838 struct pattern_expr *expr;
2839 int myidx = 0;
2840 const char *name = NULL;
2841 int flags;
2842
2843 if (curproxy == &defproxy) {
2844 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
2847 }
2848
2849 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2850 err_code |= ERR_WARN;
2851 goto out;
2852 }
2853
2854 myidx++;
2855 if ((strcmp(args[myidx], "store") == 0) ||
2856 (strcmp(args[myidx], "store-request") == 0)) {
2857 myidx++;
2858 flags = STK_IS_STORE;
2859 }
2860 else if (strcmp(args[myidx], "store-response") == 0) {
2861 myidx++;
2862 flags = STK_IS_STORE | STK_ON_RSP;
2863 }
2864 else if (strcmp(args[myidx], "match") == 0) {
2865 myidx++;
2866 flags = STK_IS_MATCH;
2867 }
2868 else if (strcmp(args[myidx], "on") == 0) {
2869 myidx++;
2870 flags = STK_IS_MATCH | STK_IS_STORE;
2871 }
2872 else {
2873 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2874 err_code |= ERR_ALERT | ERR_FATAL;
2875 goto out;
2876 }
2877
2878 if (*(args[myidx]) == 0) {
2879 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
2882 }
2883
Emeric Brun485479d2010-09-23 18:02:19 +02002884 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002885 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002886 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
2889 }
2890
2891 if (flags & STK_ON_RSP) {
2892 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2893 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2894 file, linenum, args[0], expr->fetch->kw);
2895 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002896 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002897 goto out;
2898 }
2899 } else {
2900 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2901 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2902 file, linenum, args[0], expr->fetch->kw);
2903 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002904 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002905 goto out;
2906 }
2907 }
2908
2909 if (strcmp(args[myidx], "table") == 0) {
2910 myidx++;
2911 name = args[myidx++];
2912 }
2913
Willy Tarreauef6494c2010-01-28 17:12:36 +01002914 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2915 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002916 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2917 file, linenum, args[0]);
2918 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002919 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002920 goto out;
2921 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002922 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002923 else if (*(args[myidx])) {
2924 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2925 file, linenum, args[0], args[myidx]);
2926 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002927 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002928 goto out;
2929 }
Emeric Brun97679e72010-09-23 17:56:44 +02002930 if (flags & STK_ON_RSP)
2931 err_code |= warnif_cond_requires_req(cond, file, linenum);
2932 else
2933 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002934
Emeric Brunb982a3d2010-01-04 15:45:53 +01002935 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2936 rule->cond = cond;
2937 rule->expr = expr;
2938 rule->flags = flags;
2939 rule->table.name = name ? strdup(name) : NULL;
2940 LIST_INIT(&rule->list);
2941 if (flags & STK_ON_RSP)
2942 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2943 else
2944 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002946 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002947 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002948 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002949
Willy Tarreaubaaee002006-06-26 02:48:02 +02002950 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2951 curproxy->uri_auth = NULL; /* we must detach from the default config */
2952
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002953 if (!*args[1]) {
2954 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002955 } else if (!strcmp(args[1], "admin")) {
2956 struct stats_admin_rule *rule;
2957
2958 if (curproxy == &defproxy) {
2959 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2960 err_code |= ERR_ALERT | ERR_FATAL;
2961 goto out;
2962 }
2963
2964 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2965 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2966 err_code |= ERR_ALERT | ERR_ABORT;
2967 goto out;
2968 }
2969
2970 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2971 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2972 file, linenum, args[0], args[1]);
2973 err_code |= ERR_ALERT | ERR_FATAL;
2974 goto out;
2975 }
2976 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2977 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2978 file, linenum, args[0], args[1]);
2979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
2981 }
2982
2983 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2984
2985 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2986 rule->cond = cond;
2987 LIST_INIT(&rule->list);
2988 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 } else if (!strcmp(args[1], "uri")) {
2990 if (*(args[2]) == 0) {
2991 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2995 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002996 err_code |= ERR_ALERT | ERR_ABORT;
2997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 }
2999 } else if (!strcmp(args[1], "realm")) {
3000 if (*(args[2]) == 0) {
3001 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3005 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003006 err_code |= ERR_ALERT | ERR_ABORT;
3007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003008 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003009 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003010 unsigned interval;
3011
3012 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3013 if (err) {
3014 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3015 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003016 err_code |= ERR_ALERT | ERR_FATAL;
3017 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003018 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3019 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003020 err_code |= ERR_ALERT | ERR_ABORT;
3021 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003022 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003023 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003024 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003025
3026 if (curproxy == &defproxy) {
3027 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
3030 }
3031
3032 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3033 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3034 err_code |= ERR_ALERT | ERR_ABORT;
3035 goto out;
3036 }
3037
Willy Tarreauff011f22011-01-06 17:51:27 +01003038 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3039 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003040 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3041 file, linenum, args[0]);
3042 err_code |= ERR_WARN;
3043 }
3044
Willy Tarreauff011f22011-01-06 17:51:27 +01003045 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003046
Willy Tarreauff011f22011-01-06 17:51:27 +01003047 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003048 err_code |= ERR_ALERT | ERR_ABORT;
3049 goto out;
3050 }
3051
Willy Tarreauff011f22011-01-06 17:51:27 +01003052 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3053 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003054
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055 } else if (!strcmp(args[1], "auth")) {
3056 if (*(args[2]) == 0) {
3057 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3061 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003062 err_code |= ERR_ALERT | ERR_ABORT;
3063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003064 }
3065 } else if (!strcmp(args[1], "scope")) {
3066 if (*(args[2]) == 0) {
3067 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3071 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_ALERT | ERR_ABORT;
3073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 }
3075 } else if (!strcmp(args[1], "enable")) {
3076 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3077 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003078 err_code |= ERR_ALERT | ERR_ABORT;
3079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003081 } else if (!strcmp(args[1], "hide-version")) {
3082 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3083 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003084 err_code |= ERR_ALERT | ERR_ABORT;
3085 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003086 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003087 } else if (!strcmp(args[1], "show-legends")) {
3088 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3089 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3090 err_code |= ERR_ALERT | ERR_ABORT;
3091 goto out;
3092 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003093 } else if (!strcmp(args[1], "show-node")) {
3094
3095 if (*args[2]) {
3096 int i;
3097 char c;
3098
3099 for (i=0; args[2][i]; i++) {
3100 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003101 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3102 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003103 break;
3104 }
3105
3106 if (!i || args[2][i]) {
3107 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3108 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3109 file, linenum, args[0], args[1]);
3110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
3113 }
3114
3115 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3116 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3117 err_code |= ERR_ALERT | ERR_ABORT;
3118 goto out;
3119 }
3120 } else if (!strcmp(args[1], "show-desc")) {
3121 char *desc = NULL;
3122
3123 if (*args[2]) {
3124 int i, len=0;
3125 char *d;
3126
3127 for(i=2; *args[i]; i++)
3128 len += strlen(args[i])+1;
3129
3130 desc = d = (char *)calloc(1, len);
3131
3132 d += sprintf(d, "%s", args[2]);
3133 for(i=3; *args[i]; i++)
3134 d += sprintf(d, " %s", args[i]);
3135 }
3136
3137 if (!*args[2] && !global.desc)
3138 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3139 file, linenum, args[1]);
3140 else {
3141 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3142 free(desc);
3143 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3144 err_code |= ERR_ALERT | ERR_ABORT;
3145 goto out;
3146 }
3147 free(desc);
3148 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003149 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003150stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003151 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003152 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 }
3156 }
3157 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003158 int optnum;
3159
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003160 if (*(args[1]) == '\0') {
3161 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3162 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003165 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003166
3167 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3168 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003169 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3170 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3171 file, linenum, cfg_opts[optnum].name);
3172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
3174 }
Willy Tarreau93893792009-07-23 13:19:11 +02003175 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3176 err_code |= ERR_WARN;
3177 goto out;
3178 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003179
Willy Tarreau3842f002009-06-14 11:39:52 +02003180 curproxy->no_options &= ~cfg_opts[optnum].val;
3181 curproxy->options &= ~cfg_opts[optnum].val;
3182
3183 switch (kwm) {
3184 case KWM_STD:
3185 curproxy->options |= cfg_opts[optnum].val;
3186 break;
3187 case KWM_NO:
3188 curproxy->no_options |= cfg_opts[optnum].val;
3189 break;
3190 case KWM_DEF: /* already cleared */
3191 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003192 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003193
Willy Tarreau93893792009-07-23 13:19:11 +02003194 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003195 }
3196 }
3197
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003198 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3199 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003200 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3201 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3202 file, linenum, cfg_opts2[optnum].name);
3203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
3205 }
Willy Tarreau93893792009-07-23 13:19:11 +02003206 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3207 err_code |= ERR_WARN;
3208 goto out;
3209 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003210
Willy Tarreau3842f002009-06-14 11:39:52 +02003211 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3212 curproxy->options2 &= ~cfg_opts2[optnum].val;
3213
3214 switch (kwm) {
3215 case KWM_STD:
3216 curproxy->options2 |= cfg_opts2[optnum].val;
3217 break;
3218 case KWM_NO:
3219 curproxy->no_options2 |= cfg_opts2[optnum].val;
3220 break;
3221 case KWM_DEF: /* already cleared */
3222 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003223 }
Willy Tarreau93893792009-07-23 13:19:11 +02003224 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003225 }
3226 }
3227
Willy Tarreau3842f002009-06-14 11:39:52 +02003228 if (kwm != KWM_STD) {
3229 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003230 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003231 err_code |= ERR_ALERT | ERR_FATAL;
3232 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003233 }
3234
Emeric Brun3a058f32009-06-30 18:26:00 +02003235 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003236 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003237 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003239 if (*(args[2]) != '\0') {
3240 if (!strcmp(args[2], "clf")) {
3241 curproxy->options2 |= PR_O2_CLFLOG;
3242 } else {
3243 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003244 err_code |= ERR_ALERT | ERR_FATAL;
3245 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003246 }
3247 }
3248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003249 else if (!strcmp(args[1], "tcplog"))
3250 /* generate a detailed TCP log */
3251 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252 else if (!strcmp(args[1], "tcpka")) {
3253 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003254 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003255 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003256
3257 if (curproxy->cap & PR_CAP_FE)
3258 curproxy->options |= PR_O_TCP_CLI_KA;
3259 if (curproxy->cap & PR_CAP_BE)
3260 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 }
3262 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003263 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003264 err_code |= ERR_WARN;
3265
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003267 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003268 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003269 curproxy->options2 &= ~PR_O2_CHK_ANY;
3270 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 if (!*args[2]) { /* no argument */
3272 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3273 curproxy->check_len = strlen(DEF_CHECK_REQ);
3274 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003275 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 curproxy->check_req = (char *)malloc(reqlen);
3277 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003278 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003279 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003280 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 if (*args[4])
3282 reqlen += strlen(args[4]);
3283 else
3284 reqlen += strlen("HTTP/1.0");
3285
3286 curproxy->check_req = (char *)malloc(reqlen);
3287 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003288 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003290 }
3291 else if (!strcmp(args[1], "ssl-hello-chk")) {
3292 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003293 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003295
Willy Tarreaua534fea2008-08-03 12:19:50 +02003296 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003297 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003298 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003299 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 }
Willy Tarreau23677902007-05-08 23:50:35 +02003301 else if (!strcmp(args[1], "smtpchk")) {
3302 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003303 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003304 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003305 curproxy->options2 &= ~PR_O2_CHK_ANY;
3306 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003307
3308 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3309 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3310 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3311 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3312 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3313 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3314 curproxy->check_req = (char *)malloc(reqlen);
3315 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3316 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3317 } else {
3318 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3319 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3320 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3321 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3322 }
3323 }
3324 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003325 else if (!strcmp(args[1], "pgsql-check")) {
3326 /* use PostgreSQL request to check servers' health */
3327 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3328 err_code |= ERR_WARN;
3329
3330 free(curproxy->check_req);
3331 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003332 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003333 curproxy->options2 |= PR_O2_PGSQL_CHK;
3334
3335 if (*(args[2])) {
3336 int cur_arg = 2;
3337
3338 while (*(args[cur_arg])) {
3339 if (strcmp(args[cur_arg], "user") == 0) {
3340 char * packet;
3341 uint32_t packet_len;
3342 uint32_t pv;
3343
3344 /* suboption header - needs additional argument for it */
3345 if (*(args[cur_arg+1]) == 0) {
3346 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3347 file, linenum, args[0], args[1], args[cur_arg]);
3348 err_code |= ERR_ALERT | ERR_FATAL;
3349 goto out;
3350 }
3351
3352 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3353 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3354 pv = htonl(0x30000); /* protocol version 3.0 */
3355
3356 packet = (char*) calloc(1, packet_len);
3357
3358 memcpy(packet + 4, &pv, 4);
3359
3360 /* copy "user" */
3361 memcpy(packet + 8, "user", 4);
3362
3363 /* copy username */
3364 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3365
3366 free(curproxy->check_req);
3367 curproxy->check_req = packet;
3368 curproxy->check_len = packet_len;
3369
3370 packet_len = htonl(packet_len);
3371 memcpy(packet, &packet_len, 4);
3372 cur_arg += 2;
3373 } else {
3374 /* unknown suboption - catchall */
3375 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3376 file, linenum, args[0], args[1]);
3377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
3379 }
3380 } /* end while loop */
3381 }
3382 }
3383
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003384 else if (!strcmp(args[1], "redis-check")) {
3385 /* use REDIS PING request to check servers' health */
3386 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3387 err_code |= ERR_WARN;
3388
3389 free(curproxy->check_req);
3390 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003391 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003392 curproxy->options2 |= PR_O2_REDIS_CHK;
3393
3394 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3395 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3396 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3397 }
3398
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003399 else if (!strcmp(args[1], "mysql-check")) {
3400 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003401 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3402 err_code |= ERR_WARN;
3403
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003404 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003405 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003406 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003407 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003408
3409 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3410 * const char mysql40_client_auth_pkt[] = {
3411 * "\x0e\x00\x00" // packet length
3412 * "\x01" // packet number
3413 * "\x00\x00" // client capabilities
3414 * "\x00\x00\x01" // max packet
3415 * "haproxy\x00" // username (null terminated string)
3416 * "\x00" // filler (always 0x00)
3417 * "\x01\x00\x00" // packet length
3418 * "\x00" // packet number
3419 * "\x01" // COM_QUIT command
3420 * };
3421 */
3422
3423 if (*(args[2])) {
3424 int cur_arg = 2;
3425
3426 while (*(args[cur_arg])) {
3427 if (strcmp(args[cur_arg], "user") == 0) {
3428 char *mysqluser;
3429 int packetlen, reqlen, userlen;
3430
3431 /* suboption header - needs additional argument for it */
3432 if (*(args[cur_arg+1]) == 0) {
3433 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3434 file, linenum, args[0], args[1], args[cur_arg]);
3435 err_code |= ERR_ALERT | ERR_FATAL;
3436 goto out;
3437 }
3438 mysqluser = args[cur_arg + 1];
3439 userlen = strlen(mysqluser);
3440 packetlen = userlen + 7;
3441 reqlen = packetlen + 9;
3442
3443 free(curproxy->check_req);
3444 curproxy->check_req = (char *)calloc(1, reqlen);
3445 curproxy->check_len = reqlen;
3446
3447 snprintf(curproxy->check_req, 4, "%c%c%c",
3448 ((unsigned char) packetlen & 0xff),
3449 ((unsigned char) (packetlen >> 8) & 0xff),
3450 ((unsigned char) (packetlen >> 16) & 0xff));
3451
3452 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003453 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003454 curproxy->check_req[8] = 1;
3455 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3456 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3457 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3458 cur_arg += 2;
3459 } else {
3460 /* unknown suboption - catchall */
3461 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3462 file, linenum, args[0], args[1]);
3463 err_code |= ERR_ALERT | ERR_FATAL;
3464 goto out;
3465 }
3466 } /* end while loop */
3467 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003468 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003469 else if (!strcmp(args[1], "ldap-check")) {
3470 /* use LDAP request to check servers' health */
3471 free(curproxy->check_req);
3472 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003473 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003474 curproxy->options2 |= PR_O2_LDAP_CHK;
3475
3476 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3477 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3478 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3479 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003480 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003481 int cur_arg;
3482
3483 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3484 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003485 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003486
Willy Tarreau87cf5142011-08-19 22:57:24 +02003487 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003488
3489 free(curproxy->fwdfor_hdr_name);
3490 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3491 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3492
3493 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3494 cur_arg = 2;
3495 while (*(args[cur_arg])) {
3496 if (!strcmp(args[cur_arg], "except")) {
3497 /* suboption except - needs additional argument for it */
3498 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3499 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3500 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003503 }
3504 /* flush useless bits */
3505 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003506 cur_arg += 2;
3507 } else if (!strcmp(args[cur_arg], "header")) {
3508 /* suboption header - needs additional argument for it */
3509 if (*(args[cur_arg+1]) == 0) {
3510 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3511 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003512 err_code |= ERR_ALERT | ERR_FATAL;
3513 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003514 }
3515 free(curproxy->fwdfor_hdr_name);
3516 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3517 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3518 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003519 } else if (!strcmp(args[cur_arg], "if-none")) {
3520 curproxy->options &= ~PR_O_FF_ALWAYS;
3521 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003522 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003523 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003524 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003525 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003528 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003529 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003530 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003531 else if (!strcmp(args[1], "originalto")) {
3532 int cur_arg;
3533
3534 /* insert x-original-to field, but not for the IP address listed as an except.
3535 * set default options (ie: bitfield, header name, etc)
3536 */
3537
3538 curproxy->options |= PR_O_ORGTO;
3539
3540 free(curproxy->orgto_hdr_name);
3541 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3542 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3543
Willy Tarreau87cf5142011-08-19 22:57:24 +02003544 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003545 cur_arg = 2;
3546 while (*(args[cur_arg])) {
3547 if (!strcmp(args[cur_arg], "except")) {
3548 /* suboption except - needs additional argument for it */
3549 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3550 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3551 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003554 }
3555 /* flush useless bits */
3556 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3557 cur_arg += 2;
3558 } else if (!strcmp(args[cur_arg], "header")) {
3559 /* suboption header - needs additional argument for it */
3560 if (*(args[cur_arg+1]) == 0) {
3561 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3562 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003565 }
3566 free(curproxy->orgto_hdr_name);
3567 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3568 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3569 cur_arg += 2;
3570 } else {
3571 /* unknown suboption - catchall */
3572 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3573 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003576 }
3577 } /* end while loop */
3578 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003579 else {
3580 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003581 err_code |= ERR_ALERT | ERR_FATAL;
3582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003583 }
Willy Tarreau93893792009-07-23 13:19:11 +02003584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003585 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003586 else if (!strcmp(args[0], "default_backend")) {
3587 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003588 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003589
3590 if (*(args[1]) == 0) {
3591 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003592 err_code |= ERR_ALERT | ERR_FATAL;
3593 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003594 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003595 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003596 curproxy->defbe.name = strdup(args[1]);
3597 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003598 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003599 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003600 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003601
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003602 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3603 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003604 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003605 /* enable reconnections to dispatch */
3606 curproxy->options |= PR_O_REDISP;
3607 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003608 else if (!strcmp(args[0], "http-check")) {
3609 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003610 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003611
3612 if (strcmp(args[1], "disable-on-404") == 0) {
3613 /* enable a graceful server shutdown on an HTTP 404 response */
3614 curproxy->options |= PR_O_DISABLE404;
3615 }
Willy Tarreauef781042010-01-27 11:53:01 +01003616 else if (strcmp(args[1], "send-state") == 0) {
3617 /* enable emission of the apparent state of a server in HTTP checks */
3618 curproxy->options2 |= PR_O2_CHK_SNDST;
3619 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003620 else if (strcmp(args[1], "expect") == 0) {
3621 const char *ptr_arg;
3622 int cur_arg;
3623
3624 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3625 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3626 err_code |= ERR_ALERT | ERR_FATAL;
3627 goto out;
3628 }
3629
3630 cur_arg = 2;
3631 /* consider exclamation marks, sole or at the beginning of a word */
3632 while (*(ptr_arg = args[cur_arg])) {
3633 while (*ptr_arg == '!') {
3634 curproxy->options2 ^= PR_O2_EXP_INV;
3635 ptr_arg++;
3636 }
3637 if (*ptr_arg)
3638 break;
3639 cur_arg++;
3640 }
3641 /* now ptr_arg points to the beginning of a word past any possible
3642 * exclamation mark, and cur_arg is the argument which holds this word.
3643 */
3644 if (strcmp(ptr_arg, "status") == 0) {
3645 if (!*(args[cur_arg + 1])) {
3646 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3647 file, linenum, args[0], args[1], ptr_arg);
3648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
3650 }
3651 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003652 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003653 curproxy->expect_str = strdup(args[cur_arg + 1]);
3654 }
3655 else if (strcmp(ptr_arg, "string") == 0) {
3656 if (!*(args[cur_arg + 1])) {
3657 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3658 file, linenum, args[0], args[1], ptr_arg);
3659 err_code |= ERR_ALERT | ERR_FATAL;
3660 goto out;
3661 }
3662 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003663 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003664 curproxy->expect_str = strdup(args[cur_arg + 1]);
3665 }
3666 else if (strcmp(ptr_arg, "rstatus") == 0) {
3667 if (!*(args[cur_arg + 1])) {
3668 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3669 file, linenum, args[0], args[1], ptr_arg);
3670 err_code |= ERR_ALERT | ERR_FATAL;
3671 goto out;
3672 }
3673 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003674 free(curproxy->expect_str);
3675 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3676 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003677 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3678 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3679 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3680 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
3683 }
3684 }
3685 else if (strcmp(ptr_arg, "rstring") == 0) {
3686 if (!*(args[cur_arg + 1])) {
3687 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3688 file, linenum, args[0], args[1], ptr_arg);
3689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
3691 }
3692 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003693 free(curproxy->expect_str);
3694 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3695 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003696 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3697 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3698 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3699 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3700 err_code |= ERR_ALERT | ERR_FATAL;
3701 goto out;
3702 }
3703 }
3704 else {
3705 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3706 file, linenum, args[0], args[1], ptr_arg);
3707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
3709 }
3710 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003711 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003712 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 +02003713 err_code |= ERR_ALERT | ERR_FATAL;
3714 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003715 }
3716 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003717 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003718 if (curproxy == &defproxy) {
3719 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003720 err_code |= ERR_ALERT | ERR_FATAL;
3721 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003722 }
3723
Willy Tarreaub80c2302007-11-30 20:51:32 +01003724 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003725 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003726
3727 if (strcmp(args[1], "fail") == 0) {
3728 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003729 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003730 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3731 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003734 }
3735
Willy Tarreauef6494c2010-01-28 17:12:36 +01003736 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003737 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3738 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003739 err_code |= ERR_ALERT | ERR_FATAL;
3740 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003741 }
3742 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3743 }
3744 else {
3745 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003746 err_code |= ERR_ALERT | ERR_FATAL;
3747 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003748 }
3749 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003750#ifdef TPROXY
3751 else if (!strcmp(args[0], "transparent")) {
3752 /* enable transparent proxy connections */
3753 curproxy->options |= PR_O_TRANSP;
3754 }
3755#endif
3756 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003757 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003758 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003759
Willy Tarreaubaaee002006-06-26 02:48:02 +02003760 if (*(args[1]) == 0) {
3761 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003764 }
3765 curproxy->maxconn = atol(args[1]);
3766 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003767 else if (!strcmp(args[0], "backlog")) { /* backlog */
3768 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003769 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003770
3771 if (*(args[1]) == 0) {
3772 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003775 }
3776 curproxy->backlog = atol(args[1]);
3777 }
Willy Tarreau86034312006-12-29 00:10:33 +01003778 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003779 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003780 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003781
Willy Tarreau86034312006-12-29 00:10:33 +01003782 if (*(args[1]) == 0) {
3783 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003786 }
3787 curproxy->fullconn = atol(args[1]);
3788 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3790 if (*(args[1]) == 0) {
3791 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003794 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003795 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3796 if (err) {
3797 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3798 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003801 }
3802 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003803 }
3804 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003805 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003806 if (curproxy == &defproxy) {
3807 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003811 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003813
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 if (strchr(args[1], ':') == NULL) {
3815 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003816 err_code |= ERR_ALERT | ERR_FATAL;
3817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003818 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003819 sk = str2sa(args[1]);
3820 if (!sk) {
3821 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
3824 }
3825 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003826 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003827 }
3828 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003829 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003830 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003831
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003832 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003833 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3834 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003837 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003839 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3840 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3841 err_code |= ERR_WARN;
3842
3843 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3844 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3845 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3846 }
3847 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3848 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3849 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3850 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003851 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3852 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3853 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3854 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003855 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003856 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
3859 }
3860 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003861 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003862 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003863 char *rport, *raddr;
3864 short realport = 0;
3865 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003866
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003867 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003869 err_code |= ERR_ALERT | ERR_FATAL;
3870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003871 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003872 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003873 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003874
3875 if (!*args[2]) {
3876 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3877 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_ALERT | ERR_FATAL;
3879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003880 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003881
3882 err = invalid_char(args[1]);
3883 if (err) {
3884 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3885 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003888 }
3889
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003890 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003891 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003892
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003893 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3894 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3895 err_code |= ERR_ALERT | ERR_ABORT;
3896 goto out;
3897 }
3898
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003899 /* the servers are linked backwards first */
3900 newsrv->next = curproxy->srv;
3901 curproxy->srv = newsrv;
3902 newsrv->proxy = curproxy;
3903 newsrv->conf.file = file;
3904 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003905
Simon Hormanaf514952011-06-21 14:34:57 +09003906 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003907 LIST_INIT(&newsrv->pendconns);
3908 do_check = 0;
3909 newsrv->state = SRV_RUNNING; /* early server setup */
3910 newsrv->last_change = now.tv_sec;
3911 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003912
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003913 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003914 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003915 * - IP: => port=+0, relative
3916 * - IP:N => port=N, absolute
3917 * - IP:+N => port=+N, relative
3918 * - IP:-N => port=-N, relative
3919 */
3920 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003921 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003922 if (rport) {
3923 *rport++ = 0;
3924 realport = atol(rport);
3925 if (!isdigit((unsigned char)*rport))
3926 newsrv->state |= SRV_MAPPORTS;
3927 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003928 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003929
Willy Tarreaufab5a432011-03-04 15:31:53 +01003930 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003931 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003932 if (!sk) {
3933 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3934 err_code |= ERR_ALERT | ERR_FATAL;
3935 goto out;
3936 }
3937 newsrv->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01003938
3939 switch (newsrv->addr.ss_family) {
3940 case AF_INET:
3941 ((struct sockaddr_in *)&newsrv->addr)->sin_port = htons(realport);
3942 break;
3943 case AF_INET6:
3944 ((struct sockaddr_in6 *)&newsrv->addr)->sin6_port = htons(realport);
3945 break;
3946 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003947
3948 newsrv->check_port = curproxy->defsrv.check_port;
3949 newsrv->inter = curproxy->defsrv.inter;
3950 newsrv->fastinter = curproxy->defsrv.fastinter;
3951 newsrv->downinter = curproxy->defsrv.downinter;
3952 newsrv->rise = curproxy->defsrv.rise;
3953 newsrv->fall = curproxy->defsrv.fall;
3954 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3955 newsrv->minconn = curproxy->defsrv.minconn;
3956 newsrv->maxconn = curproxy->defsrv.maxconn;
3957 newsrv->slowstart = curproxy->defsrv.slowstart;
3958 newsrv->onerror = curproxy->defsrv.onerror;
3959 newsrv->consecutive_errors_limit
3960 = curproxy->defsrv.consecutive_errors_limit;
3961 newsrv->uweight = newsrv->iweight
3962 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003963
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003964 newsrv->curfd = -1; /* no health-check in progress */
3965 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003966
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003967 cur_arg = 3;
3968 } else {
3969 newsrv = &curproxy->defsrv;
3970 cur_arg = 1;
3971 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003972
Willy Tarreaubaaee002006-06-26 02:48:02 +02003973 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003974 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003975 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003976
3977 if (!*args[cur_arg + 1]) {
3978 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3979 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003980 err_code |= ERR_ALERT | ERR_FATAL;
3981 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003982 }
3983
3984 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003985 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003986
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003987 if (newsrv->puid <= 0) {
3988 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003989 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003992 }
3993
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003994 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3995 if (node) {
3996 struct server *target = container_of(node, struct server, conf.id);
3997 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3998 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
4001 }
4002 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004003 cur_arg += 2;
4004 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004005 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004006 newsrv->cookie = strdup(args[cur_arg + 1]);
4007 newsrv->cklen = strlen(args[cur_arg + 1]);
4008 cur_arg += 2;
4009 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004010 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004011 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4012 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4013 cur_arg += 2;
4014 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004016 if (!*args[cur_arg + 1]) {
4017 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4018 file, linenum, args[cur_arg]);
4019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
4021 }
4022
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004024 if (newsrv->rise <= 0) {
4025 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4026 file, linenum, args[cur_arg]);
4027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
4029 }
4030
Willy Tarreau96839092010-03-29 10:02:24 +02004031 if (newsrv->health)
4032 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004033 cur_arg += 2;
4034 }
4035 else if (!strcmp(args[cur_arg], "fall")) {
4036 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004037
4038 if (!*args[cur_arg + 1]) {
4039 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4040 file, linenum, args[cur_arg]);
4041 err_code |= ERR_ALERT | ERR_FATAL;
4042 goto out;
4043 }
4044
4045 if (newsrv->fall <= 0) {
4046 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4047 file, linenum, args[cur_arg]);
4048 err_code |= ERR_ALERT | ERR_FATAL;
4049 goto out;
4050 }
4051
Willy Tarreaubaaee002006-06-26 02:48:02 +02004052 cur_arg += 2;
4053 }
4054 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004055 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4056 if (err) {
4057 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4058 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004059 err_code |= ERR_ALERT | ERR_FATAL;
4060 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004061 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004062 if (val <= 0) {
4063 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4064 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004067 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004068 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069 cur_arg += 2;
4070 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004071 else if (!strcmp(args[cur_arg], "fastinter")) {
4072 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4073 if (err) {
4074 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4075 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004078 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004079 if (val <= 0) {
4080 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4081 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004084 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004085 newsrv->fastinter = val;
4086 cur_arg += 2;
4087 }
4088 else if (!strcmp(args[cur_arg], "downinter")) {
4089 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4090 if (err) {
4091 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4092 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004095 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004096 if (val <= 0) {
4097 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4098 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004101 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004102 newsrv->downinter = val;
4103 cur_arg += 2;
4104 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004105 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004106 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004107 if (!sk) {
4108 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4109 err_code |= ERR_ALERT | ERR_FATAL;
4110 goto out;
4111 }
4112 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004113 cur_arg += 2;
4114 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004115 else if (!strcmp(args[cur_arg], "port")) {
4116 newsrv->check_port = atol(args[cur_arg + 1]);
4117 cur_arg += 2;
4118 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004119 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004120 newsrv->state |= SRV_BACKUP;
4121 cur_arg ++;
4122 }
Simon Hormanfa461682011-06-25 09:39:49 +09004123 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4124 newsrv->state |= SRV_NON_STICK;
4125 cur_arg ++;
4126 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004127 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4128 newsrv->state |= SRV_SEND_PROXY;
4129 cur_arg ++;
4130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004131 else if (!strcmp(args[cur_arg], "weight")) {
4132 int w;
4133 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004134 if (w < 0 || w > 256) {
4135 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004136 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004137 err_code |= ERR_ALERT | ERR_FATAL;
4138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004139 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004140 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004141 cur_arg += 2;
4142 }
4143 else if (!strcmp(args[cur_arg], "minconn")) {
4144 newsrv->minconn = atol(args[cur_arg + 1]);
4145 cur_arg += 2;
4146 }
4147 else if (!strcmp(args[cur_arg], "maxconn")) {
4148 newsrv->maxconn = atol(args[cur_arg + 1]);
4149 cur_arg += 2;
4150 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004151 else if (!strcmp(args[cur_arg], "maxqueue")) {
4152 newsrv->maxqueue = atol(args[cur_arg + 1]);
4153 cur_arg += 2;
4154 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004155 else if (!strcmp(args[cur_arg], "slowstart")) {
4156 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004157 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004158 if (err) {
4159 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4160 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004163 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004164 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004165 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4166 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004167 err_code |= ERR_ALERT | ERR_FATAL;
4168 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004169 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004170 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004171 cur_arg += 2;
4172 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004173 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004174
4175 if (!*args[cur_arg + 1]) {
4176 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4177 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004178 err_code |= ERR_ALERT | ERR_FATAL;
4179 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004180 }
4181
4182 newsrv->trackit = strdup(args[cur_arg + 1]);
4183
4184 cur_arg += 2;
4185 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004186 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004187 global.maxsock++;
4188 do_check = 1;
4189 cur_arg += 1;
4190 }
Willy Tarreau96839092010-03-29 10:02:24 +02004191 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4192 newsrv->state |= SRV_MAINTAIN;
4193 newsrv->state &= ~SRV_RUNNING;
4194 newsrv->health = 0;
4195 cur_arg += 1;
4196 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004197 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004198 if (!strcmp(args[cur_arg + 1], "none"))
4199 newsrv->observe = HANA_OBS_NONE;
4200 else if (!strcmp(args[cur_arg + 1], "layer4"))
4201 newsrv->observe = HANA_OBS_LAYER4;
4202 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4203 if (curproxy->mode != PR_MODE_HTTP) {
4204 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4205 file, linenum, args[cur_arg + 1]);
4206 err_code |= ERR_ALERT;
4207 }
4208 newsrv->observe = HANA_OBS_LAYER7;
4209 }
4210 else {
4211 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004212 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004213 file, linenum, args[cur_arg], args[cur_arg + 1]);
4214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
4216 }
4217
4218 cur_arg += 2;
4219 }
4220 else if (!strcmp(args[cur_arg], "on-error")) {
4221 if (!strcmp(args[cur_arg + 1], "fastinter"))
4222 newsrv->onerror = HANA_ONERR_FASTINTER;
4223 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4224 newsrv->onerror = HANA_ONERR_FAILCHK;
4225 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4226 newsrv->onerror = HANA_ONERR_SUDDTH;
4227 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4228 newsrv->onerror = HANA_ONERR_MARKDWN;
4229 else {
4230 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004231 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004232 file, linenum, args[cur_arg], args[cur_arg + 1]);
4233 err_code |= ERR_ALERT | ERR_FATAL;
4234 goto out;
4235 }
4236
4237 cur_arg += 2;
4238 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004239 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4240 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4241 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4242 else {
4243 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4244 file, linenum, args[cur_arg], args[cur_arg + 1]);
4245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
4247 }
4248
4249 cur_arg += 2;
4250 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004251 else if (!strcmp(args[cur_arg], "error-limit")) {
4252 if (!*args[cur_arg + 1]) {
4253 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4254 file, linenum, args[cur_arg]);
4255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
4257 }
4258
4259 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4260
4261 if (newsrv->consecutive_errors_limit <= 0) {
4262 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4263 file, linenum, args[cur_arg]);
4264 err_code |= ERR_ALERT | ERR_FATAL;
4265 goto out;
4266 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004267 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004268 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004269 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004270 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004271 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004272
Willy Tarreaubaaee002006-06-26 02:48:02 +02004273 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004274#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004275 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004276 file, linenum, "source", "usesrc");
4277#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004278 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004279 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004280#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004281 err_code |= ERR_ALERT | ERR_FATAL;
4282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004283 }
4284 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004285 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4286 if (!sk) {
4287 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4288 err_code |= ERR_ALERT | ERR_FATAL;
4289 goto out;
4290 }
4291 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004292
4293 if (port_low != port_high) {
4294 int i;
4295 if (port_low <= 0 || port_low > 65535 ||
4296 port_high <= 0 || port_high > 65535 ||
4297 port_low > port_high) {
4298 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4299 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004302 }
4303 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4304 for (i = 0; i < newsrv->sport_range->size; i++)
4305 newsrv->sport_range->ports[i] = port_low + i;
4306 }
4307
Willy Tarreaubaaee002006-06-26 02:48:02 +02004308 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004309 while (*(args[cur_arg])) {
4310 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004311#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4312#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004313 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4314 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4315 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004316 err_code |= ERR_ALERT | ERR_FATAL;
4317 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004318 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004319#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004320 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004321 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004322 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004325 }
4326 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004327 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004328 newsrv->state |= SRV_TPROXY_CLI;
4329 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004330 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004331 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004332 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4333 char *name, *end;
4334
4335 name = args[cur_arg+1] + 7;
4336 while (isspace(*name))
4337 name++;
4338
4339 end = name;
4340 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4341 end++;
4342
4343 newsrv->state &= ~SRV_TPROXY_MASK;
4344 newsrv->state |= SRV_TPROXY_DYN;
4345 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4346 newsrv->bind_hdr_len = end - name;
4347 memcpy(newsrv->bind_hdr_name, name, end - name);
4348 newsrv->bind_hdr_name[end-name] = '\0';
4349 newsrv->bind_hdr_occ = -1;
4350
4351 /* now look for an occurrence number */
4352 while (isspace(*end))
4353 end++;
4354 if (*end == ',') {
4355 end++;
4356 name = end;
4357 if (*end == '-')
4358 end++;
4359 while (isdigit(*end))
4360 end++;
4361 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4362 }
4363
4364 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4365 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4366 " occurrences values smaller than %d.\n",
4367 file, linenum, MAX_HDR_HISTORY);
4368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004371 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004372 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004373 if (!sk) {
4374 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4375 err_code |= ERR_ALERT | ERR_FATAL;
4376 goto out;
4377 }
4378 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004379 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004380 }
4381 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004382#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004383 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004384#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004385 cur_arg += 2;
4386 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004387#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004388 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004389 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004392#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4393 } /* "usesrc" */
4394
4395 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4396#ifdef SO_BINDTODEVICE
4397 if (!*args[cur_arg + 1]) {
4398 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4399 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004400 err_code |= ERR_ALERT | ERR_FATAL;
4401 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004402 }
4403 if (newsrv->iface_name)
4404 free(newsrv->iface_name);
4405
4406 newsrv->iface_name = strdup(args[cur_arg + 1]);
4407 newsrv->iface_len = strlen(newsrv->iface_name);
4408 global.last_checks |= LSTCHK_NETADM;
4409#else
4410 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4411 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004412 err_code |= ERR_ALERT | ERR_FATAL;
4413 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004414#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004415 cur_arg += 2;
4416 continue;
4417 }
4418 /* this keyword in not an option of "source" */
4419 break;
4420 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004421 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004422 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004423 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4424 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004427 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004428 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004429 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004430 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 +01004431 file, linenum, newsrv->id);
4432 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004433 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 +01004434 file, linenum);
4435
Willy Tarreau93893792009-07-23 13:19:11 +02004436 err_code |= ERR_ALERT | ERR_FATAL;
4437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004438 }
4439 }
4440
4441 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004442 if (newsrv->trackit) {
4443 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4444 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004447 }
4448
David du Colombier6f5ccb12011-03-10 22:26:24 +01004449 switch (newsrv->check_addr.ss_family) {
4450 case AF_INET:
4451 if (!newsrv->check_port && ((struct sockaddr_in *)&newsrv->check_addr)->sin_port)
4452 newsrv->check_port = ntohs(((struct sockaddr_in *)&newsrv->check_addr)->sin_port);
4453 break;
4454 case AF_INET6:
4455 if (!newsrv->check_port && ((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port)
4456 newsrv->check_port = ntohs(((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port);
4457 break;
4458 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004459
Willy Tarreaubaaee002006-06-26 02:48:02 +02004460 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4461 newsrv->check_port = realport; /* by default */
4462 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004463 /* not yet valid, because no port was set on
4464 * the server either. We'll check if we have
4465 * a known port on the first listener.
4466 */
4467 struct listener *l;
4468 l = curproxy->listen;
4469 if (l) {
4470 int port;
4471 port = (l->addr.ss_family == AF_INET6)
4472 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4473 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4474 newsrv->check_port = port;
4475 }
4476 }
4477 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004478 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4479 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004480 err_code |= ERR_ALERT | ERR_FATAL;
4481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004482 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004483
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004484 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004485 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004486 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4487 err_code |= ERR_ALERT | ERR_ABORT;
4488 goto out;
4489 }
4490
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004491 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004492 newsrv->state |= SRV_CHECKED;
4493 }
4494
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004495 if (!defsrv) {
4496 if (newsrv->state & SRV_BACKUP)
4497 curproxy->srv_bck++;
4498 else
4499 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004500
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004501 newsrv->prev_state = newsrv->state;
4502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004503 }
4504 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004505 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 int facility;
4507
4508 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4509 curproxy->logfac1 = global.logfac1;
4510 curproxy->logsrv1 = global.logsrv1;
4511 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004512 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004513 curproxy->logfac2 = global.logfac2;
4514 curproxy->logsrv2 = global.logsrv2;
4515 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004516 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004517 }
4518 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004519 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520
4521 facility = get_log_facility(args[2]);
4522 if (facility < 0) {
4523 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4524 exit(1);
4525 }
4526
4527 level = 7; /* max syslog level = debug */
4528 if (*(args[3])) {
4529 level = get_log_level(args[3]);
4530 if (level < 0) {
4531 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4532 exit(1);
4533 }
4534 }
4535
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004536 minlvl = 0; /* limit syslog level to this level (emerg) */
4537 if (*(args[4])) {
4538 minlvl = get_log_level(args[4]);
4539 if (level < 0) {
4540 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4541 exit(1);
4542 }
4543 }
4544
Robert Tsai81ae1952007-12-05 10:47:29 +01004545 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004546 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004547 if (!sk) {
4548 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004549 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004550 err_code |= ERR_ALERT | ERR_FATAL;
4551 goto out;
4552 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004553 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004554 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004555 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004556 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004557 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4558 err_code |= ERR_ALERT | ERR_FATAL;
4559 goto out;
4560 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004561 logsrv.addr = *sk;
4562 if (!get_host_port(&logsrv.addr))
4563 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004564 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004565
4566 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004567 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004568 curproxy->logfac1 = facility;
4569 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004570 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004571 }
4572 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004573 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004574 curproxy->logfac2 = facility;
4575 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004576 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004577 }
4578 else {
4579 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004580 err_code |= ERR_ALERT | ERR_FATAL;
4581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 }
4583 }
4584 else {
4585 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4586 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004587 err_code |= ERR_ALERT | ERR_FATAL;
4588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004589 }
4590 }
4591 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004592 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004593 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004594
Willy Tarreau977b8e42006-12-29 14:19:17 +01004595 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004596 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004597
Willy Tarreaubaaee002006-06-26 02:48:02 +02004598 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004599 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4600 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004601 err_code |= ERR_ALERT | ERR_FATAL;
4602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004603 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004604
4605 /* we must first clear any optional default setting */
4606 curproxy->options &= ~PR_O_TPXY_MASK;
4607 free(curproxy->iface_name);
4608 curproxy->iface_name = NULL;
4609 curproxy->iface_len = 0;
4610
Willy Tarreaud5191e72010-02-09 20:50:45 +01004611 sk = str2sa(args[1]);
4612 if (!sk) {
4613 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
4616 }
4617 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004618 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004619
4620 cur_arg = 2;
4621 while (*(args[cur_arg])) {
4622 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004623#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4624#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004625 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4626 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4627 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004628 err_code |= ERR_ALERT | ERR_FATAL;
4629 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004630 }
4631#endif
4632 if (!*args[cur_arg + 1]) {
4633 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4634 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004635 err_code |= ERR_ALERT | ERR_FATAL;
4636 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004637 }
4638
4639 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004640 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004641 curproxy->options |= PR_O_TPXY_CLI;
4642 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004643 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004644 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004645 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4646 char *name, *end;
4647
4648 name = args[cur_arg+1] + 7;
4649 while (isspace(*name))
4650 name++;
4651
4652 end = name;
4653 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4654 end++;
4655
4656 curproxy->options &= ~PR_O_TPXY_MASK;
4657 curproxy->options |= PR_O_TPXY_DYN;
4658 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4659 curproxy->bind_hdr_len = end - name;
4660 memcpy(curproxy->bind_hdr_name, name, end - name);
4661 curproxy->bind_hdr_name[end-name] = '\0';
4662 curproxy->bind_hdr_occ = -1;
4663
4664 /* now look for an occurrence number */
4665 while (isspace(*end))
4666 end++;
4667 if (*end == ',') {
4668 end++;
4669 name = end;
4670 if (*end == '-')
4671 end++;
4672 while (isdigit(*end))
4673 end++;
4674 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4675 }
4676
4677 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4678 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4679 " occurrences values smaller than %d.\n",
4680 file, linenum, MAX_HDR_HISTORY);
4681 err_code |= ERR_ALERT | ERR_FATAL;
4682 goto out;
4683 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004684 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004685 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004686 if (!sk) {
4687 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4688 err_code |= ERR_ALERT | ERR_FATAL;
4689 goto out;
4690 }
4691 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004692 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004693 }
4694 global.last_checks |= LSTCHK_NETADM;
4695#if !defined(CONFIG_HAP_LINUX_TPROXY)
4696 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004697#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004698#else /* no TPROXY support */
4699 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004700 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004701 err_code |= ERR_ALERT | ERR_FATAL;
4702 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004703#endif
4704 cur_arg += 2;
4705 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004706 }
4707
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004708 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4709#ifdef SO_BINDTODEVICE
4710 if (!*args[cur_arg + 1]) {
4711 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4712 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004713 err_code |= ERR_ALERT | ERR_FATAL;
4714 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004715 }
4716 if (curproxy->iface_name)
4717 free(curproxy->iface_name);
4718
4719 curproxy->iface_name = strdup(args[cur_arg + 1]);
4720 curproxy->iface_len = strlen(curproxy->iface_name);
4721 global.last_checks |= LSTCHK_NETADM;
4722#else
4723 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4724 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004725 err_code |= ERR_ALERT | ERR_FATAL;
4726 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004727#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004728 cur_arg += 2;
4729 continue;
4730 }
4731 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4732 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004733 err_code |= ERR_ALERT | ERR_FATAL;
4734 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004736 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004737 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4738 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4739 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004742 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004744 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004745 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4746 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004747 err_code |= ERR_ALERT | ERR_FATAL;
4748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004750
4751 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4752 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004753 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004754 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004756 }
4757 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004758 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4759 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004760 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004761 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 }
4764 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004765 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4766 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004767 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004768 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004770 }
4771 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004772 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4773 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004774 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004775 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 }
4778 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004779 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4780 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004781 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004782 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004784 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004785 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004786 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4787 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004788 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004789 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004790 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004791 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004792 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004793 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4794 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004795 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004796 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004797 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004798 }
4799 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004800 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4801 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004802 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004803 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004804 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004805 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004806 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004807 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004808 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4809 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004810 err_code |= ERR_ALERT | ERR_FATAL;
4811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004812 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004813
4814 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4815 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004816 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004817 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004819 }
4820 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004821 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4822 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004823 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004824 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004826 }
4827 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004828 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4829 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004830 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004831 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004833 }
4834 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004835 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4836 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004837 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004838 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840 }
4841 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004842 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4843 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004844 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004845 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004847 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004848 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004849 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4850 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004851 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004852 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004853 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004856 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004857
Willy Tarreaubaaee002006-06-26 02:48:02 +02004858 if (curproxy == &defproxy) {
4859 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004863 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004864 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004865
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 if (*(args[1]) == 0) {
4867 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004870 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004871
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004872 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4873 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4874 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4875 file, linenum, args[0]);
4876 err_code |= ERR_ALERT | ERR_FATAL;
4877 goto out;
4878 }
4879 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4880 }
4881 else if (*args[2]) {
4882 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4883 file, linenum, args[0], args[2]);
4884 err_code |= ERR_ALERT | ERR_FATAL;
4885 goto out;
4886 }
4887
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004888 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004889 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004890 wl->s = strdup(args[1]);
4891 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004892 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004893 }
4894 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004895 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004896 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4897 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004898 err_code |= ERR_ALERT | ERR_FATAL;
4899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004901
Willy Tarreauade5ec42010-01-28 19:33:49 +01004902 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4903 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004904 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004905 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004907 }
4908 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004909 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4910 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004911 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004912 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004914 }
4915 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004916 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4917 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004918 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004919 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004921 }
4922 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004923 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004924 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4925 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004926 err_code |= ERR_ALERT | ERR_FATAL;
4927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004928 }
4929
Willy Tarreauade5ec42010-01-28 19:33:49 +01004930 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4931 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004932 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004933 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004935 }
4936 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004937 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4938 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004939 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004940 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004942 }
4943 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004944 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4945 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004946 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004947 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 }
4950 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004951 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004952
Willy Tarreaubaaee002006-06-26 02:48:02 +02004953 if (curproxy == &defproxy) {
4954 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004955 err_code |= ERR_ALERT | ERR_FATAL;
4956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004957 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004958 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004959 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004960
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 if (*(args[1]) == 0) {
4962 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004963 err_code |= ERR_ALERT | ERR_FATAL;
4964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
4966
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004967 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4968 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4969 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4970 file, linenum, args[0]);
4971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
4973 }
4974 err_code |= warnif_cond_requires_req(cond, file, linenum);
4975 }
4976 else if (*args[2]) {
4977 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4978 file, linenum, args[0], args[2]);
4979 err_code |= ERR_ALERT | ERR_FATAL;
4980 goto out;
4981 }
4982
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004983 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004984 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004985 wl->s = strdup(args[1]);
4986 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004987 }
4988 else if (!strcmp(args[0], "errorloc") ||
4989 !strcmp(args[0], "errorloc302") ||
4990 !strcmp(args[0], "errorloc303")) { /* error location */
4991 int errnum, errlen;
4992 char *err;
4993
Willy Tarreau977b8e42006-12-29 14:19:17 +01004994 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004995 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004996
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004998 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004999 err_code |= ERR_ALERT | ERR_FATAL;
5000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005001 }
5002
5003 errnum = atol(args[1]);
5004 if (!strcmp(args[0], "errorloc303")) {
5005 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5006 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5007 } else {
5008 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5009 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5010 }
5011
Willy Tarreau0f772532006-12-23 20:51:41 +01005012 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5013 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005014 chunk_destroy(&curproxy->errmsg[rc]);
5015 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005016 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005017 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005019
5020 if (rc >= HTTP_ERR_SIZE) {
5021 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5022 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023 free(err);
5024 }
5025 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005026 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5027 int errnum, errlen, fd;
5028 char *err;
5029 struct stat stat;
5030
5031 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005032 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005033
5034 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005035 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005036 err_code |= ERR_ALERT | ERR_FATAL;
5037 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005038 }
5039
5040 fd = open(args[2], O_RDONLY);
5041 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5042 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5043 file, linenum, args[2], args[1]);
5044 if (fd >= 0)
5045 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005046 err_code |= ERR_ALERT | ERR_FATAL;
5047 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005048 }
5049
Willy Tarreau27a674e2009-08-17 07:23:33 +02005050 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005051 errlen = stat.st_size;
5052 } else {
5053 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005054 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005055 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005056 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005057 }
5058
5059 err = malloc(errlen); /* malloc() must succeed during parsing */
5060 errnum = read(fd, err, errlen);
5061 if (errnum != errlen) {
5062 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5063 file, linenum, args[2], args[1]);
5064 close(fd);
5065 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005066 err_code |= ERR_ALERT | ERR_FATAL;
5067 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005068 }
5069 close(fd);
5070
5071 errnum = atol(args[1]);
5072 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5073 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005074 chunk_destroy(&curproxy->errmsg[rc]);
5075 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005076 break;
5077 }
5078 }
5079
5080 if (rc >= HTTP_ERR_SIZE) {
5081 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5082 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005083 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005084 free(err);
5085 }
5086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005087 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005088 struct cfg_kw_list *kwl;
5089 int index;
5090
5091 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5092 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5093 if (kwl->kw[index].section != CFG_LISTEN)
5094 continue;
5095 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5096 /* prepare error message just in case */
5097 snprintf(trash, sizeof(trash),
5098 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005099 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5100 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005101 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005102 err_code |= ERR_ALERT | ERR_FATAL;
5103 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005104 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005105 else if (rc > 0) {
5106 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005107 err_code |= ERR_WARN;
5108 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005109 }
Willy Tarreau93893792009-07-23 13:19:11 +02005110 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005111 }
5112 }
5113 }
5114
Willy Tarreau6daf3432008-01-22 16:44:08 +01005115 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005116 err_code |= ERR_ALERT | ERR_FATAL;
5117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 }
Willy Tarreau93893792009-07-23 13:19:11 +02005119 out:
5120 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121}
5122
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005123int
5124cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5125{
5126
5127 int err_code = 0;
5128 const char *err;
5129
5130 if (!strcmp(args[0], "userlist")) { /* new userlist */
5131 struct userlist *newul;
5132
5133 if (!*args[1]) {
5134 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5135 file, linenum, args[0]);
5136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
5138 }
5139
5140 err = invalid_char(args[1]);
5141 if (err) {
5142 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5143 file, linenum, *err, args[0], args[1]);
5144 err_code |= ERR_ALERT | ERR_FATAL;
5145 goto out;
5146 }
5147
5148 for (newul = userlist; newul; newul = newul->next)
5149 if (!strcmp(newul->name, args[1])) {
5150 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5151 file, linenum, args[1]);
5152 err_code |= ERR_WARN;
5153 goto out;
5154 }
5155
5156 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5157 if (!newul) {
5158 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5159 err_code |= ERR_ALERT | ERR_ABORT;
5160 goto out;
5161 }
5162
5163 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5164 newul->name = strdup(args[1]);
5165
5166 if (!newul->groupusers | !newul->name) {
5167 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5168 err_code |= ERR_ALERT | ERR_ABORT;
5169 goto out;
5170 }
5171
5172 newul->next = userlist;
5173 userlist = newul;
5174
5175 } else if (!strcmp(args[0], "group")) { /* new group */
5176 int cur_arg, i;
5177 const char *err;
5178
5179 if (!*args[1]) {
5180 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5181 file, linenum, args[0]);
5182 err_code |= ERR_ALERT | ERR_FATAL;
5183 goto out;
5184 }
5185
5186 err = invalid_char(args[1]);
5187 if (err) {
5188 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5189 file, linenum, *err, args[0], args[1]);
5190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
5192 }
5193
5194 for(i = 0; i < userlist->grpcnt; i++)
5195 if (!strcmp(userlist->groups[i], args[1])) {
5196 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5197 file, linenum, args[1], userlist->name);
5198 err_code |= ERR_ALERT;
5199 goto out;
5200 }
5201
5202 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5203 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5204 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5205 err_code |= ERR_ALERT | ERR_FATAL;
5206 goto out;
5207 }
5208
5209 cur_arg = 2;
5210
5211 while (*args[cur_arg]) {
5212 if (!strcmp(args[cur_arg], "users")) {
5213 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5214 cur_arg += 2;
5215 continue;
5216 } else {
5217 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5218 file, linenum, args[0]);
5219 err_code |= ERR_ALERT | ERR_FATAL;
5220 goto out;
5221 }
5222 }
5223
5224 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5225 } else if (!strcmp(args[0], "user")) { /* new user */
5226 struct auth_users *newuser;
5227 int cur_arg;
5228
5229 if (!*args[1]) {
5230 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5231 file, linenum, args[0]);
5232 err_code |= ERR_ALERT | ERR_FATAL;
5233 goto out;
5234 }
5235
5236 for (newuser = userlist->users; newuser; newuser = newuser->next)
5237 if (!strcmp(newuser->user, args[1])) {
5238 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5239 file, linenum, args[1], userlist->name);
5240 err_code |= ERR_ALERT;
5241 goto out;
5242 }
5243
5244 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5245 if (!newuser) {
5246 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5247 err_code |= ERR_ALERT | ERR_ABORT;
5248 goto out;
5249 }
5250
5251 newuser->user = strdup(args[1]);
5252
5253 newuser->next = userlist->users;
5254 userlist->users = newuser;
5255
5256 cur_arg = 2;
5257
5258 while (*args[cur_arg]) {
5259 if (!strcmp(args[cur_arg], "password")) {
5260#ifndef CONFIG_HAP_CRYPT
5261 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5262 file, linenum);
5263 err_code |= ERR_ALERT;
5264#endif
5265 newuser->pass = strdup(args[cur_arg + 1]);
5266 cur_arg += 2;
5267 continue;
5268 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5269 newuser->pass = strdup(args[cur_arg + 1]);
5270 newuser->flags |= AU_O_INSECURE;
5271 cur_arg += 2;
5272 continue;
5273 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005274 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005275 cur_arg += 2;
5276 continue;
5277 } else {
5278 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5279 file, linenum, args[0]);
5280 err_code |= ERR_ALERT | ERR_FATAL;
5281 goto out;
5282 }
5283 }
5284 } else {
5285 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5286 err_code |= ERR_ALERT | ERR_FATAL;
5287 }
5288
5289out:
5290 return err_code;
5291}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292
5293/*
5294 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005295 * Returns the error code, 0 if OK, or any combination of :
5296 * - ERR_ABORT: must abort ASAP
5297 * - ERR_FATAL: we can continue parsing but not start the service
5298 * - ERR_WARN: a warning has been emitted
5299 * - ERR_ALERT: an alert has been emitted
5300 * Only the two first ones can stop processing, the two others are just
5301 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005302 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005303int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005305 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306 FILE *f;
5307 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005309 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310
Willy Tarreaubaaee002006-06-26 02:48:02 +02005311 if ((f=fopen(file,"r")) == NULL)
5312 return -1;
5313
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005314 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005315 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005316 char *end;
5317 char *args[MAX_LINE_ARGS + 1];
5318 char *line = thisline;
5319
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320 linenum++;
5321
5322 end = line + strlen(line);
5323
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005324 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5325 /* Check if we reached the limit and the last char is not \n.
5326 * Watch out for the last line without the terminating '\n'!
5327 */
5328 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005329 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005330 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005331 }
5332
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005334 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335 line++;
5336
5337 arg = 0;
5338 args[arg] = line;
5339
5340 while (*line && arg < MAX_LINE_ARGS) {
5341 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5342 * C equivalent value. Other combinations left unchanged (eg: \1).
5343 */
5344 if (*line == '\\') {
5345 int skip = 0;
5346 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5347 *line = line[1];
5348 skip = 1;
5349 }
5350 else if (line[1] == 'r') {
5351 *line = '\r';
5352 skip = 1;
5353 }
5354 else if (line[1] == 'n') {
5355 *line = '\n';
5356 skip = 1;
5357 }
5358 else if (line[1] == 't') {
5359 *line = '\t';
5360 skip = 1;
5361 }
5362 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005363 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 unsigned char hex1, hex2;
5365 hex1 = toupper(line[2]) - '0';
5366 hex2 = toupper(line[3]) - '0';
5367 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5368 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5369 *line = (hex1<<4) + hex2;
5370 skip = 3;
5371 }
5372 else {
5373 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005374 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005375 }
5376 }
5377 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005378 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005379 end -= skip;
5380 }
5381 line++;
5382 }
5383 else if (*line == '#' || *line == '\n' || *line == '\r') {
5384 /* end of string, end of loop */
5385 *line = 0;
5386 break;
5387 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005388 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005390 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005391 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005392 line++;
5393 args[++arg] = line;
5394 }
5395 else {
5396 line++;
5397 }
5398 }
5399
5400 /* empty line */
5401 if (!**args)
5402 continue;
5403
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005404 if (*line) {
5405 /* we had to stop due to too many args.
5406 * Let's terminate the string, print the offending part then cut the
5407 * last arg.
5408 */
5409 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5410 line++;
5411 *line = '\0';
5412
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005413 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005414 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005415 err_code |= ERR_ALERT | ERR_FATAL;
5416 args[arg] = line;
5417 }
5418
Willy Tarreau540abe42007-05-02 20:50:16 +02005419 /* zero out remaining args and ensure that at least one entry
5420 * is zeroed out.
5421 */
5422 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005423 args[arg] = line;
5424 }
5425
Willy Tarreau3842f002009-06-14 11:39:52 +02005426 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005427 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005428 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005429 for (arg=0; *args[arg+1]; arg++)
5430 args[arg] = args[arg+1]; // shift args after inversion
5431 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005432 else if (!strcmp(args[0], "default")) {
5433 kwm = KWM_DEF;
5434 for (arg=0; *args[arg+1]; arg++)
5435 args[arg] = args[arg+1]; // shift args after inversion
5436 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005437
Willy Tarreau3842f002009-06-14 11:39:52 +02005438 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5439 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005440 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005441 }
5442
Willy Tarreau977b8e42006-12-29 14:19:17 +01005443 if (!strcmp(args[0], "listen") ||
5444 !strcmp(args[0], "frontend") ||
5445 !strcmp(args[0], "backend") ||
5446 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005447 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005448 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005449 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005450 cursection = strdup(args[0]);
5451 }
5452 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005454 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005455 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005456 }
5457 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005458 confsect = CFG_USERLIST;
5459 free(cursection);
5460 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005461 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005462 else if (!strcmp(args[0], "peers")) {
5463 confsect = CFG_PEERS;
5464 free(cursection);
5465 cursection = strdup(args[0]);
5466 }
5467
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 /* else it's a section keyword */
5469
5470 switch (confsect) {
5471 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005472 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005473 break;
5474 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005475 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005476 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005477 case CFG_USERLIST:
5478 err_code |= cfg_parse_users(file, linenum, args, kwm);
5479 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005480 case CFG_PEERS:
5481 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5482 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005483 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005484 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005485 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005486 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005487
5488 if (err_code & ERR_ABORT)
5489 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005490 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005491 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005492 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005493 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005494 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005495}
5496
Willy Tarreaubb925012009-07-23 13:36:36 +02005497/*
5498 * Returns the error code, 0 if OK, or any combination of :
5499 * - ERR_ABORT: must abort ASAP
5500 * - ERR_FATAL: we can continue parsing but not start the service
5501 * - ERR_WARN: a warning has been emitted
5502 * - ERR_ALERT: an alert has been emitted
5503 * Only the two first ones can stop processing, the two others are just
5504 * indicators.
5505 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005506int check_config_validity()
5507{
5508 int cfgerr = 0;
5509 struct proxy *curproxy = NULL;
5510 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005511 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005512 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005513 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514
5515 /*
5516 * Now, check for the integrity of all that we have collected.
5517 */
5518
5519 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005520 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005521
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005522 /* first, we will invert the proxy list order */
5523 curproxy = NULL;
5524 while (proxy) {
5525 struct proxy *next;
5526
5527 next = proxy->next;
5528 proxy->next = curproxy;
5529 curproxy = proxy;
5530 if (!next)
5531 break;
5532 proxy = next;
5533 }
5534
Willy Tarreaubaaee002006-06-26 02:48:02 +02005535 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005536 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005537 err_code |= ERR_ALERT | ERR_FATAL;
5538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005539 }
5540
5541 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005542 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005543 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005544 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005545 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005546 unsigned int next_id;
5547
5548 if (!curproxy->uuid) {
5549 /* proxy ID not set, use automatic numbering with first
5550 * spare entry starting with next_pxid.
5551 */
5552 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5553 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5554 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005555 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005556 next_pxid++;
5557
Willy Tarreau55ea7572007-06-17 19:56:27 +02005558
Willy Tarreaubaaee002006-06-26 02:48:02 +02005559 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005560 /* ensure we don't keep listeners uselessly bound */
5561 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005562 curproxy = curproxy->next;
5563 continue;
5564 }
5565
Willy Tarreauff01a212009-03-15 13:46:16 +01005566 switch (curproxy->mode) {
5567 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005568 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005569 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005570 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5571 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005572 cfgerr++;
5573 }
5574
5575 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005576 Warning("config : servers will be ignored for %s '%s'.\n",
5577 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005578 break;
5579
5580 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005581 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005582 break;
5583
5584 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005585 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005586 break;
5587 }
5588
5589 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005590 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5591 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005592 cfgerr++;
5593 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005594
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005595 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005596 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005597 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005598 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5599 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005600 cfgerr++;
5601 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005602#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005603 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005604 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5605 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005606 cfgerr++;
5607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005608#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005609 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005610 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5611 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005612 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005613 }
5614 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005615 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005616 /* If no LB algo is set in a backend, and we're not in
5617 * transparent mode, dispatch mode nor proxy mode, we
5618 * want to use balance roundrobin by default.
5619 */
5620 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5621 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005622 }
5623 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005624
Willy Tarreau1620ec32011-08-06 17:05:02 +02005625 if (curproxy->options & PR_O_DISPATCH)
5626 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5627 else if (curproxy->options & PR_O_HTTP_PROXY)
5628 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5629 else if (curproxy->options & PR_O_TRANSP)
5630 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005631
Willy Tarreau1620ec32011-08-06 17:05:02 +02005632 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5633 if (curproxy->options & PR_O_DISABLE404) {
5634 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5635 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5636 err_code |= ERR_WARN;
5637 curproxy->options &= ~PR_O_DISABLE404;
5638 }
5639 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5640 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5641 "send-state", proxy_type_str(curproxy), curproxy->id);
5642 err_code |= ERR_WARN;
5643 curproxy->options &= ~PR_O2_CHK_SNDST;
5644 }
Willy Tarreauef781042010-01-27 11:53:01 +01005645 }
5646
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005647 /* if a default backend was specified, let's find it */
5648 if (curproxy->defbe.name) {
5649 struct proxy *target;
5650
Alex Williams96532db2009-11-01 21:27:13 -05005651 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005652 if (!target) {
5653 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5654 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005655 cfgerr++;
5656 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005657 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5658 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005659 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005660 } else {
5661 free(curproxy->defbe.name);
5662 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005663 /* we force the backend to be present on at least all of
5664 * the frontend's processes.
5665 */
5666 target->bind_proc = curproxy->bind_proc ?
5667 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005668 }
5669 }
5670
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005671 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005672 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5673 /* map jump target for ACT_SETBE in req_rep chain */
5674 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005675 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005676 struct proxy *target;
5677
Willy Tarreaua496b602006-12-17 23:15:24 +01005678 if (exp->action != ACT_SETBE)
5679 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005680
Alex Williams96532db2009-11-01 21:27:13 -05005681 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005682 if (!target) {
5683 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5684 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005685 cfgerr++;
5686 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005687 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5688 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005689 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005690 } else {
5691 free((void *)exp->replace);
5692 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005693 /* we force the backend to be present on at least all of
5694 * the frontend's processes.
5695 */
5696 target->bind_proc = curproxy->bind_proc ?
5697 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005698 }
5699 }
5700 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005701
5702 /* find the target proxy for 'use_backend' rules */
5703 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005704 struct proxy *target;
5705
Alex Williams96532db2009-11-01 21:27:13 -05005706 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005707
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005708 if (!target) {
5709 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5710 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005711 cfgerr++;
5712 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005713 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5714 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005715 cfgerr++;
5716 } else {
5717 free((void *)rule->be.name);
5718 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005719 /* we force the backend to be present on at least all of
5720 * the frontend's processes.
5721 */
5722 target->bind_proc = curproxy->bind_proc ?
5723 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005724 }
5725 }
5726
Emeric Brunb982a3d2010-01-04 15:45:53 +01005727 /* find the target table for 'stick' rules */
5728 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5729 struct proxy *target;
5730
Emeric Brun1d33b292010-01-04 15:47:17 +01005731 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5732 if (mrule->flags & STK_IS_STORE)
5733 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5734
Emeric Brunb982a3d2010-01-04 15:45:53 +01005735 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005736 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005737 else
5738 target = curproxy;
5739
5740 if (!target) {
5741 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5742 curproxy->id, mrule->table.name);
5743 cfgerr++;
5744 }
5745 else if (target->table.size == 0) {
5746 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5747 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5748 cfgerr++;
5749 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005750 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005751 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5752 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5753 cfgerr++;
5754 }
5755 else {
5756 free((void *)mrule->table.name);
5757 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005758 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005759 }
5760 }
5761
5762 /* find the target table for 'store response' rules */
5763 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5764 struct proxy *target;
5765
Emeric Brun1d33b292010-01-04 15:47:17 +01005766 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5767
Emeric Brunb982a3d2010-01-04 15:45:53 +01005768 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005769 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005770 else
5771 target = curproxy;
5772
5773 if (!target) {
5774 Alert("Proxy '%s': unable to find store table '%s'.\n",
5775 curproxy->id, mrule->table.name);
5776 cfgerr++;
5777 }
5778 else if (target->table.size == 0) {
5779 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5780 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5781 cfgerr++;
5782 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005783 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005784 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5785 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5786 cfgerr++;
5787 }
5788 else {
5789 free((void *)mrule->table.name);
5790 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005791 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005792 }
5793 }
5794
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005795 /* find the target table for 'tcp-request' layer 4 rules */
5796 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5797 struct proxy *target;
5798
Willy Tarreau56123282010-08-06 19:06:56 +02005799 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005800 continue;
5801
5802 if (trule->act_prm.trk_ctr.table.n)
5803 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5804 else
5805 target = curproxy;
5806
5807 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005808 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5809 curproxy->id, trule->act_prm.trk_ctr.table.n,
5810 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005811 cfgerr++;
5812 }
5813 else if (target->table.size == 0) {
5814 Alert("Proxy '%s': table '%s' used but not configured.\n",
5815 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5816 cfgerr++;
5817 }
5818 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005819 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 +02005820 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5821 cfgerr++;
5822 }
5823 else {
5824 free(trule->act_prm.trk_ctr.table.n);
5825 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005826 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005827 * to pass a list of counters to track and allocate them right here using
5828 * stktable_alloc_data_type().
5829 */
5830 }
5831 }
5832
Willy Tarreaud1f96522010-08-03 19:34:32 +02005833 /* find the target table for 'tcp-request' layer 6 rules */
5834 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5835 struct proxy *target;
5836
Willy Tarreau56123282010-08-06 19:06:56 +02005837 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005838 continue;
5839
5840 if (trule->act_prm.trk_ctr.table.n)
5841 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5842 else
5843 target = curproxy;
5844
5845 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005846 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5847 curproxy->id, trule->act_prm.trk_ctr.table.n,
5848 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005849 cfgerr++;
5850 }
5851 else if (target->table.size == 0) {
5852 Alert("Proxy '%s': table '%s' used but not configured.\n",
5853 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5854 cfgerr++;
5855 }
5856 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005857 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 +02005858 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5859 cfgerr++;
5860 }
5861 else {
5862 free(trule->act_prm.trk_ctr.table.n);
5863 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005864 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005865 * to pass a list of counters to track and allocate them right here using
5866 * stktable_alloc_data_type().
5867 */
5868 }
5869 }
5870
Emeric Brun32da3c42010-09-23 18:39:19 +02005871 if (curproxy->table.peers.name) {
5872 struct peers *curpeers = peers;
5873
5874 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5875 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5876 free((void *)curproxy->table.peers.name);
5877 curproxy->table.peers.p = peers;
5878 break;
5879 }
5880 }
5881
5882 if (!curpeers) {
5883 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5884 curproxy->id, curproxy->table.peers.name);
5885 cfgerr++;
5886 }
5887 else if (!curpeers->peers_fe) {
5888 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5889 curproxy->id, curpeers->id);
5890 cfgerr++;
5891 }
5892 }
5893
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005894 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005895 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005896 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5897 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5898 "proxy", curproxy->id);
5899 cfgerr++;
5900 goto out_uri_auth_compat;
5901 }
5902
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005903 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005904 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005905 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005906 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005907
Willy Tarreau95fa4692010-02-01 13:05:50 +01005908 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5909 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005910
5911 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005912 uri_auth_compat_req[i++] = "realm";
5913 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5914 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005915
Willy Tarreau95fa4692010-02-01 13:05:50 +01005916 uri_auth_compat_req[i++] = "unless";
5917 uri_auth_compat_req[i++] = "{";
5918 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5919 uri_auth_compat_req[i++] = "}";
5920 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005921
Willy Tarreauff011f22011-01-06 17:51:27 +01005922 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5923 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005924 cfgerr++;
5925 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005926 }
5927
Willy Tarreauff011f22011-01-06 17:51:27 +01005928 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005929
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005930 if (curproxy->uri_auth->auth_realm) {
5931 free(curproxy->uri_auth->auth_realm);
5932 curproxy->uri_auth->auth_realm = NULL;
5933 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005934
5935 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005936 }
5937out_uri_auth_compat:
5938
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005939 cfgerr += acl_find_targets(curproxy);
5940
Willy Tarreau2738a142006-07-08 17:28:09 +02005941 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005942 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005943 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005944 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005945 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005946 " | While not properly invalid, you will certainly encounter various problems\n"
5947 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005948 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005949 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005950 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005951 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005952
Willy Tarreau1fa31262007-12-03 00:36:16 +01005953 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5954 * We must still support older configurations, so let's find out whether those
5955 * parameters have been set or must be copied from contimeouts.
5956 */
5957 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005958 if (!curproxy->timeout.tarpit ||
5959 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005960 /* tarpit timeout not set. We search in the following order:
5961 * default.tarpit, curr.connect, default.connect.
5962 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005963 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005964 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005965 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005966 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005967 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005968 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005969 }
5970 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005971 (!curproxy->timeout.queue ||
5972 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005973 /* queue timeout not set. We search in the following order:
5974 * default.queue, curr.connect, default.connect.
5975 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005976 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005977 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005978 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005979 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005980 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005981 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005982 }
5983 }
5984
Willy Tarreau1620ec32011-08-06 17:05:02 +02005985 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005986 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5987 curproxy->check_req = (char *)malloc(curproxy->check_len);
5988 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005989 }
5990
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005991 /* The small pools required for the capture lists */
5992 if (curproxy->nb_req_cap)
5993 curproxy->req_cap_pool = create_pool("ptrcap",
5994 curproxy->nb_req_cap * sizeof(char *),
5995 MEM_F_SHARED);
5996 if (curproxy->nb_rsp_cap)
5997 curproxy->rsp_cap_pool = create_pool("ptrcap",
5998 curproxy->nb_rsp_cap * sizeof(char *),
5999 MEM_F_SHARED);
6000
Willy Tarreau1d4154a2007-05-13 22:57:02 +02006001 curproxy->hdr_idx_pool = create_pool("hdr_idx",
6002 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6003 MEM_F_SHARED);
6004
Willy Tarreaubaaee002006-06-26 02:48:02 +02006005 /* first, we will invert the servers list order */
6006 newsrv = NULL;
6007 while (curproxy->srv) {
6008 struct server *next;
6009
6010 next = curproxy->srv->next;
6011 curproxy->srv->next = newsrv;
6012 newsrv = curproxy->srv;
6013 if (!next)
6014 break;
6015 curproxy->srv = next;
6016 }
6017
Willy Tarreaudd701652010-05-25 23:03:02 +02006018 /* assign automatic UIDs to servers which don't have one yet */
6019 next_id = 1;
6020 newsrv = curproxy->srv;
6021 while (newsrv != NULL) {
6022 if (!newsrv->puid) {
6023 /* server ID not set, use automatic numbering with first
6024 * spare entry starting with next_svid.
6025 */
6026 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6027 newsrv->conf.id.key = newsrv->puid = next_id;
6028 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6029 }
6030 next_id++;
6031 newsrv = newsrv->next;
6032 }
6033
Willy Tarreau20697042007-11-15 23:26:18 +01006034 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006035 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006036
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006037 /* We have to initialize the server lookup mechanism depending
6038 * on what LB algorithm was choosen.
6039 */
6040
6041 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6042 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6043 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006044 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6045 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6046 init_server_map(curproxy);
6047 } else {
6048 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6049 fwrr_init_server_groups(curproxy);
6050 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006051 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006052
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006053 case BE_LB_KIND_LC:
6054 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006055 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006056 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006057
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006058 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006059 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6060 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6061 chash_init_server_tree(curproxy);
6062 } else {
6063 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6064 init_server_map(curproxy);
6065 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006066 break;
6067 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006068
6069 if (curproxy->options & PR_O_LOGASAP)
6070 curproxy->to_log &= ~LW_BYTES;
6071
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006072 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6073 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6074 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6075 proxy_type_str(curproxy), curproxy->id);
6076 err_code |= ERR_WARN;
6077 }
6078
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006079 if (curproxy->mode != PR_MODE_HTTP) {
6080 int optnum;
6081
6082 if (curproxy->options & PR_O_COOK_ANY) {
6083 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6084 proxy_type_str(curproxy), curproxy->id);
6085 err_code |= ERR_WARN;
6086 }
6087
6088 if (curproxy->uri_auth) {
6089 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6090 proxy_type_str(curproxy), curproxy->id);
6091 err_code |= ERR_WARN;
6092 curproxy->uri_auth = NULL;
6093 }
6094
Willy Tarreau87cf5142011-08-19 22:57:24 +02006095 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006096 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6097 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6098 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006099 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006100 }
6101
6102 if (curproxy->options & PR_O_ORGTO) {
6103 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6104 "originalto", proxy_type_str(curproxy), curproxy->id);
6105 err_code |= ERR_WARN;
6106 curproxy->options &= ~PR_O_ORGTO;
6107 }
6108
6109 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6110 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6111 (curproxy->cap & cfg_opts[optnum].cap) &&
6112 (curproxy->options & cfg_opts[optnum].val)) {
6113 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6114 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6115 err_code |= ERR_WARN;
6116 curproxy->options &= ~cfg_opts[optnum].val;
6117 }
6118 }
6119
6120 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6121 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6122 (curproxy->cap & cfg_opts2[optnum].cap) &&
6123 (curproxy->options2 & cfg_opts2[optnum].val)) {
6124 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6125 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6126 err_code |= ERR_WARN;
6127 curproxy->options2 &= ~cfg_opts2[optnum].val;
6128 }
6129 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006130
Willy Tarreauefa5f512010-03-30 20:13:29 +02006131#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006132 if (curproxy->bind_hdr_occ) {
6133 curproxy->bind_hdr_occ = 0;
6134 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6135 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6136 err_code |= ERR_WARN;
6137 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006138#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006139 }
6140
Willy Tarreaubaaee002006-06-26 02:48:02 +02006141 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006142 * ensure that we're not cross-dressing a TCP server into HTTP.
6143 */
6144 newsrv = curproxy->srv;
6145 while (newsrv != NULL) {
6146 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006147 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6148 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006149 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006150 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006151
Willy Tarreauefa5f512010-03-30 20:13:29 +02006152#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006153 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6154 newsrv->bind_hdr_occ = 0;
6155 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6156 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6157 err_code |= ERR_WARN;
6158 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006159#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006160 newsrv = newsrv->next;
6161 }
6162
6163 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006164 * If this server supports a maxconn parameter, it needs a dedicated
6165 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006166 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006167 */
6168 newsrv = curproxy->srv;
6169 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006170 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006171 /* Only 'minconn' was specified, or it was higher than or equal
6172 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6173 * this will avoid further useless expensive computations.
6174 */
6175 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006176 } else if (newsrv->maxconn && !newsrv->minconn) {
6177 /* minconn was not specified, so we set it to maxconn */
6178 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006179 }
6180
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006181 if (newsrv->trackit) {
6182 struct proxy *px;
6183 struct server *srv;
6184 char *pname, *sname;
6185
6186 pname = newsrv->trackit;
6187 sname = strrchr(pname, '/');
6188
6189 if (sname)
6190 *sname++ = '\0';
6191 else {
6192 sname = pname;
6193 pname = NULL;
6194 }
6195
6196 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006197 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006198 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006199 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6200 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006201 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006202 cfgerr++;
6203 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006204 }
6205 } else
6206 px = curproxy;
6207
6208 srv = findserver(px, sname);
6209 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006210 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6211 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006212 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006213 cfgerr++;
6214 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006215 }
6216
6217 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006218 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006219 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006220 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006221 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006222 cfgerr++;
6223 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006224 }
6225
6226 if (curproxy != px &&
6227 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006228 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006229 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006230 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006231 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006232 cfgerr++;
6233 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006234 }
6235
6236 newsrv->tracked = srv;
6237 newsrv->tracknext = srv->tracknext;
6238 srv->tracknext = newsrv;
6239
6240 free(newsrv->trackit);
6241 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006242 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006243 newsrv = newsrv->next;
6244 }
6245
Willy Tarreauc1a21672009-08-16 22:37:44 +02006246 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006247 curproxy->accept = frontend_accept;
6248
Willy Tarreauc1a21672009-08-16 22:37:44 +02006249 if (curproxy->tcp_req.inspect_delay ||
6250 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006251 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006252
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006253 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006254 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006255 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006256 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006257
6258 /* both TCP and HTTP must check switching rules */
6259 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6260 }
6261
6262 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006263 if (curproxy->tcp_req.inspect_delay ||
6264 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6265 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6266
Emeric Brun97679e72010-09-23 17:56:44 +02006267 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6268 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6269
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006270 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006271 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006272 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006273 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006274
6275 /* If the backend does requires RDP cookie persistence, we have to
6276 * enable the corresponding analyser.
6277 */
6278 if (curproxy->options2 & PR_O2_RDPC_PRST)
6279 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6280 }
6281
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006282 listener = NULL;
6283 while (curproxy->listen) {
6284 struct listener *next;
6285
6286 next = curproxy->listen->next;
6287 curproxy->listen->next = listener;
6288 listener = curproxy->listen;
6289
6290 if (!next)
6291 break;
6292
6293 curproxy->listen = next;
6294 }
6295
Willy Tarreaue6b98942007-10-29 01:09:36 +01006296 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006297 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006298 listener = curproxy->listen;
6299 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006300 if (!listener->luid) {
6301 /* listener ID not set, use automatic numbering with first
6302 * spare entry starting with next_luid.
6303 */
6304 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6305 listener->conf.id.key = listener->luid = next_id;
6306 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006307 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006308 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006309
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006310 /* enable separate counters */
6311 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6312 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6313 if (!listener->name) {
6314 sprintf(trash, "sock-%d", listener->luid);
6315 listener->name = strdup(trash);
6316 }
6317 }
6318
Willy Tarreaue6b98942007-10-29 01:09:36 +01006319 if (curproxy->options & PR_O_TCP_NOLING)
6320 listener->options |= LI_O_NOLINGER;
6321 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006322 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006323 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006324 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006325 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006326 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006327 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006328
Willy Tarreau8a956912010-10-15 14:27:08 +02006329 if (listener->options & LI_O_ACC_PROXY)
6330 listener->analysers |= AN_REQ_DECODE_PROXY;
6331
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006332 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6333 listener->options |= LI_O_TCP_RULES;
6334
Willy Tarreaude3041d2010-05-31 10:56:17 +02006335 if (curproxy->mon_mask.s_addr)
6336 listener->options |= LI_O_CHK_MONNET;
6337
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006338 /* smart accept mode is automatic in HTTP mode */
6339 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6340 (curproxy->mode == PR_MODE_HTTP &&
6341 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6342 listener->options |= LI_O_NOQUICKACK;
6343
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006344 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006345 listener = listener->next;
6346 }
6347
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006348 /* Check multi-process mode compatibility for the current proxy */
6349 if (global.nbproc > 1) {
6350 int nbproc = 0;
6351 if (curproxy->bind_proc) {
6352 int proc;
6353 for (proc = 0; proc < global.nbproc; proc++) {
6354 if (curproxy->bind_proc & (1 << proc)) {
6355 nbproc++;
6356 }
6357 }
6358 } else {
6359 nbproc = global.nbproc;
6360 }
6361 if (curproxy->table.peers.name) {
6362 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6363 curproxy->id);
6364 cfgerr++;
6365 }
6366 if (nbproc > 1) {
6367 if (curproxy->uri_auth) {
6368 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6369 curproxy->id);
6370 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6371 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6372 curproxy->id);
6373 }
6374 }
6375 if (curproxy->appsession_name) {
6376 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6377 curproxy->id);
6378 }
6379 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6380 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6381 curproxy->id);
6382 }
6383 }
6384 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006385
6386 /* create the task associated with the proxy */
6387 curproxy->task = task_new();
6388 if (curproxy->task) {
6389 curproxy->task->context = curproxy;
6390 curproxy->task->process = manage_proxy;
6391 /* no need to queue, it will be done automatically if some
6392 * listener gets limited.
6393 */
6394 curproxy->task->expire = TICK_ETERNITY;
6395 } else {
6396 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6397 curproxy->id);
6398 cfgerr++;
6399 }
6400
Willy Tarreaubaaee002006-06-26 02:48:02 +02006401 curproxy = curproxy->next;
6402 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006403
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006404 /* Check multi-process mode compatibility */
6405 if (global.nbproc > 1) {
6406 if (global.stats_fe) {
6407 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6408 }
6409 }
6410
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006411 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6412 struct auth_users *curuser;
6413 int g;
6414
6415 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6416 unsigned int group_mask = 0;
6417 char *group = NULL;
6418
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006419 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006420 continue;
6421
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006422 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006423
6424 for (g = 0; g < curuserlist->grpcnt; g++)
6425 if (!strcmp(curuserlist->groups[g], group))
6426 break;
6427
6428 if (g == curuserlist->grpcnt) {
6429 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6430 curuserlist->name, group, curuser->user);
6431 err_code |= ERR_ALERT | ERR_FATAL;
6432 goto out;
6433 }
6434
6435 group_mask |= (1 << g);
6436 }
6437
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006438 free(curuser->u.groups);
6439 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006440 }
6441
6442 for (g = 0; g < curuserlist->grpcnt; g++) {
6443 char *user = NULL;
6444
6445 if (!curuserlist->groupusers[g])
6446 continue;
6447
6448 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6449 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6450 if (!strcmp(curuser->user, user))
6451 break;
6452
6453 if (!curuser) {
6454 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6455 curuserlist->name, user, curuserlist->groups[g]);
6456 err_code |= ERR_ALERT | ERR_FATAL;
6457 goto out;
6458 }
6459
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006460 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006461 }
6462
6463 free(curuserlist->groupusers[g]);
6464 }
6465
6466 free(curuserlist->groupusers);
6467
6468#ifdef DEBUG_AUTH
6469 for (g = 0; g < curuserlist->grpcnt; g++) {
6470 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6471
6472 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6473 if (curuser->group_mask & (1 << g))
6474 fprintf(stderr, " %s", curuser->user);
6475 }
6476
6477 fprintf(stderr, "\n");
6478 }
6479#endif
6480
Willy Tarreaufbb78422011-06-05 15:38:35 +02006481 }
6482
6483 /* automatically compute fullconn if not set. We must not do it in the
6484 * loop above because cross-references are not yet fully resolved.
6485 */
6486 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6487 /* If <fullconn> is not set, let's set it to 10% of the sum of
6488 * the possible incoming frontend's maxconns.
6489 */
6490 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6491 struct proxy *fe;
6492 int total = 0;
6493
6494 /* sum up the number of maxconns of frontends which
6495 * reference this backend at least once or which are
6496 * the same one ('listen').
6497 */
6498 for (fe = proxy; fe; fe = fe->next) {
6499 struct switching_rule *rule;
6500 struct hdr_exp *exp;
6501 int found = 0;
6502
6503 if (!(fe->cap & PR_CAP_FE))
6504 continue;
6505
6506 if (fe == curproxy) /* we're on a "listen" instance */
6507 found = 1;
6508
6509 if (fe->defbe.be == curproxy) /* "default_backend" */
6510 found = 1;
6511
6512 /* check if a "use_backend" rule matches */
6513 if (!found) {
6514 list_for_each_entry(rule, &fe->switching_rules, list) {
6515 if (rule->be.backend == curproxy) {
6516 found = 1;
6517 break;
6518 }
6519 }
6520 }
6521
6522 /* check if a "reqsetbe" rule matches */
6523 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6524 if (exp->action == ACT_SETBE &&
6525 (struct proxy *)exp->replace == curproxy) {
6526 found = 1;
6527 break;
6528 }
6529 }
6530
6531 /* now we've checked all possible ways to reference a backend
6532 * from a frontend.
6533 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006534 if (!found)
6535 continue;
6536 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006537 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006538 /* we have the sum of the maxconns in <total>. We only
6539 * keep 10% of that sum to set the default fullconn, with
6540 * a hard minimum of 1 (to avoid a divide by zero).
6541 */
6542 curproxy->fullconn = (total + 9) / 10;
6543 if (!curproxy->fullconn)
6544 curproxy->fullconn = 1;
6545 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006546 }
6547
Willy Tarreau056f5682010-06-06 15:51:11 +02006548 /* initialize stick-tables on backend capable proxies. This must not
6549 * be done earlier because the data size may be discovered while parsing
6550 * other proxies.
6551 */
6552 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006553 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006554
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006555 /*
6556 * Recount currently required checks.
6557 */
6558
6559 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6560 int optnum;
6561
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006562 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6563 if (curproxy->options & cfg_opts[optnum].val)
6564 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006565
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006566 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6567 if (curproxy->options2 & cfg_opts2[optnum].val)
6568 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006569 }
6570
Willy Tarreaubb925012009-07-23 13:36:36 +02006571 if (cfgerr > 0)
6572 err_code |= ERR_ALERT | ERR_FATAL;
6573 out:
6574 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006575}
6576
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006577/*
6578 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6579 * parsing sessions.
6580 */
6581void cfg_register_keywords(struct cfg_kw_list *kwl)
6582{
6583 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6584}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006585
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006586/*
6587 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6588 */
6589void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6590{
6591 LIST_DEL(&kwl->list);
6592 LIST_INIT(&kwl->list);
6593}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006594
6595/*
6596 * Local variables:
6597 * c-indent-level: 8
6598 * c-basic-offset: 8
6599 * End:
6600 */