blob: 04373acf6e77c9f79aceb425cd8777557b49bce9 [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 Tarreau977b8e42006-12-29 14:19:17 +01001428 if (defproxy.cookie_name)
1429 curproxy->cookie_name = strdup(defproxy.cookie_name);
1430 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001431 if (defproxy.cookie_domain)
1432 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001433
Willy Tarreau31936852010-10-06 16:59:56 +02001434 if (defproxy.cookie_maxidle)
1435 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1436
1437 if (defproxy.cookie_maxlife)
1438 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1439
Emeric Brun647caf12009-06-30 17:57:00 +02001440 if (defproxy.rdp_cookie_name)
1441 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1442 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1443
Willy Tarreau01732802007-11-01 22:48:15 +01001444 if (defproxy.url_param_name)
1445 curproxy->url_param_name = strdup(defproxy.url_param_name);
1446 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001447
Benoitaffb4812009-03-25 13:02:10 +01001448 if (defproxy.hh_name)
1449 curproxy->hh_name = strdup(defproxy.hh_name);
1450 curproxy->hh_len = defproxy.hh_len;
1451 curproxy->hh_match_domain = defproxy.hh_match_domain;
1452
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001453 if (defproxy.iface_name)
1454 curproxy->iface_name = strdup(defproxy.iface_name);
1455 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001456 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001458 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001459 if (defproxy.capture_name)
1460 curproxy->capture_name = strdup(defproxy.capture_name);
1461 curproxy->capture_namelen = defproxy.capture_namelen;
1462 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001463 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001464
Willy Tarreau977b8e42006-12-29 14:19:17 +01001465 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001466 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001467 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001468 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001469 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001470 curproxy->uri_auth = defproxy.uri_auth;
1471 curproxy->mon_net = defproxy.mon_net;
1472 curproxy->mon_mask = defproxy.mon_mask;
1473 if (defproxy.monitor_uri)
1474 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1475 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001476 if (defproxy.defbe.name)
1477 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001478 }
1479
1480 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001481 curproxy->timeout.connect = defproxy.timeout.connect;
1482 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001483 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001484 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001485 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001486 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001487 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001488 curproxy->source_addr = defproxy.source_addr;
1489 }
1490
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491 curproxy->mode = defproxy.mode;
1492 curproxy->logfac1 = defproxy.logfac1;
1493 curproxy->logsrv1 = defproxy.logsrv1;
1494 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001495 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001496 curproxy->logfac2 = defproxy.logfac2;
1497 curproxy->logsrv2 = defproxy.logsrv2;
1498 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001499 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001501 curproxy->conf.used_listener_id = EB_ROOT;
1502 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001503
Willy Tarreau93893792009-07-23 13:19:11 +02001504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001505 }
1506 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1507 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001508 /* FIXME-20070101: we should do this too at the end of the
1509 * config parsing to free all default values.
1510 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001511 free(defproxy.check_req);
1512 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001513 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001514 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001515 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001516 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001517 free(defproxy.capture_name);
1518 free(defproxy.monitor_uri);
1519 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001520 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001521 free(defproxy.fwdfor_hdr_name);
1522 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001523 free(defproxy.orgto_hdr_name);
1524 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001525
Willy Tarreaua534fea2008-08-03 12:19:50 +02001526 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001527 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001528
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529 /* we cannot free uri_auth because it might already be used */
1530 init_default_instance();
1531 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001532 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001534 }
1535 else if (curproxy == NULL) {
1536 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001537 err_code |= ERR_ALERT | ERR_FATAL;
1538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001539 }
1540
Willy Tarreau977b8e42006-12-29 14:19:17 +01001541
1542 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001543 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001544 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001545 int cur_arg;
1546
Willy Tarreaubaaee002006-06-26 02:48:02 +02001547 if (curproxy == &defproxy) {
1548 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001549 err_code |= ERR_ALERT | ERR_FATAL;
1550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001551 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001552 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001553 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554
Emeric Bruned760922010-10-22 17:59:25 +02001555 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001556 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001558 err_code |= ERR_ALERT | ERR_FATAL;
1559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001561
1562 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001563
1564 /* NOTE: the following line might create several listeners if there
1565 * are comma-separated IPs or port ranges. So all further processing
1566 * will have to be applied to all listeners created after last_listen.
1567 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001568 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001569 err_code |= ERR_ALERT | ERR_FATAL;
1570 goto out;
1571 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001572
Willy Tarreau90a570f2009-10-04 20:54:54 +02001573 new_listen = curproxy->listen;
1574 while (new_listen != last_listen) {
1575 new_listen->conf.file = file;
1576 new_listen->conf.line = linenum;
1577 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001578 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001579 }
1580
Emeric Bruned760922010-10-22 17:59:25 +02001581 /* Set default global rights and owner for unix bind */
1582 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1583 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1584 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001585 cur_arg = 2;
1586 while (*(args[cur_arg])) {
1587 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1588#ifdef SO_BINDTODEVICE
1589 struct listener *l;
1590
Emeric Bruned760922010-10-22 17:59:25 +02001591 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1592 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1593 file, linenum, args[0], args[cur_arg]);
1594 err_code |= ERR_ALERT | ERR_FATAL;
1595 goto out;
1596 }
1597
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001598 if (!*args[cur_arg + 1]) {
1599 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1600 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001601 err_code |= ERR_ALERT | ERR_FATAL;
1602 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001603 }
1604
1605 for (l = curproxy->listen; l != last_listen; l = l->next)
1606 l->interface = strdup(args[cur_arg + 1]);
1607
1608 global.last_checks |= LSTCHK_NETADM;
1609
1610 cur_arg += 2;
1611 continue;
1612#else
1613 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1614 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001615 err_code |= ERR_ALERT | ERR_FATAL;
1616 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001617#endif
1618 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001619 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1620#ifdef TCP_MAXSEG
1621 struct listener *l;
1622 int mss;
1623
Emeric Bruned760922010-10-22 17:59:25 +02001624 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1625 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1626 file, linenum, args[0], args[cur_arg]);
1627 err_code |= ERR_ALERT | ERR_FATAL;
1628 goto out;
1629 }
1630
Willy Tarreaube1b9182009-06-14 18:48:19 +02001631 if (!*args[cur_arg + 1]) {
1632 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1633 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001634 err_code |= ERR_ALERT | ERR_FATAL;
1635 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001636 }
1637
Willy Tarreau48a7e722010-12-24 15:26:39 +01001638 mss = atoi(args[cur_arg + 1]);
1639 if (!mss || abs(mss) > 65535) {
1640 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001641 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001642 err_code |= ERR_ALERT | ERR_FATAL;
1643 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001644 }
1645
1646 for (l = curproxy->listen; l != last_listen; l = l->next)
1647 l->maxseg = mss;
1648
1649 cur_arg += 2;
1650 continue;
1651#else
1652 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1653 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001654 err_code |= ERR_ALERT | ERR_FATAL;
1655 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001656#endif
1657 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001658
1659 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1660#ifdef TCP_DEFER_ACCEPT
1661 struct listener *l;
1662
1663 for (l = curproxy->listen; l != last_listen; l = l->next)
1664 l->options |= LI_O_DEF_ACCEPT;
1665
1666 cur_arg ++;
1667 continue;
1668#else
1669 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1670 file, linenum, args[0], args[cur_arg]);
1671 err_code |= ERR_ALERT | ERR_FATAL;
1672 goto out;
1673#endif
1674 }
1675
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001676 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001677#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001678 struct listener *l;
1679
Emeric Bruned760922010-10-22 17:59:25 +02001680 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1681 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1682 file, linenum, args[0], args[cur_arg]);
1683 err_code |= ERR_ALERT | ERR_FATAL;
1684 goto out;
1685 }
1686
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001687 for (l = curproxy->listen; l != last_listen; l = l->next)
1688 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001689
1690 cur_arg ++;
1691 continue;
1692#else
1693 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1694 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001697#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001698 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001699
Willy Tarreau8a956912010-10-15 14:27:08 +02001700 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1701 struct listener *l;
1702
1703 for (l = curproxy->listen; l != last_listen; l = l->next)
1704 l->options |= LI_O_ACC_PROXY;
1705
1706 cur_arg ++;
1707 continue;
1708 }
1709
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001710 if (!strcmp(args[cur_arg], "name")) {
1711 struct listener *l;
1712
1713 for (l = curproxy->listen; l != last_listen; l = l->next)
1714 l->name = strdup(args[cur_arg + 1]);
1715
1716 cur_arg += 2;
1717 continue;
1718 }
1719
1720 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001721 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001722 struct listener *l;
1723
1724 if (curproxy->listen->next != last_listen) {
1725 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1726 file, linenum, args[cur_arg]);
1727 err_code |= ERR_ALERT | ERR_FATAL;
1728 goto out;
1729 }
1730
1731 if (!*args[cur_arg + 1]) {
1732 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1733 file, linenum, args[cur_arg]);
1734 err_code |= ERR_ALERT | ERR_FATAL;
1735 goto out;
1736 }
1737
1738 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001739 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001740
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001741 if (curproxy->listen->luid <= 0) {
1742 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001743 file, linenum);
1744 err_code |= ERR_ALERT | ERR_FATAL;
1745 goto out;
1746 }
1747
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001748 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1749 if (node) {
1750 l = container_of(node, struct listener, conf.id);
1751 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1752 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1753 err_code |= ERR_ALERT | ERR_FATAL;
1754 goto out;
1755 }
1756 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1757
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001758 cur_arg += 2;
1759 continue;
1760 }
1761
Emeric Bruned760922010-10-22 17:59:25 +02001762 if (!strcmp(args[cur_arg], "mode")) {
1763
1764 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1765 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1766 file, linenum, args[0], args[cur_arg]);
1767 err_code |= ERR_ALERT | ERR_FATAL;
1768 goto out;
1769 }
1770
1771 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1772
1773 cur_arg += 2;
1774 continue;
1775 }
1776
1777 if (!strcmp(args[cur_arg], "uid")) {
1778
1779 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1780 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1781 file, linenum, args[0], args[cur_arg]);
1782 err_code |= ERR_ALERT | ERR_FATAL;
1783 goto out;
1784 }
1785
1786 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1787 cur_arg += 2;
1788 continue;
1789 }
1790
1791 if (!strcmp(args[cur_arg], "gid")) {
1792
1793 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1794 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1795 file, linenum, args[0], args[cur_arg]);
1796 err_code |= ERR_ALERT | ERR_FATAL;
1797 goto out;
1798 }
1799
1800 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1801 cur_arg += 2;
1802 continue;
1803 }
1804
1805 if (!strcmp(args[cur_arg], "user")) {
1806 struct passwd *user;
1807
1808 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1809 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1810 file, linenum, args[0], args[cur_arg]);
1811 err_code |= ERR_ALERT | ERR_FATAL;
1812 goto out;
1813 }
1814 user = getpwnam(args[cur_arg + 1]);
1815 if (!user) {
1816 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1817 file, linenum, args[0], args[cur_arg + 1 ]);
1818 err_code |= ERR_ALERT | ERR_FATAL;
1819 goto out;
1820 }
1821
1822 curproxy->listen->perm.ux.uid = user->pw_uid;
1823 cur_arg += 2;
1824 continue;
1825 }
1826
1827 if (!strcmp(args[cur_arg], "group")) {
1828 struct group *group;
1829
1830 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1831 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1832 file, linenum, args[0], args[cur_arg]);
1833 err_code |= ERR_ALERT | ERR_FATAL;
1834 goto out;
1835 }
1836 group = getgrnam(args[cur_arg + 1]);
1837 if (!group) {
1838 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1839 file, linenum, args[0], args[cur_arg + 1 ]);
1840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
1842 }
1843
1844 curproxy->listen->perm.ux.gid = group->gr_gid;
1845 cur_arg += 2;
1846 continue;
1847 }
1848
Willy Tarreau8a956912010-10-15 14:27:08 +02001849 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 +01001850 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001851 err_code |= ERR_ALERT | ERR_FATAL;
1852 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001853 }
Willy Tarreau93893792009-07-23 13:19:11 +02001854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001855 }
1856 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1857 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1858 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1859 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001860 err_code |= ERR_ALERT | ERR_FATAL;
1861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001862 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001863 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001864 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001865
Willy Tarreaubaaee002006-06-26 02:48:02 +02001866 /* flush useless bits */
1867 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001868 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001869 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001870 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001871 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001872 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001873
Willy Tarreau1c47f852006-07-09 08:22:27 +02001874 if (!*args[1]) {
1875 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1876 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001877 err_code |= ERR_ALERT | ERR_FATAL;
1878 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001879 }
1880
Willy Tarreaua534fea2008-08-03 12:19:50 +02001881 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001882 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001883 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001884 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001885 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1886
Willy Tarreau93893792009-07-23 13:19:11 +02001887 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001888 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1890 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1891 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1892 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1893 else {
1894 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001895 err_code |= ERR_ALERT | ERR_FATAL;
1896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001897 }
1898 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001899 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001900 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001901
1902 if (curproxy == &defproxy) {
1903 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1904 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001905 err_code |= ERR_ALERT | ERR_FATAL;
1906 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001907 }
1908
1909 if (!*args[1]) {
1910 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1911 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001912 err_code |= ERR_ALERT | ERR_FATAL;
1913 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001914 }
1915
1916 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001917 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001918
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001919 if (curproxy->uuid <= 0) {
1920 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001921 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001922 err_code |= ERR_ALERT | ERR_FATAL;
1923 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001924 }
1925
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001926 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1927 if (node) {
1928 struct proxy *target = container_of(node, struct proxy, conf.id);
1929 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1930 file, linenum, proxy_type_str(curproxy), curproxy->id,
1931 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
1934 }
1935 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001936 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001937 else if (!strcmp(args[0], "description")) {
1938 int i, len=0;
1939 char *d;
1940
Cyril Bonté99ed3272010-01-24 23:29:44 +01001941 if (curproxy == &defproxy) {
1942 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1943 file, linenum, args[0]);
1944 err_code |= ERR_ALERT | ERR_FATAL;
1945 goto out;
1946 }
1947
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001948 if (!*args[1]) {
1949 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1950 file, linenum, args[0]);
1951 return -1;
1952 }
1953
1954 for(i=1; *args[i]; i++)
1955 len += strlen(args[i])+1;
1956
1957 d = (char *)calloc(1, len);
1958 curproxy->desc = d;
1959
1960 d += sprintf(d, "%s", args[1]);
1961 for(i=2; *args[i]; i++)
1962 d += sprintf(d, " %s", args[i]);
1963
1964 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001965 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1966 curproxy->state = PR_STSTOPPED;
1967 }
1968 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1969 curproxy->state = PR_STNEW;
1970 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001971 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1972 int cur_arg = 1;
1973 unsigned int set = 0;
1974
1975 while (*args[cur_arg]) {
1976 int u;
1977 if (strcmp(args[cur_arg], "all") == 0) {
1978 set = 0;
1979 break;
1980 }
1981 else if (strcmp(args[cur_arg], "odd") == 0) {
1982 set |= 0x55555555;
1983 }
1984 else if (strcmp(args[cur_arg], "even") == 0) {
1985 set |= 0xAAAAAAAA;
1986 }
1987 else {
1988 u = str2uic(args[cur_arg]);
1989 if (u < 1 || u > 32) {
1990 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1991 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001992 err_code |= ERR_ALERT | ERR_FATAL;
1993 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001994 }
1995 if (u > global.nbproc) {
1996 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1997 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001998 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001999 }
2000 set |= 1 << (u - 1);
2001 }
2002 cur_arg++;
2003 }
2004 curproxy->bind_proc = set;
2005 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002006 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002007 if (curproxy == &defproxy) {
2008 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002009 err_code |= ERR_ALERT | ERR_FATAL;
2010 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002011 }
2012
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002013 err = invalid_char(args[1]);
2014 if (err) {
2015 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2016 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002017 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002018 }
2019
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002020 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2021 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2022 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002023 err_code |= ERR_ALERT | ERR_FATAL;
2024 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002025 }
2026 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002027 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2028 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002029
Willy Tarreau977b8e42006-12-29 14:19:17 +01002030 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002031 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002032
Willy Tarreaubaaee002006-06-26 02:48:02 +02002033 if (*(args[1]) == 0) {
2034 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2035 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002036 err_code |= ERR_ALERT | ERR_FATAL;
2037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002038 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002039
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002040 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002041 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002042 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002043 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002044 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002045 curproxy->cookie_name = strdup(args[1]);
2046 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002047
Willy Tarreaubaaee002006-06-26 02:48:02 +02002048 cur_arg = 2;
2049 while (*(args[cur_arg])) {
2050 if (!strcmp(args[cur_arg], "rewrite")) {
2051 curproxy->options |= PR_O_COOK_RW;
2052 }
2053 else if (!strcmp(args[cur_arg], "indirect")) {
2054 curproxy->options |= PR_O_COOK_IND;
2055 }
2056 else if (!strcmp(args[cur_arg], "insert")) {
2057 curproxy->options |= PR_O_COOK_INS;
2058 }
2059 else if (!strcmp(args[cur_arg], "nocache")) {
2060 curproxy->options |= PR_O_COOK_NOC;
2061 }
2062 else if (!strcmp(args[cur_arg], "postonly")) {
2063 curproxy->options |= PR_O_COOK_POST;
2064 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002065 else if (!strcmp(args[cur_arg], "preserve")) {
2066 curproxy->options2 |= PR_O2_COOK_PSV;
2067 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002068 else if (!strcmp(args[cur_arg], "prefix")) {
2069 curproxy->options |= PR_O_COOK_PFX;
2070 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002071 else if (!strcmp(args[cur_arg], "domain")) {
2072 if (!*args[cur_arg + 1]) {
2073 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2074 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002075 err_code |= ERR_ALERT | ERR_FATAL;
2076 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002077 }
2078
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002079 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002080 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002081 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2082 " dots nor does not start with a dot."
2083 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002084 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002085 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002086 }
2087
2088 err = invalid_domainchar(args[cur_arg + 1]);
2089 if (err) {
2090 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2091 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002092 err_code |= ERR_ALERT | ERR_FATAL;
2093 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002094 }
2095
Willy Tarreau68a897b2009-12-03 23:28:34 +01002096 if (!curproxy->cookie_domain) {
2097 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2098 } else {
2099 /* one domain was already specified, add another one by
2100 * building the string which will be returned along with
2101 * the cookie.
2102 */
2103 char *new_ptr;
2104 int new_len = strlen(curproxy->cookie_domain) +
2105 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2106 new_ptr = malloc(new_len);
2107 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2108 free(curproxy->cookie_domain);
2109 curproxy->cookie_domain = new_ptr;
2110 }
Willy Tarreau31936852010-10-06 16:59:56 +02002111 cur_arg++;
2112 }
2113 else if (!strcmp(args[cur_arg], "maxidle")) {
2114 unsigned int maxidle;
2115 const char *res;
2116
2117 if (!*args[cur_arg + 1]) {
2118 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2119 file, linenum, args[cur_arg]);
2120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
2122 }
2123
2124 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2125 if (res) {
2126 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2127 file, linenum, *res, args[cur_arg]);
2128 err_code |= ERR_ALERT | ERR_FATAL;
2129 goto out;
2130 }
2131 curproxy->cookie_maxidle = maxidle;
2132 cur_arg++;
2133 }
2134 else if (!strcmp(args[cur_arg], "maxlife")) {
2135 unsigned int maxlife;
2136 const char *res;
2137
2138 if (!*args[cur_arg + 1]) {
2139 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2140 file, linenum, args[cur_arg]);
2141 err_code |= ERR_ALERT | ERR_FATAL;
2142 goto out;
2143 }
2144
2145 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2146 if (res) {
2147 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2148 file, linenum, *res, args[cur_arg]);
2149 err_code |= ERR_ALERT | ERR_FATAL;
2150 goto out;
2151 }
2152 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002153 cur_arg++;
2154 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002156 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 +02002157 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002158 err_code |= ERR_ALERT | ERR_FATAL;
2159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002160 }
2161 cur_arg++;
2162 }
2163 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2164 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2165 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002166 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002167 }
2168
2169 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2170 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2171 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002172 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002173 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002174
2175 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2176 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2177 file, linenum);
2178 err_code |= ERR_ALERT | ERR_FATAL;
2179 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002180 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002181 else if (!strcmp(args[0], "persist")) { /* persist */
2182 if (*(args[1]) == 0) {
2183 Alert("parsing [%s:%d] : missing persist method.\n",
2184 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002185 err_code |= ERR_ALERT | ERR_FATAL;
2186 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002187 }
2188
2189 if (!strncmp(args[1], "rdp-cookie", 10)) {
2190 curproxy->options2 |= PR_O2_RDPC_PRST;
2191
Emeric Brunb982a3d2010-01-04 15:45:53 +01002192 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002193 const char *beg, *end;
2194
2195 beg = args[1] + 11;
2196 end = strchr(beg, ')');
2197
2198 if (!end || end == beg) {
2199 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2200 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002201 err_code |= ERR_ALERT | ERR_FATAL;
2202 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002203 }
2204
2205 free(curproxy->rdp_cookie_name);
2206 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2207 curproxy->rdp_cookie_len = end-beg;
2208 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002209 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002210 free(curproxy->rdp_cookie_name);
2211 curproxy->rdp_cookie_name = strdup("msts");
2212 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2213 }
2214 else { /* syntax */
2215 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2216 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002217 err_code |= ERR_ALERT | ERR_FATAL;
2218 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002219 }
2220 }
2221 else {
2222 Alert("parsing [%s:%d] : unknown persist method.\n",
2223 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002224 err_code |= ERR_ALERT | ERR_FATAL;
2225 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002226 }
2227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002229 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002231 if (curproxy == &defproxy) {
2232 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2233 err_code |= ERR_ALERT | ERR_FATAL;
2234 goto out;
2235 }
2236
Willy Tarreau977b8e42006-12-29 14:19:17 +01002237 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002238 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002239
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002241 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 }
2246 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002247 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 curproxy->appsession_name = strdup(args[1]);
2249 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2250 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002251 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2252 if (err) {
2253 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2254 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002255 err_code |= ERR_ALERT | ERR_FATAL;
2256 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002257 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002258 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002259
Willy Tarreau51041c72007-09-09 21:56:53 +02002260 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2261 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002262 err_code |= ERR_ALERT | ERR_ABORT;
2263 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002265
2266 cur_arg = 6;
2267 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002268 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2269 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002270 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002271 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002272 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002273 } else if (!strcmp(args[cur_arg], "prefix")) {
2274 curproxy->options2 |= PR_O2_AS_PFX;
2275 } else if (!strcmp(args[cur_arg], "mode")) {
2276 if (!*args[cur_arg + 1]) {
2277 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2278 file, linenum, args[0], args[cur_arg]);
2279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
2281 }
2282
2283 cur_arg++;
2284 if (!strcmp(args[cur_arg], "query-string")) {
2285 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2286 curproxy->options2 |= PR_O2_AS_M_QS;
2287 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2288 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2289 curproxy->options2 |= PR_O2_AS_M_PP;
2290 } else {
2291 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2292 err_code |= ERR_ALERT | ERR_FATAL;
2293 goto out;
2294 }
2295 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002296 cur_arg++;
2297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 } /* Url App Session */
2299 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002300 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002301 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002302
Willy Tarreaubaaee002006-06-26 02:48:02 +02002303 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002304 if (curproxy == &defproxy) {
2305 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309
Willy Tarreaubaaee002006-06-26 02:48:02 +02002310 if (*(args[4]) == 0) {
2311 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2312 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002315 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002316 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002317 curproxy->capture_name = strdup(args[2]);
2318 curproxy->capture_namelen = strlen(curproxy->capture_name);
2319 curproxy->capture_len = atol(args[4]);
2320 if (curproxy->capture_len >= CAPTURE_LEN) {
2321 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2322 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002323 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002324 curproxy->capture_len = CAPTURE_LEN - 1;
2325 }
2326 curproxy->to_log |= LW_COOKIE;
2327 }
2328 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2329 struct cap_hdr *hdr;
2330
2331 if (curproxy == &defproxy) {
2332 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 +02002333 err_code |= ERR_ALERT | ERR_FATAL;
2334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 }
2336
2337 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2338 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2339 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002340 err_code |= ERR_ALERT | ERR_FATAL;
2341 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 }
2343
2344 hdr = calloc(sizeof(struct cap_hdr), 1);
2345 hdr->next = curproxy->req_cap;
2346 hdr->name = strdup(args[3]);
2347 hdr->namelen = strlen(args[3]);
2348 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002349 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002350 hdr->index = curproxy->nb_req_cap++;
2351 curproxy->req_cap = hdr;
2352 curproxy->to_log |= LW_REQHDR;
2353 }
2354 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2355 struct cap_hdr *hdr;
2356
2357 if (curproxy == &defproxy) {
2358 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 +02002359 err_code |= ERR_ALERT | ERR_FATAL;
2360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 }
2362
2363 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2364 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2365 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 }
2369 hdr = calloc(sizeof(struct cap_hdr), 1);
2370 hdr->next = curproxy->rsp_cap;
2371 hdr->name = strdup(args[3]);
2372 hdr->namelen = strlen(args[3]);
2373 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002374 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 hdr->index = curproxy->nb_rsp_cap++;
2376 curproxy->rsp_cap = hdr;
2377 curproxy->to_log |= LW_RSPHDR;
2378 }
2379 else {
2380 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2381 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 }
2385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002387 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002389
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 if (*(args[1]) == 0) {
2391 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\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 curproxy->conn_retries = atol(args[1]);
2397 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002398 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002399 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002400
2401 if (curproxy == &defproxy) {
2402 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2403 err_code |= ERR_ALERT | ERR_FATAL;
2404 goto out;
2405 }
2406
Willy Tarreauff011f22011-01-06 17:51:27 +01002407 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 +01002408 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2409 file, linenum, args[0]);
2410 err_code |= ERR_WARN;
2411 }
2412
Willy Tarreauff011f22011-01-06 17:51:27 +01002413 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002414
Willy Tarreauff011f22011-01-06 17:51:27 +01002415 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002416 err_code |= ERR_ALERT | ERR_ABORT;
2417 goto out;
2418 }
2419
Willy Tarreauff011f22011-01-06 17:51:27 +01002420 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2421 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002422 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002423 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002424 if (curproxy == &defproxy) {
2425 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002428 }
2429
Willy Tarreauef6494c2010-01-28 17:12:36 +01002430 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002431 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2432 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002435 }
2436
Willy Tarreauef6494c2010-01-28 17:12:36 +01002437 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002438 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2439 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002442 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002443
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002444 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002445 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002446 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002447 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002448 struct redirect_rule *rule;
2449 int cur_arg;
2450 int type = REDIRECT_TYPE_NONE;
2451 int code = 302;
2452 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002453 char *cookie = NULL;
2454 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002455 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002456
Cyril Bonté99ed3272010-01-24 23:29:44 +01002457 if (curproxy == &defproxy) {
2458 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
2461 }
2462
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002463 cur_arg = 1;
2464 while (*(args[cur_arg])) {
2465 if (!strcmp(args[cur_arg], "location")) {
2466 if (!*args[cur_arg + 1]) {
2467 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2468 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002471 }
2472
2473 type = REDIRECT_TYPE_LOCATION;
2474 cur_arg++;
2475 destination = args[cur_arg];
2476 }
2477 else if (!strcmp(args[cur_arg], "prefix")) {
2478 if (!*args[cur_arg + 1]) {
2479 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2480 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002483 }
2484
2485 type = REDIRECT_TYPE_PREFIX;
2486 cur_arg++;
2487 destination = args[cur_arg];
2488 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002489 else if (!strcmp(args[cur_arg], "set-cookie")) {
2490 if (!*args[cur_arg + 1]) {
2491 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2492 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002495 }
2496
2497 cur_arg++;
2498 cookie = args[cur_arg];
2499 cookie_set = 1;
2500 }
2501 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2502 if (!*args[cur_arg + 1]) {
2503 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2504 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002507 }
2508
2509 cur_arg++;
2510 cookie = args[cur_arg];
2511 cookie_set = 0;
2512 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002513 else if (!strcmp(args[cur_arg],"code")) {
2514 if (!*args[cur_arg + 1]) {
2515 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2516 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002517 err_code |= ERR_ALERT | ERR_FATAL;
2518 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002519 }
2520 cur_arg++;
2521 code = atol(args[cur_arg]);
2522 if (code < 301 || code > 303) {
2523 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2524 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002527 }
2528 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002529 else if (!strcmp(args[cur_arg],"drop-query")) {
2530 flags |= REDIRECT_FLAG_DROP_QS;
2531 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002532 else if (!strcmp(args[cur_arg],"append-slash")) {
2533 flags |= REDIRECT_FLAG_APPEND_SLASH;
2534 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002535 else if (strcmp(args[cur_arg], "if") == 0 ||
2536 strcmp(args[cur_arg], "unless") == 0) {
2537 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2538 if (!cond) {
2539 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2540 file, linenum, args[0]);
2541 err_code |= ERR_ALERT | ERR_FATAL;
2542 goto out;
2543 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002544 break;
2545 }
2546 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002547 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 +02002548 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002551 }
2552 cur_arg++;
2553 }
2554
2555 if (type == REDIRECT_TYPE_NONE) {
2556 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2557 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002560 }
2561
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002562 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2563 rule->cond = cond;
2564 rule->rdr_str = strdup(destination);
2565 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002566 if (cookie) {
2567 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002568 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002569 */
2570 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002571 if (cookie_set) {
2572 rule->cookie_str = malloc(rule->cookie_len + 10);
2573 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2574 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2575 rule->cookie_len += 9;
2576 } else {
2577 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002578 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002579 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2580 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002581 }
2582 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002583 rule->type = type;
2584 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002585 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002586 LIST_INIT(&rule->list);
2587 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002588 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2589 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002590 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002591 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002592 struct switching_rule *rule;
2593
Willy Tarreaub099aca2008-10-12 17:26:37 +02002594 if (curproxy == &defproxy) {
2595 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002596 err_code |= ERR_ALERT | ERR_FATAL;
2597 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002598 }
2599
Willy Tarreau55ea7572007-06-17 19:56:27 +02002600 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002601 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002602
2603 if (*(args[1]) == 0) {
2604 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002605 err_code |= ERR_ALERT | ERR_FATAL;
2606 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002607 }
2608
Willy Tarreauef6494c2010-01-28 17:12:36 +01002609 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002610 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2611 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002614 }
2615
Willy Tarreauef6494c2010-01-28 17:12:36 +01002616 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002617 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002618 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002619 err_code |= ERR_ALERT | ERR_FATAL;
2620 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002621 }
2622
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002623 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002624
Willy Tarreau55ea7572007-06-17 19:56:27 +02002625 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2626 rule->cond = cond;
2627 rule->be.name = strdup(args[1]);
2628 LIST_INIT(&rule->list);
2629 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2630 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002631 else if ((!strcmp(args[0], "force-persist")) ||
2632 (!strcmp(args[0], "ignore-persist"))) {
2633 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002634
2635 if (curproxy == &defproxy) {
2636 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2637 err_code |= ERR_ALERT | ERR_FATAL;
2638 goto out;
2639 }
2640
2641 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2642 err_code |= ERR_WARN;
2643
Willy Tarreauef6494c2010-01-28 17:12:36 +01002644 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002645 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2646 file, linenum, args[0]);
2647 err_code |= ERR_ALERT | ERR_FATAL;
2648 goto out;
2649 }
2650
Willy Tarreauef6494c2010-01-28 17:12:36 +01002651 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002652 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2653 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
2656 }
2657
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002658 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002659
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002660 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002661 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002662 if (!strcmp(args[0], "force-persist")) {
2663 rule->type = PERSIST_TYPE_FORCE;
2664 } else {
2665 rule->type = PERSIST_TYPE_IGNORE;
2666 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002667 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002668 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002669 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002670 else if (!strcmp(args[0], "stick-table")) {
2671 int myidx = 1;
2672
Emeric Brun32da3c42010-09-23 18:39:19 +02002673 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002674 curproxy->table.type = (unsigned int)-1;
2675 while (*args[myidx]) {
2676 const char *err;
2677
2678 if (strcmp(args[myidx], "size") == 0) {
2679 myidx++;
2680 if (!*(args[myidx])) {
2681 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2682 file, linenum, args[myidx-1]);
2683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
2685 }
2686 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2687 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2688 file, linenum, *err, args[myidx-1]);
2689 err_code |= ERR_ALERT | ERR_FATAL;
2690 goto out;
2691 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002692 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002693 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002694 else if (strcmp(args[myidx], "peers") == 0) {
2695 myidx++;
2696 if (!*(args[myidx])) {
2697 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2698 file, linenum, args[myidx-1]);
2699 err_code |= ERR_ALERT | ERR_FATAL;
2700 goto out;
2701 }
2702 curproxy->table.peers.name = strdup(args[myidx++]);
2703 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002704 else if (strcmp(args[myidx], "expire") == 0) {
2705 myidx++;
2706 if (!*(args[myidx])) {
2707 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2708 file, linenum, args[myidx-1]);
2709 err_code |= ERR_ALERT | ERR_FATAL;
2710 goto out;
2711 }
2712 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2713 if (err) {
2714 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2715 file, linenum, *err, args[myidx-1]);
2716 err_code |= ERR_ALERT | ERR_FATAL;
2717 goto out;
2718 }
2719 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002720 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002721 }
2722 else if (strcmp(args[myidx], "nopurge") == 0) {
2723 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002724 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002725 }
2726 else if (strcmp(args[myidx], "type") == 0) {
2727 myidx++;
2728 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2729 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2730 file, linenum, args[myidx]);
2731 err_code |= ERR_ALERT | ERR_FATAL;
2732 goto out;
2733 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002734 /* myidx already points to next arg */
2735 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002736 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002737 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002738 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002739
2740 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002741 nw = args[myidx];
2742 while (*nw) {
2743 /* the "store" keyword supports a comma-separated list */
2744 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002745 sa = NULL; /* store arg */
2746 while (*nw && *nw != ',') {
2747 if (*nw == '(') {
2748 *nw = 0;
2749 sa = ++nw;
2750 while (*nw != ')') {
2751 if (!*nw) {
2752 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2753 file, linenum, args[0], cw);
2754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
2756 }
2757 nw++;
2758 }
2759 *nw = '\0';
2760 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002761 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002762 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002763 if (*nw)
2764 *nw++ = '\0';
2765 type = stktable_get_data_type(cw);
2766 if (type < 0) {
2767 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2768 file, linenum, args[0], cw);
2769 err_code |= ERR_ALERT | ERR_FATAL;
2770 goto out;
2771 }
Willy Tarreauac782882010-06-20 10:41:54 +02002772
2773 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2774 switch (err) {
2775 case PE_NONE: break;
2776 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002777 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2778 file, linenum, args[0], cw);
2779 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002780 break;
2781
2782 case PE_ARG_MISSING:
2783 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2784 file, linenum, args[0], cw);
2785 err_code |= ERR_ALERT | ERR_FATAL;
2786 goto out;
2787
2788 case PE_ARG_NOT_USED:
2789 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2790 file, linenum, args[0], cw);
2791 err_code |= ERR_ALERT | ERR_FATAL;
2792 goto out;
2793
2794 default:
2795 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2796 file, linenum, args[0], cw);
2797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002799 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002800 }
2801 myidx++;
2802 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002803 else {
2804 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2805 file, linenum, args[myidx]);
2806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002808 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002809 }
2810
2811 if (!curproxy->table.size) {
2812 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2813 file, linenum);
2814 err_code |= ERR_ALERT | ERR_FATAL;
2815 goto out;
2816 }
2817
2818 if (curproxy->table.type == (unsigned int)-1) {
2819 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2820 file, linenum);
2821 err_code |= ERR_ALERT | ERR_FATAL;
2822 goto out;
2823 }
2824 }
2825 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002826 struct sticking_rule *rule;
2827 struct pattern_expr *expr;
2828 int myidx = 0;
2829 const char *name = NULL;
2830 int flags;
2831
2832 if (curproxy == &defproxy) {
2833 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2834 err_code |= ERR_ALERT | ERR_FATAL;
2835 goto out;
2836 }
2837
2838 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2839 err_code |= ERR_WARN;
2840 goto out;
2841 }
2842
2843 myidx++;
2844 if ((strcmp(args[myidx], "store") == 0) ||
2845 (strcmp(args[myidx], "store-request") == 0)) {
2846 myidx++;
2847 flags = STK_IS_STORE;
2848 }
2849 else if (strcmp(args[myidx], "store-response") == 0) {
2850 myidx++;
2851 flags = STK_IS_STORE | STK_ON_RSP;
2852 }
2853 else if (strcmp(args[myidx], "match") == 0) {
2854 myidx++;
2855 flags = STK_IS_MATCH;
2856 }
2857 else if (strcmp(args[myidx], "on") == 0) {
2858 myidx++;
2859 flags = STK_IS_MATCH | STK_IS_STORE;
2860 }
2861 else {
2862 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2863 err_code |= ERR_ALERT | ERR_FATAL;
2864 goto out;
2865 }
2866
2867 if (*(args[myidx]) == 0) {
2868 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
2871 }
2872
Emeric Brun485479d2010-09-23 18:02:19 +02002873 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002874 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002875 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
2878 }
2879
2880 if (flags & STK_ON_RSP) {
2881 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2882 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2883 file, linenum, args[0], expr->fetch->kw);
2884 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002885 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002886 goto out;
2887 }
2888 } else {
2889 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2890 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2891 file, linenum, args[0], expr->fetch->kw);
2892 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002893 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002894 goto out;
2895 }
2896 }
2897
2898 if (strcmp(args[myidx], "table") == 0) {
2899 myidx++;
2900 name = args[myidx++];
2901 }
2902
Willy Tarreauef6494c2010-01-28 17:12:36 +01002903 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2904 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002905 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2906 file, linenum, args[0]);
2907 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002908 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002909 goto out;
2910 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002911 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002912 else if (*(args[myidx])) {
2913 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2914 file, linenum, args[0], args[myidx]);
2915 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002916 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002917 goto out;
2918 }
Emeric Brun97679e72010-09-23 17:56:44 +02002919 if (flags & STK_ON_RSP)
2920 err_code |= warnif_cond_requires_req(cond, file, linenum);
2921 else
2922 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002923
Emeric Brunb982a3d2010-01-04 15:45:53 +01002924 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2925 rule->cond = cond;
2926 rule->expr = expr;
2927 rule->flags = flags;
2928 rule->table.name = name ? strdup(name) : NULL;
2929 LIST_INIT(&rule->list);
2930 if (flags & STK_ON_RSP)
2931 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2932 else
2933 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2934 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002935 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002936 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002937 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002938
Willy Tarreaubaaee002006-06-26 02:48:02 +02002939 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2940 curproxy->uri_auth = NULL; /* we must detach from the default config */
2941
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002942 if (!*args[1]) {
2943 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002944 } else if (!strcmp(args[1], "admin")) {
2945 struct stats_admin_rule *rule;
2946
2947 if (curproxy == &defproxy) {
2948 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952
2953 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2954 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2955 err_code |= ERR_ALERT | ERR_ABORT;
2956 goto out;
2957 }
2958
2959 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2960 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2961 file, linenum, args[0], args[1]);
2962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
2964 }
2965 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2966 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2967 file, linenum, args[0], args[1]);
2968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
2971
2972 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2973
2974 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2975 rule->cond = cond;
2976 LIST_INIT(&rule->list);
2977 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002978 } else if (!strcmp(args[1], "uri")) {
2979 if (*(args[2]) == 0) {
2980 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002981 err_code |= ERR_ALERT | ERR_FATAL;
2982 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002983 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2984 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002985 err_code |= ERR_ALERT | ERR_ABORT;
2986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002987 }
2988 } else if (!strcmp(args[1], "realm")) {
2989 if (*(args[2]) == 0) {
2990 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002993 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2994 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002995 err_code |= ERR_ALERT | ERR_ABORT;
2996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002998 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002999 unsigned interval;
3000
3001 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3002 if (err) {
3003 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3004 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003005 err_code |= ERR_ALERT | ERR_FATAL;
3006 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003007 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3008 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003009 err_code |= ERR_ALERT | ERR_ABORT;
3010 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003011 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003012 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003013 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003014
3015 if (curproxy == &defproxy) {
3016 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
3019 }
3020
3021 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3022 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3023 err_code |= ERR_ALERT | ERR_ABORT;
3024 goto out;
3025 }
3026
Willy Tarreauff011f22011-01-06 17:51:27 +01003027 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3028 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003029 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3030 file, linenum, args[0]);
3031 err_code |= ERR_WARN;
3032 }
3033
Willy Tarreauff011f22011-01-06 17:51:27 +01003034 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003035
Willy Tarreauff011f22011-01-06 17:51:27 +01003036 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003037 err_code |= ERR_ALERT | ERR_ABORT;
3038 goto out;
3039 }
3040
Willy Tarreauff011f22011-01-06 17:51:27 +01003041 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3042 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003043
Willy Tarreaubaaee002006-06-26 02:48:02 +02003044 } else if (!strcmp(args[1], "auth")) {
3045 if (*(args[2]) == 0) {
3046 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003049 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3050 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003051 err_code |= ERR_ALERT | ERR_ABORT;
3052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003053 }
3054 } else if (!strcmp(args[1], "scope")) {
3055 if (*(args[2]) == 0) {
3056 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003057 err_code |= ERR_ALERT | ERR_FATAL;
3058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003059 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3060 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_ABORT;
3062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 }
3064 } else if (!strcmp(args[1], "enable")) {
3065 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3066 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003067 err_code |= ERR_ALERT | ERR_ABORT;
3068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003069 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003070 } else if (!strcmp(args[1], "hide-version")) {
3071 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3072 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003073 err_code |= ERR_ALERT | ERR_ABORT;
3074 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003075 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003076 } else if (!strcmp(args[1], "show-legends")) {
3077 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3078 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3079 err_code |= ERR_ALERT | ERR_ABORT;
3080 goto out;
3081 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003082 } else if (!strcmp(args[1], "show-node")) {
3083
3084 if (*args[2]) {
3085 int i;
3086 char c;
3087
3088 for (i=0; args[2][i]; i++) {
3089 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003090 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3091 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003092 break;
3093 }
3094
3095 if (!i || args[2][i]) {
3096 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3097 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3098 file, linenum, args[0], args[1]);
3099 err_code |= ERR_ALERT | ERR_FATAL;
3100 goto out;
3101 }
3102 }
3103
3104 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3105 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3106 err_code |= ERR_ALERT | ERR_ABORT;
3107 goto out;
3108 }
3109 } else if (!strcmp(args[1], "show-desc")) {
3110 char *desc = NULL;
3111
3112 if (*args[2]) {
3113 int i, len=0;
3114 char *d;
3115
3116 for(i=2; *args[i]; i++)
3117 len += strlen(args[i])+1;
3118
3119 desc = d = (char *)calloc(1, len);
3120
3121 d += sprintf(d, "%s", args[2]);
3122 for(i=3; *args[i]; i++)
3123 d += sprintf(d, " %s", args[i]);
3124 }
3125
3126 if (!*args[2] && !global.desc)
3127 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3128 file, linenum, args[1]);
3129 else {
3130 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3131 free(desc);
3132 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3133 err_code |= ERR_ALERT | ERR_ABORT;
3134 goto out;
3135 }
3136 free(desc);
3137 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003139stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003140 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 +01003141 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144 }
3145 }
3146 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003147 int optnum;
3148
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003149 if (*(args[1]) == '\0') {
3150 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3151 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003152 err_code |= ERR_ALERT | ERR_FATAL;
3153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003155
3156 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3157 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003158 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3159 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3160 file, linenum, cfg_opts[optnum].name);
3161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
3163 }
Willy Tarreau93893792009-07-23 13:19:11 +02003164 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3165 err_code |= ERR_WARN;
3166 goto out;
3167 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003168
Willy Tarreau3842f002009-06-14 11:39:52 +02003169 curproxy->no_options &= ~cfg_opts[optnum].val;
3170 curproxy->options &= ~cfg_opts[optnum].val;
3171
3172 switch (kwm) {
3173 case KWM_STD:
3174 curproxy->options |= cfg_opts[optnum].val;
3175 break;
3176 case KWM_NO:
3177 curproxy->no_options |= cfg_opts[optnum].val;
3178 break;
3179 case KWM_DEF: /* already cleared */
3180 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003181 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003182
Willy Tarreau93893792009-07-23 13:19:11 +02003183 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003184 }
3185 }
3186
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003187 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3188 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003189 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3190 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3191 file, linenum, cfg_opts2[optnum].name);
3192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
3194 }
Willy Tarreau93893792009-07-23 13:19:11 +02003195 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3196 err_code |= ERR_WARN;
3197 goto out;
3198 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003199
Willy Tarreau3842f002009-06-14 11:39:52 +02003200 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3201 curproxy->options2 &= ~cfg_opts2[optnum].val;
3202
3203 switch (kwm) {
3204 case KWM_STD:
3205 curproxy->options2 |= cfg_opts2[optnum].val;
3206 break;
3207 case KWM_NO:
3208 curproxy->no_options2 |= cfg_opts2[optnum].val;
3209 break;
3210 case KWM_DEF: /* already cleared */
3211 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003212 }
Willy Tarreau93893792009-07-23 13:19:11 +02003213 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003214 }
3215 }
3216
Willy Tarreau3842f002009-06-14 11:39:52 +02003217 if (kwm != KWM_STD) {
3218 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003219 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_ALERT | ERR_FATAL;
3221 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003222 }
3223
Emeric Brun3a058f32009-06-30 18:26:00 +02003224 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003225 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003226 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003228 if (*(args[2]) != '\0') {
3229 if (!strcmp(args[2], "clf")) {
3230 curproxy->options2 |= PR_O2_CLFLOG;
3231 } else {
3232 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003235 }
3236 }
3237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 else if (!strcmp(args[1], "tcplog"))
3239 /* generate a detailed TCP log */
3240 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 else if (!strcmp(args[1], "tcpka")) {
3242 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003243 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003244 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003245
3246 if (curproxy->cap & PR_CAP_FE)
3247 curproxy->options |= PR_O_TCP_CLI_KA;
3248 if (curproxy->cap & PR_CAP_BE)
3249 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 }
3251 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003252 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003253 err_code |= ERR_WARN;
3254
Willy Tarreaubaaee002006-06-26 02:48:02 +02003255 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003256 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003257 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003258 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003259 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003260 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003261 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003262 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003263 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 if (!*args[2]) { /* no argument */
3265 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3266 curproxy->check_len = strlen(DEF_CHECK_REQ);
3267 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003268 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269 curproxy->check_req = (char *)malloc(reqlen);
3270 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003271 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003273 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274 if (*args[4])
3275 reqlen += strlen(args[4]);
3276 else
3277 reqlen += strlen("HTTP/1.0");
3278
3279 curproxy->check_req = (char *)malloc(reqlen);
3280 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003281 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003283 }
3284 else if (!strcmp(args[1], "ssl-hello-chk")) {
3285 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003286 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003287 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003288
Willy Tarreaua534fea2008-08-03 12:19:50 +02003289 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003290 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003291 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003292 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003293 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003294 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003295 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003296 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 }
Willy Tarreau23677902007-05-08 23:50:35 +02003298 else if (!strcmp(args[1], "smtpchk")) {
3299 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003300 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003301 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003302 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003303 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003304 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003305 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003306 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003307 curproxy->options |= PR_O_SMTP_CHK;
3308
3309 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3310 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3311 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3312 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3313 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3314 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3315 curproxy->check_req = (char *)malloc(reqlen);
3316 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3317 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3318 } else {
3319 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3320 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3321 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3322 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3323 }
3324 }
3325 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003326 else if (!strcmp(args[1], "pgsql-check")) {
3327 /* use PostgreSQL request to check servers' health */
3328 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3329 err_code |= ERR_WARN;
3330
3331 free(curproxy->check_req);
3332 curproxy->check_req = NULL;
3333 curproxy->options &= ~PR_O_HTTP_CHK;
3334 curproxy->options &= ~PR_O_SMTP_CHK;
3335 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3336 curproxy->options2 &= ~PR_O2_LDAP_CHK;
3337 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3338 curproxy->options2 |= PR_O2_PGSQL_CHK;
3339
3340 if (*(args[2])) {
3341 int cur_arg = 2;
3342
3343 while (*(args[cur_arg])) {
3344 if (strcmp(args[cur_arg], "user") == 0) {
3345 char * packet;
3346 uint32_t packet_len;
3347 uint32_t pv;
3348
3349 /* suboption header - needs additional argument for it */
3350 if (*(args[cur_arg+1]) == 0) {
3351 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3352 file, linenum, args[0], args[1], args[cur_arg]);
3353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
3355 }
3356
3357 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3358 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3359 pv = htonl(0x30000); /* protocol version 3.0 */
3360
3361 packet = (char*) calloc(1, packet_len);
3362
3363 memcpy(packet + 4, &pv, 4);
3364
3365 /* copy "user" */
3366 memcpy(packet + 8, "user", 4);
3367
3368 /* copy username */
3369 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3370
3371 free(curproxy->check_req);
3372 curproxy->check_req = packet;
3373 curproxy->check_len = packet_len;
3374
3375 packet_len = htonl(packet_len);
3376 memcpy(packet, &packet_len, 4);
3377 cur_arg += 2;
3378 } else {
3379 /* unknown suboption - catchall */
3380 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3381 file, linenum, args[0], args[1]);
3382 err_code |= ERR_ALERT | ERR_FATAL;
3383 goto out;
3384 }
3385 } /* end while loop */
3386 }
3387 }
3388
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003389 else if (!strcmp(args[1], "mysql-check")) {
3390 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003391 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3392 err_code |= ERR_WARN;
3393
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003394 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003395 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003396 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003397 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003398 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003399 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003400 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003401 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003402
3403 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3404 * const char mysql40_client_auth_pkt[] = {
3405 * "\x0e\x00\x00" // packet length
3406 * "\x01" // packet number
3407 * "\x00\x00" // client capabilities
3408 * "\x00\x00\x01" // max packet
3409 * "haproxy\x00" // username (null terminated string)
3410 * "\x00" // filler (always 0x00)
3411 * "\x01\x00\x00" // packet length
3412 * "\x00" // packet number
3413 * "\x01" // COM_QUIT command
3414 * };
3415 */
3416
3417 if (*(args[2])) {
3418 int cur_arg = 2;
3419
3420 while (*(args[cur_arg])) {
3421 if (strcmp(args[cur_arg], "user") == 0) {
3422 char *mysqluser;
3423 int packetlen, reqlen, userlen;
3424
3425 /* suboption header - needs additional argument for it */
3426 if (*(args[cur_arg+1]) == 0) {
3427 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3428 file, linenum, args[0], args[1], args[cur_arg]);
3429 err_code |= ERR_ALERT | ERR_FATAL;
3430 goto out;
3431 }
3432 mysqluser = args[cur_arg + 1];
3433 userlen = strlen(mysqluser);
3434 packetlen = userlen + 7;
3435 reqlen = packetlen + 9;
3436
3437 free(curproxy->check_req);
3438 curproxy->check_req = (char *)calloc(1, reqlen);
3439 curproxy->check_len = reqlen;
3440
3441 snprintf(curproxy->check_req, 4, "%c%c%c",
3442 ((unsigned char) packetlen & 0xff),
3443 ((unsigned char) (packetlen >> 8) & 0xff),
3444 ((unsigned char) (packetlen >> 16) & 0xff));
3445
3446 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003447 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003448 curproxy->check_req[8] = 1;
3449 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3450 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3451 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3452 cur_arg += 2;
3453 } else {
3454 /* unknown suboption - catchall */
3455 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3456 file, linenum, args[0], args[1]);
3457 err_code |= ERR_ALERT | ERR_FATAL;
3458 goto out;
3459 }
3460 } /* end while loop */
3461 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003462 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003463 else if (!strcmp(args[1], "ldap-check")) {
3464 /* use LDAP request to check servers' health */
3465 free(curproxy->check_req);
3466 curproxy->check_req = NULL;
3467 curproxy->options &= ~PR_O_HTTP_CHK;
3468 curproxy->options &= ~PR_O_SMTP_CHK;
3469 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3470 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003471 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003472 curproxy->options2 |= PR_O2_LDAP_CHK;
3473
3474 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3475 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3476 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3477 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003478 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003479 int cur_arg;
3480
3481 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3482 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003483 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003484
3485 curproxy->options |= PR_O_FWDFOR;
3486
3487 free(curproxy->fwdfor_hdr_name);
3488 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3489 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3490
3491 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3492 cur_arg = 2;
3493 while (*(args[cur_arg])) {
3494 if (!strcmp(args[cur_arg], "except")) {
3495 /* suboption except - needs additional argument for it */
3496 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3497 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3498 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003501 }
3502 /* flush useless bits */
3503 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003504 cur_arg += 2;
3505 } else if (!strcmp(args[cur_arg], "header")) {
3506 /* suboption header - needs additional argument for it */
3507 if (*(args[cur_arg+1]) == 0) {
3508 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3509 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003512 }
3513 free(curproxy->fwdfor_hdr_name);
3514 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3515 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3516 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003517 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003518 /* unknown suboption - catchall */
3519 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3520 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003523 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003524 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003525 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003526 else if (!strcmp(args[1], "originalto")) {
3527 int cur_arg;
3528
3529 /* insert x-original-to field, but not for the IP address listed as an except.
3530 * set default options (ie: bitfield, header name, etc)
3531 */
3532
3533 curproxy->options |= PR_O_ORGTO;
3534
3535 free(curproxy->orgto_hdr_name);
3536 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3537 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3538
3539 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3540 cur_arg = 2;
3541 while (*(args[cur_arg])) {
3542 if (!strcmp(args[cur_arg], "except")) {
3543 /* suboption except - needs additional argument for it */
3544 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3545 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3546 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003547 err_code |= ERR_ALERT | ERR_FATAL;
3548 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003549 }
3550 /* flush useless bits */
3551 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3552 cur_arg += 2;
3553 } else if (!strcmp(args[cur_arg], "header")) {
3554 /* suboption header - needs additional argument for it */
3555 if (*(args[cur_arg+1]) == 0) {
3556 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3557 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003558 err_code |= ERR_ALERT | ERR_FATAL;
3559 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003560 }
3561 free(curproxy->orgto_hdr_name);
3562 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3563 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3564 cur_arg += 2;
3565 } else {
3566 /* unknown suboption - catchall */
3567 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3568 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003569 err_code |= ERR_ALERT | ERR_FATAL;
3570 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003571 }
3572 } /* end while loop */
3573 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003574 else {
3575 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003576 err_code |= ERR_ALERT | ERR_FATAL;
3577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 }
Willy Tarreau93893792009-07-23 13:19:11 +02003579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003581 else if (!strcmp(args[0], "default_backend")) {
3582 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003583 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003584
3585 if (*(args[1]) == 0) {
3586 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003589 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003590 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003591 curproxy->defbe.name = strdup(args[1]);
3592 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003594 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003596
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003597 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3598 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003599 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003600 /* enable reconnections to dispatch */
3601 curproxy->options |= PR_O_REDISP;
3602 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003603 else if (!strcmp(args[0], "http-check")) {
3604 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003605 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003606
3607 if (strcmp(args[1], "disable-on-404") == 0) {
3608 /* enable a graceful server shutdown on an HTTP 404 response */
3609 curproxy->options |= PR_O_DISABLE404;
3610 }
Willy Tarreauef781042010-01-27 11:53:01 +01003611 else if (strcmp(args[1], "send-state") == 0) {
3612 /* enable emission of the apparent state of a server in HTTP checks */
3613 curproxy->options2 |= PR_O2_CHK_SNDST;
3614 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003615 else if (strcmp(args[1], "expect") == 0) {
3616 const char *ptr_arg;
3617 int cur_arg;
3618
3619 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3620 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
3623 }
3624
3625 cur_arg = 2;
3626 /* consider exclamation marks, sole or at the beginning of a word */
3627 while (*(ptr_arg = args[cur_arg])) {
3628 while (*ptr_arg == '!') {
3629 curproxy->options2 ^= PR_O2_EXP_INV;
3630 ptr_arg++;
3631 }
3632 if (*ptr_arg)
3633 break;
3634 cur_arg++;
3635 }
3636 /* now ptr_arg points to the beginning of a word past any possible
3637 * exclamation mark, and cur_arg is the argument which holds this word.
3638 */
3639 if (strcmp(ptr_arg, "status") == 0) {
3640 if (!*(args[cur_arg + 1])) {
3641 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3642 file, linenum, args[0], args[1], ptr_arg);
3643 err_code |= ERR_ALERT | ERR_FATAL;
3644 goto out;
3645 }
3646 curproxy->options2 |= PR_O2_EXP_STS;
3647 curproxy->expect_str = strdup(args[cur_arg + 1]);
3648 }
3649 else if (strcmp(ptr_arg, "string") == 0) {
3650 if (!*(args[cur_arg + 1])) {
3651 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3652 file, linenum, args[0], args[1], ptr_arg);
3653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
3655 }
3656 curproxy->options2 |= PR_O2_EXP_STR;
3657 curproxy->expect_str = strdup(args[cur_arg + 1]);
3658 }
3659 else if (strcmp(ptr_arg, "rstatus") == 0) {
3660 if (!*(args[cur_arg + 1])) {
3661 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3662 file, linenum, args[0], args[1], ptr_arg);
3663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
3665 }
3666 curproxy->options2 |= PR_O2_EXP_RSTS;
3667 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3668 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3669 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3670 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3671 err_code |= ERR_ALERT | ERR_FATAL;
3672 goto out;
3673 }
3674 }
3675 else if (strcmp(ptr_arg, "rstring") == 0) {
3676 if (!*(args[cur_arg + 1])) {
3677 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3678 file, linenum, args[0], args[1], ptr_arg);
3679 err_code |= ERR_ALERT | ERR_FATAL;
3680 goto out;
3681 }
3682 curproxy->options2 |= PR_O2_EXP_RSTR;
3683 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3684 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3685 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3686 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
3689 }
3690 }
3691 else {
3692 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3693 file, linenum, args[0], args[1], ptr_arg);
3694 err_code |= ERR_ALERT | ERR_FATAL;
3695 goto out;
3696 }
3697 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003698 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003699 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003700 err_code |= ERR_ALERT | ERR_FATAL;
3701 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003702 }
3703 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003704 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003705 if (curproxy == &defproxy) {
3706 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003709 }
3710
Willy Tarreaub80c2302007-11-30 20:51:32 +01003711 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003712 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003713
3714 if (strcmp(args[1], "fail") == 0) {
3715 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003716 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003717 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3718 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003721 }
3722
Willy Tarreauef6494c2010-01-28 17:12:36 +01003723 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003724 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3725 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003728 }
3729 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3730 }
3731 else {
3732 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003735 }
3736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737#ifdef TPROXY
3738 else if (!strcmp(args[0], "transparent")) {
3739 /* enable transparent proxy connections */
3740 curproxy->options |= PR_O_TRANSP;
3741 }
3742#endif
3743 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003744 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003746
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747 if (*(args[1]) == 0) {
3748 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003751 }
3752 curproxy->maxconn = atol(args[1]);
3753 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003754 else if (!strcmp(args[0], "backlog")) { /* backlog */
3755 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003756 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003757
3758 if (*(args[1]) == 0) {
3759 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003762 }
3763 curproxy->backlog = atol(args[1]);
3764 }
Willy Tarreau86034312006-12-29 00:10:33 +01003765 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003766 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003768
Willy Tarreau86034312006-12-29 00:10:33 +01003769 if (*(args[1]) == 0) {
3770 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003773 }
3774 curproxy->fullconn = atol(args[1]);
3775 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3777 if (*(args[1]) == 0) {
3778 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003782 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3783 if (err) {
3784 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3785 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003788 }
3789 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 }
3791 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003792 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003793 if (curproxy == &defproxy) {
3794 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003797 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003798 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003800
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 if (strchr(args[1], ':') == NULL) {
3802 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003806 sk = str2sa(args[1]);
3807 if (!sk) {
3808 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
3811 }
3812 curproxy->dispatch_addr = *sk;
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01003813 curproxy->options2 |= PR_O2_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 }
3815 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003816 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003818
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003819 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003820 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3821 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003824 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003826 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3827 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3828 err_code |= ERR_WARN;
3829
3830 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3831 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3832 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3833 }
3834 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3835 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3836 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3837 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003838 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3839 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3840 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3841 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003842 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003843 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
3846 }
3847 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003848 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003849 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003850 char *rport, *raddr;
3851 short realport = 0;
3852 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003854 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003855 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003859 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003860 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003861
3862 if (!*args[2]) {
3863 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3864 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_ALERT | ERR_FATAL;
3866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003868
3869 err = invalid_char(args[1]);
3870 if (err) {
3871 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3872 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003873 err_code |= ERR_ALERT | ERR_FATAL;
3874 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003875 }
3876
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003877 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003878 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003879
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003880 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3881 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3882 err_code |= ERR_ALERT | ERR_ABORT;
3883 goto out;
3884 }
3885
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003886 /* the servers are linked backwards first */
3887 newsrv->next = curproxy->srv;
3888 curproxy->srv = newsrv;
3889 newsrv->proxy = curproxy;
3890 newsrv->conf.file = file;
3891 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003892
Simon Hormanaf514952011-06-21 14:34:57 +09003893 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003894 LIST_INIT(&newsrv->pendconns);
3895 do_check = 0;
3896 newsrv->state = SRV_RUNNING; /* early server setup */
3897 newsrv->last_change = now.tv_sec;
3898 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003899
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003900 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003901 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003902 * - IP: => port=+0, relative
3903 * - IP:N => port=N, absolute
3904 * - IP:+N => port=+N, relative
3905 * - IP:-N => port=-N, relative
3906 */
3907 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003908 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003909 if (rport) {
3910 *rport++ = 0;
3911 realport = atol(rport);
3912 if (!isdigit((unsigned char)*rport))
3913 newsrv->state |= SRV_MAPPORTS;
3914 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003915 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003916
Willy Tarreaufab5a432011-03-04 15:31:53 +01003917 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003918 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003919 if (!sk) {
3920 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3921 err_code |= ERR_ALERT | ERR_FATAL;
3922 goto out;
3923 }
3924 newsrv->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01003925
3926 switch (newsrv->addr.ss_family) {
3927 case AF_INET:
3928 ((struct sockaddr_in *)&newsrv->addr)->sin_port = htons(realport);
3929 break;
3930 case AF_INET6:
3931 ((struct sockaddr_in6 *)&newsrv->addr)->sin6_port = htons(realport);
3932 break;
3933 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003934
3935 newsrv->check_port = curproxy->defsrv.check_port;
3936 newsrv->inter = curproxy->defsrv.inter;
3937 newsrv->fastinter = curproxy->defsrv.fastinter;
3938 newsrv->downinter = curproxy->defsrv.downinter;
3939 newsrv->rise = curproxy->defsrv.rise;
3940 newsrv->fall = curproxy->defsrv.fall;
3941 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3942 newsrv->minconn = curproxy->defsrv.minconn;
3943 newsrv->maxconn = curproxy->defsrv.maxconn;
3944 newsrv->slowstart = curproxy->defsrv.slowstart;
3945 newsrv->onerror = curproxy->defsrv.onerror;
3946 newsrv->consecutive_errors_limit
3947 = curproxy->defsrv.consecutive_errors_limit;
3948 newsrv->uweight = newsrv->iweight
3949 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003951 newsrv->curfd = -1; /* no health-check in progress */
3952 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003953
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003954 cur_arg = 3;
3955 } else {
3956 newsrv = &curproxy->defsrv;
3957 cur_arg = 1;
3958 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003959
Willy Tarreaubaaee002006-06-26 02:48:02 +02003960 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003961 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003962 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003963
3964 if (!*args[cur_arg + 1]) {
3965 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3966 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003969 }
3970
3971 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003972 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003973
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003974 if (newsrv->puid <= 0) {
3975 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003976 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003977 err_code |= ERR_ALERT | ERR_FATAL;
3978 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003979 }
3980
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003981 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3982 if (node) {
3983 struct server *target = container_of(node, struct server, conf.id);
3984 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3985 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3986 err_code |= ERR_ALERT | ERR_FATAL;
3987 goto out;
3988 }
3989 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003990 cur_arg += 2;
3991 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003992 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003993 newsrv->cookie = strdup(args[cur_arg + 1]);
3994 newsrv->cklen = strlen(args[cur_arg + 1]);
3995 cur_arg += 2;
3996 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003997 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003998 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3999 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4000 cur_arg += 2;
4001 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004002 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004003 if (!*args[cur_arg + 1]) {
4004 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4005 file, linenum, args[cur_arg]);
4006 err_code |= ERR_ALERT | ERR_FATAL;
4007 goto out;
4008 }
4009
Willy Tarreaubaaee002006-06-26 02:48:02 +02004010 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004011 if (newsrv->rise <= 0) {
4012 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4013 file, linenum, args[cur_arg]);
4014 err_code |= ERR_ALERT | ERR_FATAL;
4015 goto out;
4016 }
4017
Willy Tarreau96839092010-03-29 10:02:24 +02004018 if (newsrv->health)
4019 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004020 cur_arg += 2;
4021 }
4022 else if (!strcmp(args[cur_arg], "fall")) {
4023 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004024
4025 if (!*args[cur_arg + 1]) {
4026 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4027 file, linenum, args[cur_arg]);
4028 err_code |= ERR_ALERT | ERR_FATAL;
4029 goto out;
4030 }
4031
4032 if (newsrv->fall <= 0) {
4033 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4034 file, linenum, args[cur_arg]);
4035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
4037 }
4038
Willy Tarreaubaaee002006-06-26 02:48:02 +02004039 cur_arg += 2;
4040 }
4041 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004042 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4043 if (err) {
4044 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4045 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004048 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004049 if (val <= 0) {
4050 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4051 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004054 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004055 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004056 cur_arg += 2;
4057 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004058 else if (!strcmp(args[cur_arg], "fastinter")) {
4059 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4060 if (err) {
4061 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4062 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004063 err_code |= ERR_ALERT | ERR_FATAL;
4064 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004065 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004066 if (val <= 0) {
4067 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4068 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004069 err_code |= ERR_ALERT | ERR_FATAL;
4070 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004071 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004072 newsrv->fastinter = val;
4073 cur_arg += 2;
4074 }
4075 else if (!strcmp(args[cur_arg], "downinter")) {
4076 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4077 if (err) {
4078 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4079 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004080 err_code |= ERR_ALERT | ERR_FATAL;
4081 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004082 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004083 if (val <= 0) {
4084 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4085 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004086 err_code |= ERR_ALERT | ERR_FATAL;
4087 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004088 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004089 newsrv->downinter = val;
4090 cur_arg += 2;
4091 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004092 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004093 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004094 if (!sk) {
4095 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4096 err_code |= ERR_ALERT | ERR_FATAL;
4097 goto out;
4098 }
4099 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004100 cur_arg += 2;
4101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004102 else if (!strcmp(args[cur_arg], "port")) {
4103 newsrv->check_port = atol(args[cur_arg + 1]);
4104 cur_arg += 2;
4105 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004106 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004107 newsrv->state |= SRV_BACKUP;
4108 cur_arg ++;
4109 }
Simon Hormanfa461682011-06-25 09:39:49 +09004110 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4111 newsrv->state |= SRV_NON_STICK;
4112 cur_arg ++;
4113 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004114 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4115 newsrv->state |= SRV_SEND_PROXY;
4116 cur_arg ++;
4117 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004118 else if (!strcmp(args[cur_arg], "weight")) {
4119 int w;
4120 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004121 if (w < 0 || w > 256) {
4122 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004123 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004126 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004127 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004128 cur_arg += 2;
4129 }
4130 else if (!strcmp(args[cur_arg], "minconn")) {
4131 newsrv->minconn = atol(args[cur_arg + 1]);
4132 cur_arg += 2;
4133 }
4134 else if (!strcmp(args[cur_arg], "maxconn")) {
4135 newsrv->maxconn = atol(args[cur_arg + 1]);
4136 cur_arg += 2;
4137 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004138 else if (!strcmp(args[cur_arg], "maxqueue")) {
4139 newsrv->maxqueue = atol(args[cur_arg + 1]);
4140 cur_arg += 2;
4141 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004142 else if (!strcmp(args[cur_arg], "slowstart")) {
4143 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004144 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004145 if (err) {
4146 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4147 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004148 err_code |= ERR_ALERT | ERR_FATAL;
4149 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004150 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004151 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004152 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4153 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004154 err_code |= ERR_ALERT | ERR_FATAL;
4155 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004156 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004157 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004158 cur_arg += 2;
4159 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004160 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004161
4162 if (!*args[cur_arg + 1]) {
4163 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4164 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004165 err_code |= ERR_ALERT | ERR_FATAL;
4166 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004167 }
4168
4169 newsrv->trackit = strdup(args[cur_arg + 1]);
4170
4171 cur_arg += 2;
4172 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004173 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004174 global.maxsock++;
4175 do_check = 1;
4176 cur_arg += 1;
4177 }
Willy Tarreau96839092010-03-29 10:02:24 +02004178 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4179 newsrv->state |= SRV_MAINTAIN;
4180 newsrv->state &= ~SRV_RUNNING;
4181 newsrv->health = 0;
4182 cur_arg += 1;
4183 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004184 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004185 if (!strcmp(args[cur_arg + 1], "none"))
4186 newsrv->observe = HANA_OBS_NONE;
4187 else if (!strcmp(args[cur_arg + 1], "layer4"))
4188 newsrv->observe = HANA_OBS_LAYER4;
4189 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4190 if (curproxy->mode != PR_MODE_HTTP) {
4191 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4192 file, linenum, args[cur_arg + 1]);
4193 err_code |= ERR_ALERT;
4194 }
4195 newsrv->observe = HANA_OBS_LAYER7;
4196 }
4197 else {
4198 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004199 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004200 file, linenum, args[cur_arg], args[cur_arg + 1]);
4201 err_code |= ERR_ALERT | ERR_FATAL;
4202 goto out;
4203 }
4204
4205 cur_arg += 2;
4206 }
4207 else if (!strcmp(args[cur_arg], "on-error")) {
4208 if (!strcmp(args[cur_arg + 1], "fastinter"))
4209 newsrv->onerror = HANA_ONERR_FASTINTER;
4210 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4211 newsrv->onerror = HANA_ONERR_FAILCHK;
4212 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4213 newsrv->onerror = HANA_ONERR_SUDDTH;
4214 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4215 newsrv->onerror = HANA_ONERR_MARKDWN;
4216 else {
4217 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004218 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004219 file, linenum, args[cur_arg], args[cur_arg + 1]);
4220 err_code |= ERR_ALERT | ERR_FATAL;
4221 goto out;
4222 }
4223
4224 cur_arg += 2;
4225 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004226 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4227 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4228 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4229 else {
4230 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4231 file, linenum, args[cur_arg], args[cur_arg + 1]);
4232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
4234 }
4235
4236 cur_arg += 2;
4237 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004238 else if (!strcmp(args[cur_arg], "error-limit")) {
4239 if (!*args[cur_arg + 1]) {
4240 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4241 file, linenum, args[cur_arg]);
4242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
4244 }
4245
4246 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4247
4248 if (newsrv->consecutive_errors_limit <= 0) {
4249 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4250 file, linenum, args[cur_arg]);
4251 err_code |= ERR_ALERT | ERR_FATAL;
4252 goto out;
4253 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004254 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004255 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004256 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004257 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004258 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004259
Willy Tarreaubaaee002006-06-26 02:48:02 +02004260 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004261#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004262 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004263 file, linenum, "source", "usesrc");
4264#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004265 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004266 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004267#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004270 }
4271 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004272 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4273 if (!sk) {
4274 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4275 err_code |= ERR_ALERT | ERR_FATAL;
4276 goto out;
4277 }
4278 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004279
4280 if (port_low != port_high) {
4281 int i;
4282 if (port_low <= 0 || port_low > 65535 ||
4283 port_high <= 0 || port_high > 65535 ||
4284 port_low > port_high) {
4285 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4286 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004287 err_code |= ERR_ALERT | ERR_FATAL;
4288 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004289 }
4290 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4291 for (i = 0; i < newsrv->sport_range->size; i++)
4292 newsrv->sport_range->ports[i] = port_low + i;
4293 }
4294
Willy Tarreaubaaee002006-06-26 02:48:02 +02004295 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004296 while (*(args[cur_arg])) {
4297 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004298#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4299#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004300 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4301 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4302 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004303 err_code |= ERR_ALERT | ERR_FATAL;
4304 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004305 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004306#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004307 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004308 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004309 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004312 }
4313 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004314 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004315 newsrv->state |= SRV_TPROXY_CLI;
4316 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004317 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004318 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004319 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4320 char *name, *end;
4321
4322 name = args[cur_arg+1] + 7;
4323 while (isspace(*name))
4324 name++;
4325
4326 end = name;
4327 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4328 end++;
4329
4330 newsrv->state &= ~SRV_TPROXY_MASK;
4331 newsrv->state |= SRV_TPROXY_DYN;
4332 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4333 newsrv->bind_hdr_len = end - name;
4334 memcpy(newsrv->bind_hdr_name, name, end - name);
4335 newsrv->bind_hdr_name[end-name] = '\0';
4336 newsrv->bind_hdr_occ = -1;
4337
4338 /* now look for an occurrence number */
4339 while (isspace(*end))
4340 end++;
4341 if (*end == ',') {
4342 end++;
4343 name = end;
4344 if (*end == '-')
4345 end++;
4346 while (isdigit(*end))
4347 end++;
4348 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4349 }
4350
4351 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4352 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4353 " occurrences values smaller than %d.\n",
4354 file, linenum, MAX_HDR_HISTORY);
4355 err_code |= ERR_ALERT | ERR_FATAL;
4356 goto out;
4357 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004358 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004359 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004360 if (!sk) {
4361 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4362 err_code |= ERR_ALERT | ERR_FATAL;
4363 goto out;
4364 }
4365 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004366 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004367 }
4368 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004369#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004370 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004371#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004372 cur_arg += 2;
4373 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004374#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004375 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004376 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004377 err_code |= ERR_ALERT | ERR_FATAL;
4378 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004379#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4380 } /* "usesrc" */
4381
4382 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4383#ifdef SO_BINDTODEVICE
4384 if (!*args[cur_arg + 1]) {
4385 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4386 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004389 }
4390 if (newsrv->iface_name)
4391 free(newsrv->iface_name);
4392
4393 newsrv->iface_name = strdup(args[cur_arg + 1]);
4394 newsrv->iface_len = strlen(newsrv->iface_name);
4395 global.last_checks |= LSTCHK_NETADM;
4396#else
4397 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4398 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004399 err_code |= ERR_ALERT | ERR_FATAL;
4400 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004401#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004402 cur_arg += 2;
4403 continue;
4404 }
4405 /* this keyword in not an option of "source" */
4406 break;
4407 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004408 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004409 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004410 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4411 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004412 err_code |= ERR_ALERT | ERR_FATAL;
4413 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004414 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004415 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004416 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004417 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 +01004418 file, linenum, newsrv->id);
4419 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004420 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 +01004421 file, linenum);
4422
Willy Tarreau93893792009-07-23 13:19:11 +02004423 err_code |= ERR_ALERT | ERR_FATAL;
4424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004425 }
4426 }
4427
4428 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004429 if (newsrv->trackit) {
4430 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4431 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004432 err_code |= ERR_ALERT | ERR_FATAL;
4433 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004434 }
4435
David du Colombier6f5ccb12011-03-10 22:26:24 +01004436 switch (newsrv->check_addr.ss_family) {
4437 case AF_INET:
4438 if (!newsrv->check_port && ((struct sockaddr_in *)&newsrv->check_addr)->sin_port)
4439 newsrv->check_port = ntohs(((struct sockaddr_in *)&newsrv->check_addr)->sin_port);
4440 break;
4441 case AF_INET6:
4442 if (!newsrv->check_port && ((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port)
4443 newsrv->check_port = ntohs(((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port);
4444 break;
4445 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004446
Willy Tarreaubaaee002006-06-26 02:48:02 +02004447 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4448 newsrv->check_port = realport; /* by default */
4449 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004450 /* not yet valid, because no port was set on
4451 * the server either. We'll check if we have
4452 * a known port on the first listener.
4453 */
4454 struct listener *l;
4455 l = curproxy->listen;
4456 if (l) {
4457 int port;
4458 port = (l->addr.ss_family == AF_INET6)
4459 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4460 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4461 newsrv->check_port = port;
4462 }
4463 }
4464 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004465 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4466 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004467 err_code |= ERR_ALERT | ERR_FATAL;
4468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004469 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004470
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004471 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004472 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004473 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4474 err_code |= ERR_ALERT | ERR_ABORT;
4475 goto out;
4476 }
4477
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004478 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004479 newsrv->state |= SRV_CHECKED;
4480 }
4481
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004482 if (!defsrv) {
4483 if (newsrv->state & SRV_BACKUP)
4484 curproxy->srv_bck++;
4485 else
4486 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004487
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004488 newsrv->prev_state = newsrv->state;
4489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004490 }
4491 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004492 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004493 int facility;
4494
4495 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4496 curproxy->logfac1 = global.logfac1;
4497 curproxy->logsrv1 = global.logsrv1;
4498 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004499 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 curproxy->logfac2 = global.logfac2;
4501 curproxy->logsrv2 = global.logsrv2;
4502 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004503 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004504 }
4505 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004506 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004507
4508 facility = get_log_facility(args[2]);
4509 if (facility < 0) {
4510 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4511 exit(1);
4512 }
4513
4514 level = 7; /* max syslog level = debug */
4515 if (*(args[3])) {
4516 level = get_log_level(args[3]);
4517 if (level < 0) {
4518 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4519 exit(1);
4520 }
4521 }
4522
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004523 minlvl = 0; /* limit syslog level to this level (emerg) */
4524 if (*(args[4])) {
4525 minlvl = get_log_level(args[4]);
4526 if (level < 0) {
4527 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4528 exit(1);
4529 }
4530 }
4531
Robert Tsai81ae1952007-12-05 10:47:29 +01004532 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004533 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004534 if (!sk) {
4535 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004536 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004537 err_code |= ERR_ALERT | ERR_FATAL;
4538 goto out;
4539 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004540 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004541 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004542 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004543 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004544 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4545 err_code |= ERR_ALERT | ERR_FATAL;
4546 goto out;
4547 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004548 logsrv.addr = *sk;
4549 if (!get_host_port(&logsrv.addr))
4550 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004551 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004552
4553 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004554 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004555 curproxy->logfac1 = facility;
4556 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004557 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004558 }
4559 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004560 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004561 curproxy->logfac2 = facility;
4562 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004563 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004564 }
4565 else {
4566 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004567 err_code |= ERR_ALERT | ERR_FATAL;
4568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 }
4570 }
4571 else {
4572 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4573 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004574 err_code |= ERR_ALERT | ERR_FATAL;
4575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 }
4577 }
4578 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004579 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004580 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004581
Willy Tarreau977b8e42006-12-29 14:19:17 +01004582 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004583 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004584
Willy Tarreaubaaee002006-06-26 02:48:02 +02004585 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004586 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4587 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004590 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004591
4592 /* we must first clear any optional default setting */
4593 curproxy->options &= ~PR_O_TPXY_MASK;
4594 free(curproxy->iface_name);
4595 curproxy->iface_name = NULL;
4596 curproxy->iface_len = 0;
4597
Willy Tarreaud5191e72010-02-09 20:50:45 +01004598 sk = str2sa(args[1]);
4599 if (!sk) {
4600 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4601 err_code |= ERR_ALERT | ERR_FATAL;
4602 goto out;
4603 }
4604 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004606
4607 cur_arg = 2;
4608 while (*(args[cur_arg])) {
4609 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004610#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4611#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004612 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4613 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4614 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004615 err_code |= ERR_ALERT | ERR_FATAL;
4616 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004617 }
4618#endif
4619 if (!*args[cur_arg + 1]) {
4620 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4621 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004622 err_code |= ERR_ALERT | ERR_FATAL;
4623 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004624 }
4625
4626 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004627 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004628 curproxy->options |= PR_O_TPXY_CLI;
4629 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004630 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004631 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004632 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4633 char *name, *end;
4634
4635 name = args[cur_arg+1] + 7;
4636 while (isspace(*name))
4637 name++;
4638
4639 end = name;
4640 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4641 end++;
4642
4643 curproxy->options &= ~PR_O_TPXY_MASK;
4644 curproxy->options |= PR_O_TPXY_DYN;
4645 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4646 curproxy->bind_hdr_len = end - name;
4647 memcpy(curproxy->bind_hdr_name, name, end - name);
4648 curproxy->bind_hdr_name[end-name] = '\0';
4649 curproxy->bind_hdr_occ = -1;
4650
4651 /* now look for an occurrence number */
4652 while (isspace(*end))
4653 end++;
4654 if (*end == ',') {
4655 end++;
4656 name = end;
4657 if (*end == '-')
4658 end++;
4659 while (isdigit(*end))
4660 end++;
4661 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4662 }
4663
4664 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4665 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4666 " occurrences values smaller than %d.\n",
4667 file, linenum, MAX_HDR_HISTORY);
4668 err_code |= ERR_ALERT | ERR_FATAL;
4669 goto out;
4670 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004671 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004672 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004673 if (!sk) {
4674 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4675 err_code |= ERR_ALERT | ERR_FATAL;
4676 goto out;
4677 }
4678 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004679 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004680 }
4681 global.last_checks |= LSTCHK_NETADM;
4682#if !defined(CONFIG_HAP_LINUX_TPROXY)
4683 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004684#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004685#else /* no TPROXY support */
4686 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004687 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004688 err_code |= ERR_ALERT | ERR_FATAL;
4689 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004690#endif
4691 cur_arg += 2;
4692 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004693 }
4694
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004695 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4696#ifdef SO_BINDTODEVICE
4697 if (!*args[cur_arg + 1]) {
4698 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4699 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004700 err_code |= ERR_ALERT | ERR_FATAL;
4701 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004702 }
4703 if (curproxy->iface_name)
4704 free(curproxy->iface_name);
4705
4706 curproxy->iface_name = strdup(args[cur_arg + 1]);
4707 curproxy->iface_len = strlen(curproxy->iface_name);
4708 global.last_checks |= LSTCHK_NETADM;
4709#else
4710 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4711 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004712 err_code |= ERR_ALERT | ERR_FATAL;
4713 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004714#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004715 cur_arg += 2;
4716 continue;
4717 }
4718 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4719 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004720 err_code |= ERR_ALERT | ERR_FATAL;
4721 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004722 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004723 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004724 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4725 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4726 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004730 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004731 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004732 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4733 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004734 err_code |= ERR_ALERT | ERR_FATAL;
4735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004736 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004737
4738 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4739 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004740 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004741 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 }
4744 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004745 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4746 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004747 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004748 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 }
4751 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004752 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4753 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004754 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004755 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 }
4758 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004759 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4760 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004761 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004762 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004764 }
4765 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004766 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4767 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004768 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004769 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004772 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004773 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4774 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004775 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004776 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004777 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004778 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004779 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004780 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4781 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004782 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004783 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004784 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004785 }
4786 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004787 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4788 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004789 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004790 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004791 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004792 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004794 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004795 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4796 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004797 err_code |= ERR_ALERT | ERR_FATAL;
4798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004800
4801 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4802 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004803 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004804 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004806 }
4807 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004808 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4809 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004810 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004811 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004813 }
4814 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004815 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4816 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004817 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004818 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004820 }
4821 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004822 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4823 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004824 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004825 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004827 }
4828 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004829 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4830 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004831 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004832 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004834 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004835 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004836 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4837 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004838 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004839 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004840 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004841 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004843 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004844
Willy Tarreaubaaee002006-06-26 02:48:02 +02004845 if (curproxy == &defproxy) {
4846 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004847 err_code |= ERR_ALERT | ERR_FATAL;
4848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004849 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004850 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004851 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004852
Willy Tarreaubaaee002006-06-26 02:48:02 +02004853 if (*(args[1]) == 0) {
4854 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004855 err_code |= ERR_ALERT | ERR_FATAL;
4856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004857 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004858
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004859 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4860 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4861 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4862 file, linenum, args[0]);
4863 err_code |= ERR_ALERT | ERR_FATAL;
4864 goto out;
4865 }
4866 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4867 }
4868 else if (*args[2]) {
4869 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4870 file, linenum, args[0], args[2]);
4871 err_code |= ERR_ALERT | ERR_FATAL;
4872 goto out;
4873 }
4874
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004875 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004876 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004877 wl->s = strdup(args[1]);
4878 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004879 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004880 }
4881 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004882 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004883 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4884 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004885 err_code |= ERR_ALERT | ERR_FATAL;
4886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004887 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004888
Willy Tarreauade5ec42010-01-28 19:33:49 +01004889 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4890 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004891 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004892 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 }
4895 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004896 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4897 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004898 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004899 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004901 }
4902 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004903 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4904 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004905 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004906 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004908 }
4909 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004910 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004911 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4912 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004913 err_code |= ERR_ALERT | ERR_FATAL;
4914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004915 }
4916
Willy Tarreauade5ec42010-01-28 19:33:49 +01004917 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4918 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004919 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004920 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004922 }
4923 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004924 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4925 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004926 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004927 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929 }
4930 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004931 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4932 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004933 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004934 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004936 }
4937 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004938 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004939
Willy Tarreaubaaee002006-06-26 02:48:02 +02004940 if (curproxy == &defproxy) {
4941 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004942 err_code |= ERR_ALERT | ERR_FATAL;
4943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004945 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004946 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947
Willy Tarreaubaaee002006-06-26 02:48:02 +02004948 if (*(args[1]) == 0) {
4949 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004950 err_code |= ERR_ALERT | ERR_FATAL;
4951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
4953
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004954 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4955 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4956 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4957 file, linenum, args[0]);
4958 err_code |= ERR_ALERT | ERR_FATAL;
4959 goto out;
4960 }
4961 err_code |= warnif_cond_requires_req(cond, file, linenum);
4962 }
4963 else if (*args[2]) {
4964 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4965 file, linenum, args[0], args[2]);
4966 err_code |= ERR_ALERT | ERR_FATAL;
4967 goto out;
4968 }
4969
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004970 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004971 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004972 wl->s = strdup(args[1]);
4973 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 }
4975 else if (!strcmp(args[0], "errorloc") ||
4976 !strcmp(args[0], "errorloc302") ||
4977 !strcmp(args[0], "errorloc303")) { /* error location */
4978 int errnum, errlen;
4979 char *err;
4980
Willy Tarreau977b8e42006-12-29 14:19:17 +01004981 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004982 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004983
Willy Tarreaubaaee002006-06-26 02:48:02 +02004984 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004985 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 }
4989
4990 errnum = atol(args[1]);
4991 if (!strcmp(args[0], "errorloc303")) {
4992 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4993 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4994 } else {
4995 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4996 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4997 }
4998
Willy Tarreau0f772532006-12-23 20:51:41 +01004999 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5000 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005001 chunk_destroy(&curproxy->errmsg[rc]);
5002 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005003 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005005 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005006
5007 if (rc >= HTTP_ERR_SIZE) {
5008 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5009 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 free(err);
5011 }
5012 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005013 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5014 int errnum, errlen, fd;
5015 char *err;
5016 struct stat stat;
5017
5018 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005019 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005020
5021 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005022 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005023 err_code |= ERR_ALERT | ERR_FATAL;
5024 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005025 }
5026
5027 fd = open(args[2], O_RDONLY);
5028 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5029 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5030 file, linenum, args[2], args[1]);
5031 if (fd >= 0)
5032 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005033 err_code |= ERR_ALERT | ERR_FATAL;
5034 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005035 }
5036
Willy Tarreau27a674e2009-08-17 07:23:33 +02005037 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005038 errlen = stat.st_size;
5039 } else {
5040 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005041 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005042 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005043 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005044 }
5045
5046 err = malloc(errlen); /* malloc() must succeed during parsing */
5047 errnum = read(fd, err, errlen);
5048 if (errnum != errlen) {
5049 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5050 file, linenum, args[2], args[1]);
5051 close(fd);
5052 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005053 err_code |= ERR_ALERT | ERR_FATAL;
5054 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005055 }
5056 close(fd);
5057
5058 errnum = atol(args[1]);
5059 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5060 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005061 chunk_destroy(&curproxy->errmsg[rc]);
5062 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005063 break;
5064 }
5065 }
5066
5067 if (rc >= HTTP_ERR_SIZE) {
5068 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5069 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005070 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005071 free(err);
5072 }
5073 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005074 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005075 struct cfg_kw_list *kwl;
5076 int index;
5077
5078 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5079 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5080 if (kwl->kw[index].section != CFG_LISTEN)
5081 continue;
5082 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5083 /* prepare error message just in case */
5084 snprintf(trash, sizeof(trash),
5085 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005086 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5087 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005088 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005089 err_code |= ERR_ALERT | ERR_FATAL;
5090 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005091 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005092 else if (rc > 0) {
5093 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005094 err_code |= ERR_WARN;
5095 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005096 }
Willy Tarreau93893792009-07-23 13:19:11 +02005097 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005098 }
5099 }
5100 }
5101
Willy Tarreau6daf3432008-01-22 16:44:08 +01005102 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005103 err_code |= ERR_ALERT | ERR_FATAL;
5104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005105 }
Willy Tarreau93893792009-07-23 13:19:11 +02005106 out:
5107 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005108}
5109
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005110int
5111cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5112{
5113
5114 int err_code = 0;
5115 const char *err;
5116
5117 if (!strcmp(args[0], "userlist")) { /* new userlist */
5118 struct userlist *newul;
5119
5120 if (!*args[1]) {
5121 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5122 file, linenum, args[0]);
5123 err_code |= ERR_ALERT | ERR_FATAL;
5124 goto out;
5125 }
5126
5127 err = invalid_char(args[1]);
5128 if (err) {
5129 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5130 file, linenum, *err, args[0], args[1]);
5131 err_code |= ERR_ALERT | ERR_FATAL;
5132 goto out;
5133 }
5134
5135 for (newul = userlist; newul; newul = newul->next)
5136 if (!strcmp(newul->name, args[1])) {
5137 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5138 file, linenum, args[1]);
5139 err_code |= ERR_WARN;
5140 goto out;
5141 }
5142
5143 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5144 if (!newul) {
5145 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5146 err_code |= ERR_ALERT | ERR_ABORT;
5147 goto out;
5148 }
5149
5150 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5151 newul->name = strdup(args[1]);
5152
5153 if (!newul->groupusers | !newul->name) {
5154 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5155 err_code |= ERR_ALERT | ERR_ABORT;
5156 goto out;
5157 }
5158
5159 newul->next = userlist;
5160 userlist = newul;
5161
5162 } else if (!strcmp(args[0], "group")) { /* new group */
5163 int cur_arg, i;
5164 const char *err;
5165
5166 if (!*args[1]) {
5167 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5168 file, linenum, args[0]);
5169 err_code |= ERR_ALERT | ERR_FATAL;
5170 goto out;
5171 }
5172
5173 err = invalid_char(args[1]);
5174 if (err) {
5175 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5176 file, linenum, *err, args[0], args[1]);
5177 err_code |= ERR_ALERT | ERR_FATAL;
5178 goto out;
5179 }
5180
5181 for(i = 0; i < userlist->grpcnt; i++)
5182 if (!strcmp(userlist->groups[i], args[1])) {
5183 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5184 file, linenum, args[1], userlist->name);
5185 err_code |= ERR_ALERT;
5186 goto out;
5187 }
5188
5189 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5190 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5191 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5192 err_code |= ERR_ALERT | ERR_FATAL;
5193 goto out;
5194 }
5195
5196 cur_arg = 2;
5197
5198 while (*args[cur_arg]) {
5199 if (!strcmp(args[cur_arg], "users")) {
5200 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5201 cur_arg += 2;
5202 continue;
5203 } else {
5204 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5205 file, linenum, args[0]);
5206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
5208 }
5209 }
5210
5211 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5212 } else if (!strcmp(args[0], "user")) { /* new user */
5213 struct auth_users *newuser;
5214 int cur_arg;
5215
5216 if (!*args[1]) {
5217 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5218 file, linenum, args[0]);
5219 err_code |= ERR_ALERT | ERR_FATAL;
5220 goto out;
5221 }
5222
5223 for (newuser = userlist->users; newuser; newuser = newuser->next)
5224 if (!strcmp(newuser->user, args[1])) {
5225 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5226 file, linenum, args[1], userlist->name);
5227 err_code |= ERR_ALERT;
5228 goto out;
5229 }
5230
5231 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5232 if (!newuser) {
5233 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5234 err_code |= ERR_ALERT | ERR_ABORT;
5235 goto out;
5236 }
5237
5238 newuser->user = strdup(args[1]);
5239
5240 newuser->next = userlist->users;
5241 userlist->users = newuser;
5242
5243 cur_arg = 2;
5244
5245 while (*args[cur_arg]) {
5246 if (!strcmp(args[cur_arg], "password")) {
5247#ifndef CONFIG_HAP_CRYPT
5248 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5249 file, linenum);
5250 err_code |= ERR_ALERT;
5251#endif
5252 newuser->pass = strdup(args[cur_arg + 1]);
5253 cur_arg += 2;
5254 continue;
5255 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5256 newuser->pass = strdup(args[cur_arg + 1]);
5257 newuser->flags |= AU_O_INSECURE;
5258 cur_arg += 2;
5259 continue;
5260 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005261 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005262 cur_arg += 2;
5263 continue;
5264 } else {
5265 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5266 file, linenum, args[0]);
5267 err_code |= ERR_ALERT | ERR_FATAL;
5268 goto out;
5269 }
5270 }
5271 } else {
5272 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5273 err_code |= ERR_ALERT | ERR_FATAL;
5274 }
5275
5276out:
5277 return err_code;
5278}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279
5280/*
5281 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005282 * Returns the error code, 0 if OK, or any combination of :
5283 * - ERR_ABORT: must abort ASAP
5284 * - ERR_FATAL: we can continue parsing but not start the service
5285 * - ERR_WARN: a warning has been emitted
5286 * - ERR_ALERT: an alert has been emitted
5287 * Only the two first ones can stop processing, the two others are just
5288 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005290int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005292 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005293 FILE *f;
5294 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005296 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005297
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298 if ((f=fopen(file,"r")) == NULL)
5299 return -1;
5300
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005301 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005302 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005303 char *end;
5304 char *args[MAX_LINE_ARGS + 1];
5305 char *line = thisline;
5306
Willy Tarreaubaaee002006-06-26 02:48:02 +02005307 linenum++;
5308
5309 end = line + strlen(line);
5310
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005311 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5312 /* Check if we reached the limit and the last char is not \n.
5313 * Watch out for the last line without the terminating '\n'!
5314 */
5315 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005316 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005317 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005318 }
5319
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005321 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005322 line++;
5323
5324 arg = 0;
5325 args[arg] = line;
5326
5327 while (*line && arg < MAX_LINE_ARGS) {
5328 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5329 * C equivalent value. Other combinations left unchanged (eg: \1).
5330 */
5331 if (*line == '\\') {
5332 int skip = 0;
5333 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5334 *line = line[1];
5335 skip = 1;
5336 }
5337 else if (line[1] == 'r') {
5338 *line = '\r';
5339 skip = 1;
5340 }
5341 else if (line[1] == 'n') {
5342 *line = '\n';
5343 skip = 1;
5344 }
5345 else if (line[1] == 't') {
5346 *line = '\t';
5347 skip = 1;
5348 }
5349 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005350 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005351 unsigned char hex1, hex2;
5352 hex1 = toupper(line[2]) - '0';
5353 hex2 = toupper(line[3]) - '0';
5354 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5355 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5356 *line = (hex1<<4) + hex2;
5357 skip = 3;
5358 }
5359 else {
5360 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005361 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005362 }
5363 }
5364 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005365 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005366 end -= skip;
5367 }
5368 line++;
5369 }
5370 else if (*line == '#' || *line == '\n' || *line == '\r') {
5371 /* end of string, end of loop */
5372 *line = 0;
5373 break;
5374 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005375 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005377 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005378 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005379 line++;
5380 args[++arg] = line;
5381 }
5382 else {
5383 line++;
5384 }
5385 }
5386
5387 /* empty line */
5388 if (!**args)
5389 continue;
5390
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005391 if (*line) {
5392 /* we had to stop due to too many args.
5393 * Let's terminate the string, print the offending part then cut the
5394 * last arg.
5395 */
5396 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5397 line++;
5398 *line = '\0';
5399
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005400 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005401 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005402 err_code |= ERR_ALERT | ERR_FATAL;
5403 args[arg] = line;
5404 }
5405
Willy Tarreau540abe42007-05-02 20:50:16 +02005406 /* zero out remaining args and ensure that at least one entry
5407 * is zeroed out.
5408 */
5409 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005410 args[arg] = line;
5411 }
5412
Willy Tarreau3842f002009-06-14 11:39:52 +02005413 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005414 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005415 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005416 for (arg=0; *args[arg+1]; arg++)
5417 args[arg] = args[arg+1]; // shift args after inversion
5418 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005419 else if (!strcmp(args[0], "default")) {
5420 kwm = KWM_DEF;
5421 for (arg=0; *args[arg+1]; arg++)
5422 args[arg] = args[arg+1]; // shift args after inversion
5423 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005424
Willy Tarreau3842f002009-06-14 11:39:52 +02005425 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5426 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005427 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005428 }
5429
Willy Tarreau977b8e42006-12-29 14:19:17 +01005430 if (!strcmp(args[0], "listen") ||
5431 !strcmp(args[0], "frontend") ||
5432 !strcmp(args[0], "backend") ||
5433 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005434 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005435 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005436 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005437 cursection = strdup(args[0]);
5438 }
5439 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005440 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005441 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005442 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005443 }
5444 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005445 confsect = CFG_USERLIST;
5446 free(cursection);
5447 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005448 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005449 else if (!strcmp(args[0], "peers")) {
5450 confsect = CFG_PEERS;
5451 free(cursection);
5452 cursection = strdup(args[0]);
5453 }
5454
Willy Tarreaubaaee002006-06-26 02:48:02 +02005455 /* else it's a section keyword */
5456
5457 switch (confsect) {
5458 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005459 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005460 break;
5461 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005462 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005463 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005464 case CFG_USERLIST:
5465 err_code |= cfg_parse_users(file, linenum, args, kwm);
5466 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005467 case CFG_PEERS:
5468 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5469 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005470 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005471 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005472 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005473 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005474
5475 if (err_code & ERR_ABORT)
5476 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005477 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005478 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005479 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005480 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005481 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005482}
5483
Willy Tarreaubb925012009-07-23 13:36:36 +02005484/*
5485 * Returns the error code, 0 if OK, or any combination of :
5486 * - ERR_ABORT: must abort ASAP
5487 * - ERR_FATAL: we can continue parsing but not start the service
5488 * - ERR_WARN: a warning has been emitted
5489 * - ERR_ALERT: an alert has been emitted
5490 * Only the two first ones can stop processing, the two others are just
5491 * indicators.
5492 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005493int check_config_validity()
5494{
5495 int cfgerr = 0;
5496 struct proxy *curproxy = NULL;
5497 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005498 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005499 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005500 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005501
5502 /*
5503 * Now, check for the integrity of all that we have collected.
5504 */
5505
5506 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005507 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005508
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005509 /* first, we will invert the proxy list order */
5510 curproxy = NULL;
5511 while (proxy) {
5512 struct proxy *next;
5513
5514 next = proxy->next;
5515 proxy->next = curproxy;
5516 curproxy = proxy;
5517 if (!next)
5518 break;
5519 proxy = next;
5520 }
5521
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005523 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005524 err_code |= ERR_ALERT | ERR_FATAL;
5525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005526 }
5527
5528 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005529 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005530 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005531 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005532 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005533 unsigned int next_id;
5534
5535 if (!curproxy->uuid) {
5536 /* proxy ID not set, use automatic numbering with first
5537 * spare entry starting with next_pxid.
5538 */
5539 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5540 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5541 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005542 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005543 next_pxid++;
5544
Willy Tarreau55ea7572007-06-17 19:56:27 +02005545
Willy Tarreaubaaee002006-06-26 02:48:02 +02005546 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005547 /* ensure we don't keep listeners uselessly bound */
5548 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005549 curproxy = curproxy->next;
5550 continue;
5551 }
5552
Willy Tarreauff01a212009-03-15 13:46:16 +01005553 switch (curproxy->mode) {
5554 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005555 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005556 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005557 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5558 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005559 cfgerr++;
5560 }
5561
5562 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005563 Warning("config : servers will be ignored for %s '%s'.\n",
5564 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005565 break;
5566
5567 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005568 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005569 break;
5570
5571 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005572 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005573 break;
5574 }
5575
5576 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005577 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5578 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005579 cfgerr++;
5580 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005581
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005582 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005583 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005584 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005585 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5586 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005587 cfgerr++;
5588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005589#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005590 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005591 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5592 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005593 cfgerr++;
5594 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005595#endif
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005596 else if (curproxy->options2 & PR_O2_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005597 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5598 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005599 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005600 }
5601 }
5602 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005603 !(curproxy->options2 & PR_O2_DISPATCH)) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005604 /* If no LB algo is set in a backend, and we're not in
5605 * transparent mode, dispatch mode nor proxy mode, we
5606 * want to use balance roundrobin by default.
5607 */
5608 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5609 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610 }
5611 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005612
Willy Tarreaud6cc5322011-03-04 17:30:54 +01005613 if (curproxy->options2 & PR_O2_DISPATCH) {
5614 curproxy->options &= ~PR_O_TRANSP;
5615 curproxy->options &= ~PR_O_HTTP_PROXY;
5616 }
5617 else if (curproxy->options & PR_O_HTTP_PROXY) {
5618 curproxy->options2 &= ~PR_O2_DISPATCH;
5619 curproxy->options &= ~PR_O_TRANSP;
5620 }
5621 else if (curproxy->options & PR_O_TRANSP) {
5622 curproxy->options2 &= ~PR_O2_DISPATCH;
5623 curproxy->options &= ~PR_O_HTTP_PROXY;
5624 }
5625
Willy Tarreau82936582007-11-30 15:20:09 +01005626 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5627 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005628 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5629 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005630 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005631 }
5632
Willy Tarreauef781042010-01-27 11:53:01 +01005633 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5634 curproxy->options &= ~PR_O2_CHK_SNDST;
5635 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5636 "send-state", proxy_type_str(curproxy), curproxy->id);
5637 err_code |= ERR_WARN;
5638 }
5639
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005640 /* if a default backend was specified, let's find it */
5641 if (curproxy->defbe.name) {
5642 struct proxy *target;
5643
Alex Williams96532db2009-11-01 21:27:13 -05005644 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005645 if (!target) {
5646 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5647 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005648 cfgerr++;
5649 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005650 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5651 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005652 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005653 } else {
5654 free(curproxy->defbe.name);
5655 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005656 /* we force the backend to be present on at least all of
5657 * the frontend's processes.
5658 */
5659 target->bind_proc = curproxy->bind_proc ?
5660 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005661 }
5662 }
5663
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005664 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005665 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5666 /* map jump target for ACT_SETBE in req_rep chain */
5667 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005668 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005669 struct proxy *target;
5670
Willy Tarreaua496b602006-12-17 23:15:24 +01005671 if (exp->action != ACT_SETBE)
5672 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005673
Alex Williams96532db2009-11-01 21:27:13 -05005674 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005675 if (!target) {
5676 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5677 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005678 cfgerr++;
5679 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005680 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5681 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005682 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005683 } else {
5684 free((void *)exp->replace);
5685 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005686 /* we force the backend to be present on at least all of
5687 * the frontend's processes.
5688 */
5689 target->bind_proc = curproxy->bind_proc ?
5690 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005691 }
5692 }
5693 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005694
5695 /* find the target proxy for 'use_backend' rules */
5696 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005697 struct proxy *target;
5698
Alex Williams96532db2009-11-01 21:27:13 -05005699 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005700
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005701 if (!target) {
5702 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5703 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005704 cfgerr++;
5705 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005706 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5707 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005708 cfgerr++;
5709 } else {
5710 free((void *)rule->be.name);
5711 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005712 /* we force the backend to be present on at least all of
5713 * the frontend's processes.
5714 */
5715 target->bind_proc = curproxy->bind_proc ?
5716 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005717 }
5718 }
5719
Emeric Brunb982a3d2010-01-04 15:45:53 +01005720 /* find the target table for 'stick' rules */
5721 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5722 struct proxy *target;
5723
Emeric Brun1d33b292010-01-04 15:47:17 +01005724 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5725 if (mrule->flags & STK_IS_STORE)
5726 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5727
Emeric Brunb982a3d2010-01-04 15:45:53 +01005728 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005729 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005730 else
5731 target = curproxy;
5732
5733 if (!target) {
5734 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5735 curproxy->id, mrule->table.name);
5736 cfgerr++;
5737 }
5738 else if (target->table.size == 0) {
5739 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5740 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5741 cfgerr++;
5742 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005743 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005744 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5745 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5746 cfgerr++;
5747 }
5748 else {
5749 free((void *)mrule->table.name);
5750 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005751 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005752 }
5753 }
5754
5755 /* find the target table for 'store response' rules */
5756 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5757 struct proxy *target;
5758
Emeric Brun1d33b292010-01-04 15:47:17 +01005759 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5760
Emeric Brunb982a3d2010-01-04 15:45:53 +01005761 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005762 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005763 else
5764 target = curproxy;
5765
5766 if (!target) {
5767 Alert("Proxy '%s': unable to find store table '%s'.\n",
5768 curproxy->id, mrule->table.name);
5769 cfgerr++;
5770 }
5771 else if (target->table.size == 0) {
5772 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5773 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5774 cfgerr++;
5775 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005776 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005777 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5778 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5779 cfgerr++;
5780 }
5781 else {
5782 free((void *)mrule->table.name);
5783 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005784 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005785 }
5786 }
5787
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005788 /* find the target table for 'tcp-request' layer 4 rules */
5789 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5790 struct proxy *target;
5791
Willy Tarreau56123282010-08-06 19:06:56 +02005792 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005793 continue;
5794
5795 if (trule->act_prm.trk_ctr.table.n)
5796 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5797 else
5798 target = curproxy;
5799
5800 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005801 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5802 curproxy->id, trule->act_prm.trk_ctr.table.n,
5803 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005804 cfgerr++;
5805 }
5806 else if (target->table.size == 0) {
5807 Alert("Proxy '%s': table '%s' used but not configured.\n",
5808 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5809 cfgerr++;
5810 }
5811 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005812 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 +02005813 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5814 cfgerr++;
5815 }
5816 else {
5817 free(trule->act_prm.trk_ctr.table.n);
5818 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005819 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005820 * to pass a list of counters to track and allocate them right here using
5821 * stktable_alloc_data_type().
5822 */
5823 }
5824 }
5825
Willy Tarreaud1f96522010-08-03 19:34:32 +02005826 /* find the target table for 'tcp-request' layer 6 rules */
5827 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5828 struct proxy *target;
5829
Willy Tarreau56123282010-08-06 19:06:56 +02005830 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005831 continue;
5832
5833 if (trule->act_prm.trk_ctr.table.n)
5834 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5835 else
5836 target = curproxy;
5837
5838 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005839 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5840 curproxy->id, trule->act_prm.trk_ctr.table.n,
5841 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005842 cfgerr++;
5843 }
5844 else if (target->table.size == 0) {
5845 Alert("Proxy '%s': table '%s' used but not configured.\n",
5846 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5847 cfgerr++;
5848 }
5849 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005850 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 +02005851 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5852 cfgerr++;
5853 }
5854 else {
5855 free(trule->act_prm.trk_ctr.table.n);
5856 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005857 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005858 * to pass a list of counters to track and allocate them right here using
5859 * stktable_alloc_data_type().
5860 */
5861 }
5862 }
5863
Emeric Brun32da3c42010-09-23 18:39:19 +02005864 if (curproxy->table.peers.name) {
5865 struct peers *curpeers = peers;
5866
5867 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5868 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5869 free((void *)curproxy->table.peers.name);
5870 curproxy->table.peers.p = peers;
5871 break;
5872 }
5873 }
5874
5875 if (!curpeers) {
5876 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5877 curproxy->id, curproxy->table.peers.name);
5878 cfgerr++;
5879 }
5880 else if (!curpeers->peers_fe) {
5881 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5882 curproxy->id, curpeers->id);
5883 cfgerr++;
5884 }
5885 }
5886
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005887 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005888 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005889 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5890 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5891 "proxy", curproxy->id);
5892 cfgerr++;
5893 goto out_uri_auth_compat;
5894 }
5895
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005896 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005897 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005898 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005899 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005900
Willy Tarreau95fa4692010-02-01 13:05:50 +01005901 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5902 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005903
5904 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005905 uri_auth_compat_req[i++] = "realm";
5906 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5907 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005908
Willy Tarreau95fa4692010-02-01 13:05:50 +01005909 uri_auth_compat_req[i++] = "unless";
5910 uri_auth_compat_req[i++] = "{";
5911 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5912 uri_auth_compat_req[i++] = "}";
5913 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005914
Willy Tarreauff011f22011-01-06 17:51:27 +01005915 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5916 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005917 cfgerr++;
5918 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005919 }
5920
Willy Tarreauff011f22011-01-06 17:51:27 +01005921 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005922
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005923 if (curproxy->uri_auth->auth_realm) {
5924 free(curproxy->uri_auth->auth_realm);
5925 curproxy->uri_auth->auth_realm = NULL;
5926 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005927
5928 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005929 }
5930out_uri_auth_compat:
5931
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005932 cfgerr += acl_find_targets(curproxy);
5933
Willy Tarreau2738a142006-07-08 17:28:09 +02005934 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005935 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005936 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005937 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005938 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005939 " | While not properly invalid, you will certainly encounter various problems\n"
5940 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005941 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005942 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005943 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005944 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005945
Willy Tarreau1fa31262007-12-03 00:36:16 +01005946 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5947 * We must still support older configurations, so let's find out whether those
5948 * parameters have been set or must be copied from contimeouts.
5949 */
5950 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005951 if (!curproxy->timeout.tarpit ||
5952 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005953 /* tarpit timeout not set. We search in the following order:
5954 * default.tarpit, curr.connect, default.connect.
5955 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005956 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005957 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005958 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005959 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005960 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005961 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005962 }
5963 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005964 (!curproxy->timeout.queue ||
5965 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005966 /* queue timeout not set. We search in the following order:
5967 * default.queue, curr.connect, default.connect.
5968 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005969 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005970 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005971 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005972 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005973 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005974 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005975 }
5976 }
5977
Willy Tarreau07a54902010-03-29 18:33:29 +02005978 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005979 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5980 curproxy->check_req = (char *)malloc(curproxy->check_len);
5981 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005982 }
5983
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005984 /* The small pools required for the capture lists */
5985 if (curproxy->nb_req_cap)
5986 curproxy->req_cap_pool = create_pool("ptrcap",
5987 curproxy->nb_req_cap * sizeof(char *),
5988 MEM_F_SHARED);
5989 if (curproxy->nb_rsp_cap)
5990 curproxy->rsp_cap_pool = create_pool("ptrcap",
5991 curproxy->nb_rsp_cap * sizeof(char *),
5992 MEM_F_SHARED);
5993
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005994 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5995 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5996 MEM_F_SHARED);
5997
Willy Tarreaubaaee002006-06-26 02:48:02 +02005998 /* first, we will invert the servers list order */
5999 newsrv = NULL;
6000 while (curproxy->srv) {
6001 struct server *next;
6002
6003 next = curproxy->srv->next;
6004 curproxy->srv->next = newsrv;
6005 newsrv = curproxy->srv;
6006 if (!next)
6007 break;
6008 curproxy->srv = next;
6009 }
6010
Willy Tarreaudd701652010-05-25 23:03:02 +02006011 /* assign automatic UIDs to servers which don't have one yet */
6012 next_id = 1;
6013 newsrv = curproxy->srv;
6014 while (newsrv != NULL) {
6015 if (!newsrv->puid) {
6016 /* server ID not set, use automatic numbering with first
6017 * spare entry starting with next_svid.
6018 */
6019 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6020 newsrv->conf.id.key = newsrv->puid = next_id;
6021 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6022 }
6023 next_id++;
6024 newsrv = newsrv->next;
6025 }
6026
Willy Tarreau20697042007-11-15 23:26:18 +01006027 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006028 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006029
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006030 /* We have to initialize the server lookup mechanism depending
6031 * on what LB algorithm was choosen.
6032 */
6033
6034 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6035 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6036 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006037 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6038 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6039 init_server_map(curproxy);
6040 } else {
6041 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6042 fwrr_init_server_groups(curproxy);
6043 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006044 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006045
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006046 case BE_LB_KIND_LC:
6047 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006048 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006049 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006050
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006051 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006052 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6053 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6054 chash_init_server_tree(curproxy);
6055 } else {
6056 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6057 init_server_map(curproxy);
6058 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006059 break;
6060 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006061
6062 if (curproxy->options & PR_O_LOGASAP)
6063 curproxy->to_log &= ~LW_BYTES;
6064
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006065 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6066 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6067 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6068 proxy_type_str(curproxy), curproxy->id);
6069 err_code |= ERR_WARN;
6070 }
6071
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006072 if (curproxy->mode != PR_MODE_HTTP) {
6073 int optnum;
6074
6075 if (curproxy->options & PR_O_COOK_ANY) {
6076 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6077 proxy_type_str(curproxy), curproxy->id);
6078 err_code |= ERR_WARN;
6079 }
6080
6081 if (curproxy->uri_auth) {
6082 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6083 proxy_type_str(curproxy), curproxy->id);
6084 err_code |= ERR_WARN;
6085 curproxy->uri_auth = NULL;
6086 }
6087
6088 if (curproxy->options & PR_O_FWDFOR) {
6089 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6090 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6091 err_code |= ERR_WARN;
6092 curproxy->options &= ~PR_O_FWDFOR;
6093 }
6094
6095 if (curproxy->options & PR_O_ORGTO) {
6096 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6097 "originalto", proxy_type_str(curproxy), curproxy->id);
6098 err_code |= ERR_WARN;
6099 curproxy->options &= ~PR_O_ORGTO;
6100 }
6101
6102 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6103 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6104 (curproxy->cap & cfg_opts[optnum].cap) &&
6105 (curproxy->options & cfg_opts[optnum].val)) {
6106 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6107 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6108 err_code |= ERR_WARN;
6109 curproxy->options &= ~cfg_opts[optnum].val;
6110 }
6111 }
6112
6113 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6114 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6115 (curproxy->cap & cfg_opts2[optnum].cap) &&
6116 (curproxy->options2 & cfg_opts2[optnum].val)) {
6117 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6118 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6119 err_code |= ERR_WARN;
6120 curproxy->options2 &= ~cfg_opts2[optnum].val;
6121 }
6122 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006123
Willy Tarreauefa5f512010-03-30 20:13:29 +02006124#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006125 if (curproxy->bind_hdr_occ) {
6126 curproxy->bind_hdr_occ = 0;
6127 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6128 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6129 err_code |= ERR_WARN;
6130 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006131#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006132 }
6133
Willy Tarreaubaaee002006-06-26 02:48:02 +02006134 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006135 * ensure that we're not cross-dressing a TCP server into HTTP.
6136 */
6137 newsrv = curproxy->srv;
6138 while (newsrv != NULL) {
6139 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006140 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6141 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006142 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006143 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006144
Willy Tarreauefa5f512010-03-30 20:13:29 +02006145#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006146 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6147 newsrv->bind_hdr_occ = 0;
6148 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6149 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6150 err_code |= ERR_WARN;
6151 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006152#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006153 newsrv = newsrv->next;
6154 }
6155
6156 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006157 * If this server supports a maxconn parameter, it needs a dedicated
6158 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006159 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006160 */
6161 newsrv = curproxy->srv;
6162 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006163 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006164 /* Only 'minconn' was specified, or it was higher than or equal
6165 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6166 * this will avoid further useless expensive computations.
6167 */
6168 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006169 } else if (newsrv->maxconn && !newsrv->minconn) {
6170 /* minconn was not specified, so we set it to maxconn */
6171 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006172 }
6173
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006174 if (newsrv->trackit) {
6175 struct proxy *px;
6176 struct server *srv;
6177 char *pname, *sname;
6178
6179 pname = newsrv->trackit;
6180 sname = strrchr(pname, '/');
6181
6182 if (sname)
6183 *sname++ = '\0';
6184 else {
6185 sname = pname;
6186 pname = NULL;
6187 }
6188
6189 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006190 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006191 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006192 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6193 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006194 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006195 cfgerr++;
6196 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006197 }
6198 } else
6199 px = curproxy;
6200
6201 srv = findserver(px, sname);
6202 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006203 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6204 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006205 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006206 cfgerr++;
6207 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006208 }
6209
6210 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006211 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006212 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006213 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006214 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006215 cfgerr++;
6216 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006217 }
6218
6219 if (curproxy != px &&
6220 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006221 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006222 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006223 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006224 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006225 cfgerr++;
6226 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006227 }
6228
6229 newsrv->tracked = srv;
6230 newsrv->tracknext = srv->tracknext;
6231 srv->tracknext = newsrv;
6232
6233 free(newsrv->trackit);
6234 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006235 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006236 newsrv = newsrv->next;
6237 }
6238
Willy Tarreauc1a21672009-08-16 22:37:44 +02006239 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006240 curproxy->accept = frontend_accept;
6241
Willy Tarreauc1a21672009-08-16 22:37:44 +02006242 if (curproxy->tcp_req.inspect_delay ||
6243 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006244 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006245
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006246 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006247 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006248 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006249 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006250
6251 /* both TCP and HTTP must check switching rules */
6252 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6253 }
6254
6255 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006256 if (curproxy->tcp_req.inspect_delay ||
6257 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6258 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6259
Emeric Brun97679e72010-09-23 17:56:44 +02006260 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6261 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6262
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006263 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006264 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006265 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006266 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006267
6268 /* If the backend does requires RDP cookie persistence, we have to
6269 * enable the corresponding analyser.
6270 */
6271 if (curproxy->options2 & PR_O2_RDPC_PRST)
6272 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6273 }
6274
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006275 listener = NULL;
6276 while (curproxy->listen) {
6277 struct listener *next;
6278
6279 next = curproxy->listen->next;
6280 curproxy->listen->next = listener;
6281 listener = curproxy->listen;
6282
6283 if (!next)
6284 break;
6285
6286 curproxy->listen = next;
6287 }
6288
Willy Tarreaue6b98942007-10-29 01:09:36 +01006289 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006290 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006291 listener = curproxy->listen;
6292 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006293 if (!listener->luid) {
6294 /* listener ID not set, use automatic numbering with first
6295 * spare entry starting with next_luid.
6296 */
6297 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6298 listener->conf.id.key = listener->luid = next_id;
6299 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006300 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006301 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006302
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006303 /* enable separate counters */
6304 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6305 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6306 if (!listener->name) {
6307 sprintf(trash, "sock-%d", listener->luid);
6308 listener->name = strdup(trash);
6309 }
6310 }
6311
Willy Tarreaue6b98942007-10-29 01:09:36 +01006312 if (curproxy->options & PR_O_TCP_NOLING)
6313 listener->options |= LI_O_NOLINGER;
6314 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006315 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006316 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006317 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006318 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006319 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006320 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006321
Willy Tarreau8a956912010-10-15 14:27:08 +02006322 if (listener->options & LI_O_ACC_PROXY)
6323 listener->analysers |= AN_REQ_DECODE_PROXY;
6324
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006325 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6326 listener->options |= LI_O_TCP_RULES;
6327
Willy Tarreaude3041d2010-05-31 10:56:17 +02006328 if (curproxy->mon_mask.s_addr)
6329 listener->options |= LI_O_CHK_MONNET;
6330
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006331 /* smart accept mode is automatic in HTTP mode */
6332 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6333 (curproxy->mode == PR_MODE_HTTP &&
6334 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6335 listener->options |= LI_O_NOQUICKACK;
6336
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006337 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006338 listener = listener->next;
6339 }
6340
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006341 /* Check multi-process mode compatibility for the current proxy */
6342 if (global.nbproc > 1) {
6343 int nbproc = 0;
6344 if (curproxy->bind_proc) {
6345 int proc;
6346 for (proc = 0; proc < global.nbproc; proc++) {
6347 if (curproxy->bind_proc & (1 << proc)) {
6348 nbproc++;
6349 }
6350 }
6351 } else {
6352 nbproc = global.nbproc;
6353 }
6354 if (curproxy->table.peers.name) {
6355 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6356 curproxy->id);
6357 cfgerr++;
6358 }
6359 if (nbproc > 1) {
6360 if (curproxy->uri_auth) {
6361 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6362 curproxy->id);
6363 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6364 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6365 curproxy->id);
6366 }
6367 }
6368 if (curproxy->appsession_name) {
6369 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6370 curproxy->id);
6371 }
6372 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6373 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6374 curproxy->id);
6375 }
6376 }
6377 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006378
6379 /* create the task associated with the proxy */
6380 curproxy->task = task_new();
6381 if (curproxy->task) {
6382 curproxy->task->context = curproxy;
6383 curproxy->task->process = manage_proxy;
6384 /* no need to queue, it will be done automatically if some
6385 * listener gets limited.
6386 */
6387 curproxy->task->expire = TICK_ETERNITY;
6388 } else {
6389 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6390 curproxy->id);
6391 cfgerr++;
6392 }
6393
Willy Tarreaubaaee002006-06-26 02:48:02 +02006394 curproxy = curproxy->next;
6395 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006396
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006397 /* Check multi-process mode compatibility */
6398 if (global.nbproc > 1) {
6399 if (global.stats_fe) {
6400 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6401 }
6402 }
6403
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006404 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6405 struct auth_users *curuser;
6406 int g;
6407
6408 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6409 unsigned int group_mask = 0;
6410 char *group = NULL;
6411
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006412 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006413 continue;
6414
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006415 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006416
6417 for (g = 0; g < curuserlist->grpcnt; g++)
6418 if (!strcmp(curuserlist->groups[g], group))
6419 break;
6420
6421 if (g == curuserlist->grpcnt) {
6422 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6423 curuserlist->name, group, curuser->user);
6424 err_code |= ERR_ALERT | ERR_FATAL;
6425 goto out;
6426 }
6427
6428 group_mask |= (1 << g);
6429 }
6430
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006431 free(curuser->u.groups);
6432 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006433 }
6434
6435 for (g = 0; g < curuserlist->grpcnt; g++) {
6436 char *user = NULL;
6437
6438 if (!curuserlist->groupusers[g])
6439 continue;
6440
6441 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6442 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6443 if (!strcmp(curuser->user, user))
6444 break;
6445
6446 if (!curuser) {
6447 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6448 curuserlist->name, user, curuserlist->groups[g]);
6449 err_code |= ERR_ALERT | ERR_FATAL;
6450 goto out;
6451 }
6452
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006453 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006454 }
6455
6456 free(curuserlist->groupusers[g]);
6457 }
6458
6459 free(curuserlist->groupusers);
6460
6461#ifdef DEBUG_AUTH
6462 for (g = 0; g < curuserlist->grpcnt; g++) {
6463 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6464
6465 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6466 if (curuser->group_mask & (1 << g))
6467 fprintf(stderr, " %s", curuser->user);
6468 }
6469
6470 fprintf(stderr, "\n");
6471 }
6472#endif
6473
Willy Tarreaufbb78422011-06-05 15:38:35 +02006474 }
6475
6476 /* automatically compute fullconn if not set. We must not do it in the
6477 * loop above because cross-references are not yet fully resolved.
6478 */
6479 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6480 /* If <fullconn> is not set, let's set it to 10% of the sum of
6481 * the possible incoming frontend's maxconns.
6482 */
6483 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6484 struct proxy *fe;
6485 int total = 0;
6486
6487 /* sum up the number of maxconns of frontends which
6488 * reference this backend at least once or which are
6489 * the same one ('listen').
6490 */
6491 for (fe = proxy; fe; fe = fe->next) {
6492 struct switching_rule *rule;
6493 struct hdr_exp *exp;
6494 int found = 0;
6495
6496 if (!(fe->cap & PR_CAP_FE))
6497 continue;
6498
6499 if (fe == curproxy) /* we're on a "listen" instance */
6500 found = 1;
6501
6502 if (fe->defbe.be == curproxy) /* "default_backend" */
6503 found = 1;
6504
6505 /* check if a "use_backend" rule matches */
6506 if (!found) {
6507 list_for_each_entry(rule, &fe->switching_rules, list) {
6508 if (rule->be.backend == curproxy) {
6509 found = 1;
6510 break;
6511 }
6512 }
6513 }
6514
6515 /* check if a "reqsetbe" rule matches */
6516 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6517 if (exp->action == ACT_SETBE &&
6518 (struct proxy *)exp->replace == curproxy) {
6519 found = 1;
6520 break;
6521 }
6522 }
6523
6524 /* now we've checked all possible ways to reference a backend
6525 * from a frontend.
6526 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006527 if (!found)
6528 continue;
6529 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006530 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006531 /* we have the sum of the maxconns in <total>. We only
6532 * keep 10% of that sum to set the default fullconn, with
6533 * a hard minimum of 1 (to avoid a divide by zero).
6534 */
6535 curproxy->fullconn = (total + 9) / 10;
6536 if (!curproxy->fullconn)
6537 curproxy->fullconn = 1;
6538 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006539 }
6540
Willy Tarreau056f5682010-06-06 15:51:11 +02006541 /* initialize stick-tables on backend capable proxies. This must not
6542 * be done earlier because the data size may be discovered while parsing
6543 * other proxies.
6544 */
6545 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006546 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006547
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006548 /*
6549 * Recount currently required checks.
6550 */
6551
6552 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6553 int optnum;
6554
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006555 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6556 if (curproxy->options & cfg_opts[optnum].val)
6557 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006558
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006559 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6560 if (curproxy->options2 & cfg_opts2[optnum].val)
6561 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006562 }
6563
Willy Tarreaubb925012009-07-23 13:36:36 +02006564 if (cfgerr > 0)
6565 err_code |= ERR_ALERT | ERR_FATAL;
6566 out:
6567 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006568}
6569
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006570/*
6571 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6572 * parsing sessions.
6573 */
6574void cfg_register_keywords(struct cfg_kw_list *kwl)
6575{
6576 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6577}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006578
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006579/*
6580 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6581 */
6582void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6583{
6584 LIST_DEL(&kwl->list);
6585 LIST_INIT(&kwl->list);
6586}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006587
6588/*
6589 * Local variables:
6590 * c-indent-level: 8
6591 * c-basic-offset: 8
6592 * End:
6593 */