blob: 44fc1dabd96e20e40224de786deb98494a4b1e33 [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;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003263 curproxy->options2 &= ~PR_O2_REDIS_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003264 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003265 if (!*args[2]) { /* no argument */
3266 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3267 curproxy->check_len = strlen(DEF_CHECK_REQ);
3268 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003269 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 curproxy->check_req = (char *)malloc(reqlen);
3271 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003272 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003274 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 if (*args[4])
3276 reqlen += strlen(args[4]);
3277 else
3278 reqlen += strlen("HTTP/1.0");
3279
3280 curproxy->check_req = (char *)malloc(reqlen);
3281 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003282 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003284 }
3285 else if (!strcmp(args[1], "ssl-hello-chk")) {
3286 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003287 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003288 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003289
Willy Tarreaua534fea2008-08-03 12:19:50 +02003290 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003291 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003292 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003293 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003294 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003295 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003296 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003297 curproxy->options2 &= ~PR_O2_REDIS_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003298 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003299 }
Willy Tarreau23677902007-05-08 23:50:35 +02003300 else if (!strcmp(args[1], "smtpchk")) {
3301 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003302 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003303 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003304 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003305 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003306 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003307 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003308 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003309 curproxy->options2 &= ~PR_O2_REDIS_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003310 curproxy->options |= PR_O_SMTP_CHK;
3311
3312 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3313 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3314 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3315 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3316 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3317 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3318 curproxy->check_req = (char *)malloc(reqlen);
3319 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3320 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3321 } else {
3322 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3323 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3324 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3325 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3326 }
3327 }
3328 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003329 else if (!strcmp(args[1], "pgsql-check")) {
3330 /* use PostgreSQL request to check servers' health */
3331 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3332 err_code |= ERR_WARN;
3333
3334 free(curproxy->check_req);
3335 curproxy->check_req = NULL;
3336 curproxy->options &= ~PR_O_HTTP_CHK;
3337 curproxy->options &= ~PR_O_SMTP_CHK;
3338 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3339 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003340 curproxy->options2 &= ~PR_O2_REDIS_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003341 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3342 curproxy->options2 |= PR_O2_PGSQL_CHK;
3343
3344 if (*(args[2])) {
3345 int cur_arg = 2;
3346
3347 while (*(args[cur_arg])) {
3348 if (strcmp(args[cur_arg], "user") == 0) {
3349 char * packet;
3350 uint32_t packet_len;
3351 uint32_t pv;
3352
3353 /* suboption header - needs additional argument for it */
3354 if (*(args[cur_arg+1]) == 0) {
3355 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3356 file, linenum, args[0], args[1], args[cur_arg]);
3357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
3359 }
3360
3361 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3362 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3363 pv = htonl(0x30000); /* protocol version 3.0 */
3364
3365 packet = (char*) calloc(1, packet_len);
3366
3367 memcpy(packet + 4, &pv, 4);
3368
3369 /* copy "user" */
3370 memcpy(packet + 8, "user", 4);
3371
3372 /* copy username */
3373 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3374
3375 free(curproxy->check_req);
3376 curproxy->check_req = packet;
3377 curproxy->check_len = packet_len;
3378
3379 packet_len = htonl(packet_len);
3380 memcpy(packet, &packet_len, 4);
3381 cur_arg += 2;
3382 } else {
3383 /* unknown suboption - catchall */
3384 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3385 file, linenum, args[0], args[1]);
3386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
3388 }
3389 } /* end while loop */
3390 }
3391 }
3392
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003393 else if (!strcmp(args[1], "redis-check")) {
3394 /* use REDIS PING request to check servers' health */
3395 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3396 err_code |= ERR_WARN;
3397
3398 free(curproxy->check_req);
3399 curproxy->check_req = NULL;
3400 curproxy->options &= ~PR_O_HTTP_CHK;
3401 curproxy->options &= ~PR_O_SMTP_CHK;
3402 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3403 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3404 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
3405 curproxy->options2 &= ~PR_O2_LDAP_CHK;
3406 curproxy->options2 |= PR_O2_REDIS_CHK;
3407
3408 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3409 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3410 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3411 }
3412
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003413 else if (!strcmp(args[1], "mysql-check")) {
3414 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003415 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3416 err_code |= ERR_WARN;
3417
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003418 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003419 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003420 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003421 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003422 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003423 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003424 curproxy->options2 &= ~PR_O2_REDIS_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003425 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003426 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003427
3428 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3429 * const char mysql40_client_auth_pkt[] = {
3430 * "\x0e\x00\x00" // packet length
3431 * "\x01" // packet number
3432 * "\x00\x00" // client capabilities
3433 * "\x00\x00\x01" // max packet
3434 * "haproxy\x00" // username (null terminated string)
3435 * "\x00" // filler (always 0x00)
3436 * "\x01\x00\x00" // packet length
3437 * "\x00" // packet number
3438 * "\x01" // COM_QUIT command
3439 * };
3440 */
3441
3442 if (*(args[2])) {
3443 int cur_arg = 2;
3444
3445 while (*(args[cur_arg])) {
3446 if (strcmp(args[cur_arg], "user") == 0) {
3447 char *mysqluser;
3448 int packetlen, reqlen, userlen;
3449
3450 /* suboption header - needs additional argument for it */
3451 if (*(args[cur_arg+1]) == 0) {
3452 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3453 file, linenum, args[0], args[1], args[cur_arg]);
3454 err_code |= ERR_ALERT | ERR_FATAL;
3455 goto out;
3456 }
3457 mysqluser = args[cur_arg + 1];
3458 userlen = strlen(mysqluser);
3459 packetlen = userlen + 7;
3460 reqlen = packetlen + 9;
3461
3462 free(curproxy->check_req);
3463 curproxy->check_req = (char *)calloc(1, reqlen);
3464 curproxy->check_len = reqlen;
3465
3466 snprintf(curproxy->check_req, 4, "%c%c%c",
3467 ((unsigned char) packetlen & 0xff),
3468 ((unsigned char) (packetlen >> 8) & 0xff),
3469 ((unsigned char) (packetlen >> 16) & 0xff));
3470
3471 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003472 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003473 curproxy->check_req[8] = 1;
3474 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3475 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3476 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3477 cur_arg += 2;
3478 } else {
3479 /* unknown suboption - catchall */
3480 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3481 file, linenum, args[0], args[1]);
3482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
3484 }
3485 } /* end while loop */
3486 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003487 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003488 else if (!strcmp(args[1], "ldap-check")) {
3489 /* use LDAP request to check servers' health */
3490 free(curproxy->check_req);
3491 curproxy->check_req = NULL;
3492 curproxy->options &= ~PR_O_HTTP_CHK;
3493 curproxy->options &= ~PR_O_SMTP_CHK;
3494 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3495 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003496 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003497 curproxy->options2 &= ~PR_O2_REDIS_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003498 curproxy->options2 |= PR_O2_LDAP_CHK;
3499
3500 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3501 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3502 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3503 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003504 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003505 int cur_arg;
3506
3507 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3508 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003509 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003510
3511 curproxy->options |= PR_O_FWDFOR;
3512
3513 free(curproxy->fwdfor_hdr_name);
3514 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3515 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3516
3517 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3518 cur_arg = 2;
3519 while (*(args[cur_arg])) {
3520 if (!strcmp(args[cur_arg], "except")) {
3521 /* suboption except - needs additional argument for it */
3522 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3523 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3524 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003525 err_code |= ERR_ALERT | ERR_FATAL;
3526 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003527 }
3528 /* flush useless bits */
3529 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003530 cur_arg += 2;
3531 } else if (!strcmp(args[cur_arg], "header")) {
3532 /* suboption header - needs additional argument for it */
3533 if (*(args[cur_arg+1]) == 0) {
3534 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3535 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003538 }
3539 free(curproxy->fwdfor_hdr_name);
3540 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3541 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3542 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003543 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003544 /* unknown suboption - catchall */
3545 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3546 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003547 err_code |= ERR_ALERT | ERR_FATAL;
3548 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003549 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003550 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003551 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003552 else if (!strcmp(args[1], "originalto")) {
3553 int cur_arg;
3554
3555 /* insert x-original-to field, but not for the IP address listed as an except.
3556 * set default options (ie: bitfield, header name, etc)
3557 */
3558
3559 curproxy->options |= PR_O_ORGTO;
3560
3561 free(curproxy->orgto_hdr_name);
3562 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3563 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3564
3565 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3566 cur_arg = 2;
3567 while (*(args[cur_arg])) {
3568 if (!strcmp(args[cur_arg], "except")) {
3569 /* suboption except - needs additional argument for it */
3570 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3571 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3572 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003573 err_code |= ERR_ALERT | ERR_FATAL;
3574 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003575 }
3576 /* flush useless bits */
3577 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3578 cur_arg += 2;
3579 } else if (!strcmp(args[cur_arg], "header")) {
3580 /* suboption header - needs additional argument for it */
3581 if (*(args[cur_arg+1]) == 0) {
3582 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3583 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003586 }
3587 free(curproxy->orgto_hdr_name);
3588 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3589 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3590 cur_arg += 2;
3591 } else {
3592 /* unknown suboption - catchall */
3593 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3594 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003597 }
3598 } /* end while loop */
3599 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003600 else {
3601 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003604 }
Willy Tarreau93893792009-07-23 13:19:11 +02003605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003606 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003607 else if (!strcmp(args[0], "default_backend")) {
3608 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003609 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003610
3611 if (*(args[1]) == 0) {
3612 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003615 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003616 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003617 curproxy->defbe.name = strdup(args[1]);
3618 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003619 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003620 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003621 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003622
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003623 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3624 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003625 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003626 /* enable reconnections to dispatch */
3627 curproxy->options |= PR_O_REDISP;
3628 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003629 else if (!strcmp(args[0], "http-check")) {
3630 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003632
3633 if (strcmp(args[1], "disable-on-404") == 0) {
3634 /* enable a graceful server shutdown on an HTTP 404 response */
3635 curproxy->options |= PR_O_DISABLE404;
3636 }
Willy Tarreauef781042010-01-27 11:53:01 +01003637 else if (strcmp(args[1], "send-state") == 0) {
3638 /* enable emission of the apparent state of a server in HTTP checks */
3639 curproxy->options2 |= PR_O2_CHK_SNDST;
3640 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003641 else if (strcmp(args[1], "expect") == 0) {
3642 const char *ptr_arg;
3643 int cur_arg;
3644
3645 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3646 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
3649 }
3650
3651 cur_arg = 2;
3652 /* consider exclamation marks, sole or at the beginning of a word */
3653 while (*(ptr_arg = args[cur_arg])) {
3654 while (*ptr_arg == '!') {
3655 curproxy->options2 ^= PR_O2_EXP_INV;
3656 ptr_arg++;
3657 }
3658 if (*ptr_arg)
3659 break;
3660 cur_arg++;
3661 }
3662 /* now ptr_arg points to the beginning of a word past any possible
3663 * exclamation mark, and cur_arg is the argument which holds this word.
3664 */
3665 if (strcmp(ptr_arg, "status") == 0) {
3666 if (!*(args[cur_arg + 1])) {
3667 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3668 file, linenum, args[0], args[1], ptr_arg);
3669 err_code |= ERR_ALERT | ERR_FATAL;
3670 goto out;
3671 }
3672 curproxy->options2 |= PR_O2_EXP_STS;
3673 curproxy->expect_str = strdup(args[cur_arg + 1]);
3674 }
3675 else if (strcmp(ptr_arg, "string") == 0) {
3676 if (!*(args[cur_arg + 1])) {
3677 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3678 file, linenum, args[0], args[1], ptr_arg);
3679 err_code |= ERR_ALERT | ERR_FATAL;
3680 goto out;
3681 }
3682 curproxy->options2 |= PR_O2_EXP_STR;
3683 curproxy->expect_str = strdup(args[cur_arg + 1]);
3684 }
3685 else if (strcmp(ptr_arg, "rstatus") == 0) {
3686 if (!*(args[cur_arg + 1])) {
3687 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3688 file, linenum, args[0], args[1], ptr_arg);
3689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
3691 }
3692 curproxy->options2 |= PR_O2_EXP_RSTS;
3693 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3694 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3695 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3696 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
3699 }
3700 }
3701 else if (strcmp(ptr_arg, "rstring") == 0) {
3702 if (!*(args[cur_arg + 1])) {
3703 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3704 file, linenum, args[0], args[1], ptr_arg);
3705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
3707 }
3708 curproxy->options2 |= PR_O2_EXP_RSTR;
3709 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3710 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3711 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3712 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3713 err_code |= ERR_ALERT | ERR_FATAL;
3714 goto out;
3715 }
3716 }
3717 else {
3718 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3719 file, linenum, args[0], args[1], ptr_arg);
3720 err_code |= ERR_ALERT | ERR_FATAL;
3721 goto out;
3722 }
3723 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003724 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003725 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003728 }
3729 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003730 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003731 if (curproxy == &defproxy) {
3732 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003735 }
3736
Willy Tarreaub80c2302007-11-30 20:51:32 +01003737 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003738 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003739
3740 if (strcmp(args[1], "fail") == 0) {
3741 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003742 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003743 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3744 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_ALERT | ERR_FATAL;
3746 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003747 }
3748
Willy Tarreauef6494c2010-01-28 17:12:36 +01003749 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003750 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3751 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003754 }
3755 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3756 }
3757 else {
3758 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003761 }
3762 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003763#ifdef TPROXY
3764 else if (!strcmp(args[0], "transparent")) {
3765 /* enable transparent proxy connections */
3766 curproxy->options |= PR_O_TRANSP;
3767 }
3768#endif
3769 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003770 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003772
Willy Tarreaubaaee002006-06-26 02:48:02 +02003773 if (*(args[1]) == 0) {
3774 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003775 err_code |= ERR_ALERT | ERR_FATAL;
3776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003777 }
3778 curproxy->maxconn = atol(args[1]);
3779 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003780 else if (!strcmp(args[0], "backlog")) { /* backlog */
3781 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003782 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003783
3784 if (*(args[1]) == 0) {
3785 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003788 }
3789 curproxy->backlog = atol(args[1]);
3790 }
Willy Tarreau86034312006-12-29 00:10:33 +01003791 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003792 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003793 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003794
Willy Tarreau86034312006-12-29 00:10:33 +01003795 if (*(args[1]) == 0) {
3796 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003797 err_code |= ERR_ALERT | ERR_FATAL;
3798 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003799 }
3800 curproxy->fullconn = atol(args[1]);
3801 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003802 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3803 if (*(args[1]) == 0) {
3804 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003805 err_code |= ERR_ALERT | ERR_FATAL;
3806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003807 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003808 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3809 if (err) {
3810 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3811 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003814 }
3815 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003816 }
3817 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003818 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003819 if (curproxy == &defproxy) {
3820 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003824 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003825 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003826
Willy Tarreaubaaee002006-06-26 02:48:02 +02003827 if (strchr(args[1], ':') == NULL) {
3828 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003831 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003832 sk = str2sa(args[1]);
3833 if (!sk) {
3834 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
3837 }
3838 curproxy->dispatch_addr = *sk;
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01003839 curproxy->options2 |= PR_O2_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003840 }
3841 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003842 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003843 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003844
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003845 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003846 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3847 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003850 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003852 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3853 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3854 err_code |= ERR_WARN;
3855
3856 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3857 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3858 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3859 }
3860 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3861 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3862 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3863 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003864 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3865 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3866 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3867 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003868 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003869 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
3872 }
3873 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003874 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003875 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003876 char *rport, *raddr;
3877 short realport = 0;
3878 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003879
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003880 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003881 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003884 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003885 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003886 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887
3888 if (!*args[2]) {
3889 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3890 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003894
3895 err = invalid_char(args[1]);
3896 if (err) {
3897 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3898 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003899 err_code |= ERR_ALERT | ERR_FATAL;
3900 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003901 }
3902
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003903 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003904 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003905
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003906 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3907 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3908 err_code |= ERR_ALERT | ERR_ABORT;
3909 goto out;
3910 }
3911
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003912 /* the servers are linked backwards first */
3913 newsrv->next = curproxy->srv;
3914 curproxy->srv = newsrv;
3915 newsrv->proxy = curproxy;
3916 newsrv->conf.file = file;
3917 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003918
Simon Hormanaf514952011-06-21 14:34:57 +09003919 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003920 LIST_INIT(&newsrv->pendconns);
3921 do_check = 0;
3922 newsrv->state = SRV_RUNNING; /* early server setup */
3923 newsrv->last_change = now.tv_sec;
3924 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003925
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003926 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003927 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003928 * - IP: => port=+0, relative
3929 * - IP:N => port=N, absolute
3930 * - IP:+N => port=+N, relative
3931 * - IP:-N => port=-N, relative
3932 */
3933 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003934 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003935 if (rport) {
3936 *rport++ = 0;
3937 realport = atol(rport);
3938 if (!isdigit((unsigned char)*rport))
3939 newsrv->state |= SRV_MAPPORTS;
3940 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003941 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003942
Willy Tarreaufab5a432011-03-04 15:31:53 +01003943 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003944 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003945 if (!sk) {
3946 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
3949 }
3950 newsrv->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01003951
3952 switch (newsrv->addr.ss_family) {
3953 case AF_INET:
3954 ((struct sockaddr_in *)&newsrv->addr)->sin_port = htons(realport);
3955 break;
3956 case AF_INET6:
3957 ((struct sockaddr_in6 *)&newsrv->addr)->sin6_port = htons(realport);
3958 break;
3959 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003960
3961 newsrv->check_port = curproxy->defsrv.check_port;
3962 newsrv->inter = curproxy->defsrv.inter;
3963 newsrv->fastinter = curproxy->defsrv.fastinter;
3964 newsrv->downinter = curproxy->defsrv.downinter;
3965 newsrv->rise = curproxy->defsrv.rise;
3966 newsrv->fall = curproxy->defsrv.fall;
3967 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3968 newsrv->minconn = curproxy->defsrv.minconn;
3969 newsrv->maxconn = curproxy->defsrv.maxconn;
3970 newsrv->slowstart = curproxy->defsrv.slowstart;
3971 newsrv->onerror = curproxy->defsrv.onerror;
3972 newsrv->consecutive_errors_limit
3973 = curproxy->defsrv.consecutive_errors_limit;
3974 newsrv->uweight = newsrv->iweight
3975 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003977 newsrv->curfd = -1; /* no health-check in progress */
3978 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003979
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003980 cur_arg = 3;
3981 } else {
3982 newsrv = &curproxy->defsrv;
3983 cur_arg = 1;
3984 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003985
Willy Tarreaubaaee002006-06-26 02:48:02 +02003986 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003987 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003988 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003989
3990 if (!*args[cur_arg + 1]) {
3991 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3992 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003995 }
3996
3997 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003998 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003999
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004000 if (newsrv->puid <= 0) {
4001 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004002 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004003 err_code |= ERR_ALERT | ERR_FATAL;
4004 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004005 }
4006
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004007 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4008 if (node) {
4009 struct server *target = container_of(node, struct server, conf.id);
4010 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4011 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
4014 }
4015 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004016 cur_arg += 2;
4017 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004018 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004019 newsrv->cookie = strdup(args[cur_arg + 1]);
4020 newsrv->cklen = strlen(args[cur_arg + 1]);
4021 cur_arg += 2;
4022 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004023 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004024 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4025 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4026 cur_arg += 2;
4027 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004028 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004029 if (!*args[cur_arg + 1]) {
4030 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4031 file, linenum, args[cur_arg]);
4032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
4034 }
4035
Willy Tarreaubaaee002006-06-26 02:48:02 +02004036 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004037 if (newsrv->rise <= 0) {
4038 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4039 file, linenum, args[cur_arg]);
4040 err_code |= ERR_ALERT | ERR_FATAL;
4041 goto out;
4042 }
4043
Willy Tarreau96839092010-03-29 10:02:24 +02004044 if (newsrv->health)
4045 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046 cur_arg += 2;
4047 }
4048 else if (!strcmp(args[cur_arg], "fall")) {
4049 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004050
4051 if (!*args[cur_arg + 1]) {
4052 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4053 file, linenum, args[cur_arg]);
4054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
4056 }
4057
4058 if (newsrv->fall <= 0) {
4059 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4060 file, linenum, args[cur_arg]);
4061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
4063 }
4064
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 cur_arg += 2;
4066 }
4067 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004068 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4069 if (err) {
4070 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4071 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004074 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004075 if (val <= 0) {
4076 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4077 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004078 err_code |= ERR_ALERT | ERR_FATAL;
4079 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004080 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004081 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004082 cur_arg += 2;
4083 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004084 else if (!strcmp(args[cur_arg], "fastinter")) {
4085 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4086 if (err) {
4087 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4088 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004091 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004092 if (val <= 0) {
4093 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4094 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004095 err_code |= ERR_ALERT | ERR_FATAL;
4096 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004097 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004098 newsrv->fastinter = val;
4099 cur_arg += 2;
4100 }
4101 else if (!strcmp(args[cur_arg], "downinter")) {
4102 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4103 if (err) {
4104 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4105 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004108 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004109 if (val <= 0) {
4110 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4111 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004112 err_code |= ERR_ALERT | ERR_FATAL;
4113 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004114 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004115 newsrv->downinter = val;
4116 cur_arg += 2;
4117 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004118 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004119 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004120 if (!sk) {
4121 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4122 err_code |= ERR_ALERT | ERR_FATAL;
4123 goto out;
4124 }
4125 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004126 cur_arg += 2;
4127 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004128 else if (!strcmp(args[cur_arg], "port")) {
4129 newsrv->check_port = atol(args[cur_arg + 1]);
4130 cur_arg += 2;
4131 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004132 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004133 newsrv->state |= SRV_BACKUP;
4134 cur_arg ++;
4135 }
Simon Hormanfa461682011-06-25 09:39:49 +09004136 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4137 newsrv->state |= SRV_NON_STICK;
4138 cur_arg ++;
4139 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004140 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4141 newsrv->state |= SRV_SEND_PROXY;
4142 cur_arg ++;
4143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004144 else if (!strcmp(args[cur_arg], "weight")) {
4145 int w;
4146 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004147 if (w < 0 || w > 256) {
4148 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004149 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004150 err_code |= ERR_ALERT | ERR_FATAL;
4151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004152 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004153 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 cur_arg += 2;
4155 }
4156 else if (!strcmp(args[cur_arg], "minconn")) {
4157 newsrv->minconn = atol(args[cur_arg + 1]);
4158 cur_arg += 2;
4159 }
4160 else if (!strcmp(args[cur_arg], "maxconn")) {
4161 newsrv->maxconn = atol(args[cur_arg + 1]);
4162 cur_arg += 2;
4163 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004164 else if (!strcmp(args[cur_arg], "maxqueue")) {
4165 newsrv->maxqueue = atol(args[cur_arg + 1]);
4166 cur_arg += 2;
4167 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004168 else if (!strcmp(args[cur_arg], "slowstart")) {
4169 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004170 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004171 if (err) {
4172 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4173 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004176 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004177 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004178 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4179 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004182 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004183 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004184 cur_arg += 2;
4185 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004186 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004187
4188 if (!*args[cur_arg + 1]) {
4189 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4190 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004193 }
4194
4195 newsrv->trackit = strdup(args[cur_arg + 1]);
4196
4197 cur_arg += 2;
4198 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004199 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004200 global.maxsock++;
4201 do_check = 1;
4202 cur_arg += 1;
4203 }
Willy Tarreau96839092010-03-29 10:02:24 +02004204 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4205 newsrv->state |= SRV_MAINTAIN;
4206 newsrv->state &= ~SRV_RUNNING;
4207 newsrv->health = 0;
4208 cur_arg += 1;
4209 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004210 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004211 if (!strcmp(args[cur_arg + 1], "none"))
4212 newsrv->observe = HANA_OBS_NONE;
4213 else if (!strcmp(args[cur_arg + 1], "layer4"))
4214 newsrv->observe = HANA_OBS_LAYER4;
4215 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4216 if (curproxy->mode != PR_MODE_HTTP) {
4217 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4218 file, linenum, args[cur_arg + 1]);
4219 err_code |= ERR_ALERT;
4220 }
4221 newsrv->observe = HANA_OBS_LAYER7;
4222 }
4223 else {
4224 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004225 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004226 file, linenum, args[cur_arg], args[cur_arg + 1]);
4227 err_code |= ERR_ALERT | ERR_FATAL;
4228 goto out;
4229 }
4230
4231 cur_arg += 2;
4232 }
4233 else if (!strcmp(args[cur_arg], "on-error")) {
4234 if (!strcmp(args[cur_arg + 1], "fastinter"))
4235 newsrv->onerror = HANA_ONERR_FASTINTER;
4236 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4237 newsrv->onerror = HANA_ONERR_FAILCHK;
4238 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4239 newsrv->onerror = HANA_ONERR_SUDDTH;
4240 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4241 newsrv->onerror = HANA_ONERR_MARKDWN;
4242 else {
4243 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004244 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004245 file, linenum, args[cur_arg], args[cur_arg + 1]);
4246 err_code |= ERR_ALERT | ERR_FATAL;
4247 goto out;
4248 }
4249
4250 cur_arg += 2;
4251 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004252 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4253 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4254 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4255 else {
4256 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4257 file, linenum, args[cur_arg], args[cur_arg + 1]);
4258 err_code |= ERR_ALERT | ERR_FATAL;
4259 goto out;
4260 }
4261
4262 cur_arg += 2;
4263 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004264 else if (!strcmp(args[cur_arg], "error-limit")) {
4265 if (!*args[cur_arg + 1]) {
4266 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4267 file, linenum, args[cur_arg]);
4268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
4270 }
4271
4272 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4273
4274 if (newsrv->consecutive_errors_limit <= 0) {
4275 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4276 file, linenum, args[cur_arg]);
4277 err_code |= ERR_ALERT | ERR_FATAL;
4278 goto out;
4279 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004280 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004281 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004282 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004283 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004284 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004285
Willy Tarreaubaaee002006-06-26 02:48:02 +02004286 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004287#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004288 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004289 file, linenum, "source", "usesrc");
4290#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004291 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004292 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004293#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004294 err_code |= ERR_ALERT | ERR_FATAL;
4295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004296 }
4297 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004298 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4299 if (!sk) {
4300 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4301 err_code |= ERR_ALERT | ERR_FATAL;
4302 goto out;
4303 }
4304 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004305
4306 if (port_low != port_high) {
4307 int i;
4308 if (port_low <= 0 || port_low > 65535 ||
4309 port_high <= 0 || port_high > 65535 ||
4310 port_low > port_high) {
4311 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4312 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004313 err_code |= ERR_ALERT | ERR_FATAL;
4314 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004315 }
4316 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4317 for (i = 0; i < newsrv->sport_range->size; i++)
4318 newsrv->sport_range->ports[i] = port_low + i;
4319 }
4320
Willy Tarreaubaaee002006-06-26 02:48:02 +02004321 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004322 while (*(args[cur_arg])) {
4323 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004324#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4325#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004326 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4327 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4328 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004329 err_code |= ERR_ALERT | ERR_FATAL;
4330 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004331 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004332#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004333 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004334 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004335 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004336 err_code |= ERR_ALERT | ERR_FATAL;
4337 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004338 }
4339 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004340 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004341 newsrv->state |= SRV_TPROXY_CLI;
4342 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004343 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004344 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004345 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4346 char *name, *end;
4347
4348 name = args[cur_arg+1] + 7;
4349 while (isspace(*name))
4350 name++;
4351
4352 end = name;
4353 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4354 end++;
4355
4356 newsrv->state &= ~SRV_TPROXY_MASK;
4357 newsrv->state |= SRV_TPROXY_DYN;
4358 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4359 newsrv->bind_hdr_len = end - name;
4360 memcpy(newsrv->bind_hdr_name, name, end - name);
4361 newsrv->bind_hdr_name[end-name] = '\0';
4362 newsrv->bind_hdr_occ = -1;
4363
4364 /* now look for an occurrence number */
4365 while (isspace(*end))
4366 end++;
4367 if (*end == ',') {
4368 end++;
4369 name = end;
4370 if (*end == '-')
4371 end++;
4372 while (isdigit(*end))
4373 end++;
4374 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4375 }
4376
4377 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4378 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4379 " occurrences values smaller than %d.\n",
4380 file, linenum, MAX_HDR_HISTORY);
4381 err_code |= ERR_ALERT | ERR_FATAL;
4382 goto out;
4383 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004384 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004385 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004386 if (!sk) {
4387 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4388 err_code |= ERR_ALERT | ERR_FATAL;
4389 goto out;
4390 }
4391 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004392 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004393 }
4394 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004395#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004396 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004397#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004398 cur_arg += 2;
4399 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004400#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004401 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004402 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004403 err_code |= ERR_ALERT | ERR_FATAL;
4404 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004405#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4406 } /* "usesrc" */
4407
4408 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4409#ifdef SO_BINDTODEVICE
4410 if (!*args[cur_arg + 1]) {
4411 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4412 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= ERR_ALERT | ERR_FATAL;
4414 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004415 }
4416 if (newsrv->iface_name)
4417 free(newsrv->iface_name);
4418
4419 newsrv->iface_name = strdup(args[cur_arg + 1]);
4420 newsrv->iface_len = strlen(newsrv->iface_name);
4421 global.last_checks |= LSTCHK_NETADM;
4422#else
4423 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4424 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004427#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004428 cur_arg += 2;
4429 continue;
4430 }
4431 /* this keyword in not an option of "source" */
4432 break;
4433 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004434 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004435 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004436 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4437 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004440 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004441 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004442 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004443 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 +01004444 file, linenum, newsrv->id);
4445 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004446 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 +01004447 file, linenum);
4448
Willy Tarreau93893792009-07-23 13:19:11 +02004449 err_code |= ERR_ALERT | ERR_FATAL;
4450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004451 }
4452 }
4453
4454 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004455 if (newsrv->trackit) {
4456 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4457 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004458 err_code |= ERR_ALERT | ERR_FATAL;
4459 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004460 }
4461
David du Colombier6f5ccb12011-03-10 22:26:24 +01004462 switch (newsrv->check_addr.ss_family) {
4463 case AF_INET:
4464 if (!newsrv->check_port && ((struct sockaddr_in *)&newsrv->check_addr)->sin_port)
4465 newsrv->check_port = ntohs(((struct sockaddr_in *)&newsrv->check_addr)->sin_port);
4466 break;
4467 case AF_INET6:
4468 if (!newsrv->check_port && ((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port)
4469 newsrv->check_port = ntohs(((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port);
4470 break;
4471 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004472
Willy Tarreaubaaee002006-06-26 02:48:02 +02004473 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4474 newsrv->check_port = realport; /* by default */
4475 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004476 /* not yet valid, because no port was set on
4477 * the server either. We'll check if we have
4478 * a known port on the first listener.
4479 */
4480 struct listener *l;
4481 l = curproxy->listen;
4482 if (l) {
4483 int port;
4484 port = (l->addr.ss_family == AF_INET6)
4485 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4486 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4487 newsrv->check_port = port;
4488 }
4489 }
4490 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004491 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4492 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004496
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004497 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004498 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004499 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4500 err_code |= ERR_ALERT | ERR_ABORT;
4501 goto out;
4502 }
4503
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004504 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505 newsrv->state |= SRV_CHECKED;
4506 }
4507
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004508 if (!defsrv) {
4509 if (newsrv->state & SRV_BACKUP)
4510 curproxy->srv_bck++;
4511 else
4512 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004513
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004514 newsrv->prev_state = newsrv->state;
4515 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 }
4517 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004518 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004519 int facility;
4520
4521 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4522 curproxy->logfac1 = global.logfac1;
4523 curproxy->logsrv1 = global.logsrv1;
4524 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004525 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004526 curproxy->logfac2 = global.logfac2;
4527 curproxy->logsrv2 = global.logsrv2;
4528 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004529 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004530 }
4531 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004532 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004533
4534 facility = get_log_facility(args[2]);
4535 if (facility < 0) {
4536 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4537 exit(1);
4538 }
4539
4540 level = 7; /* max syslog level = debug */
4541 if (*(args[3])) {
4542 level = get_log_level(args[3]);
4543 if (level < 0) {
4544 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4545 exit(1);
4546 }
4547 }
4548
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004549 minlvl = 0; /* limit syslog level to this level (emerg) */
4550 if (*(args[4])) {
4551 minlvl = get_log_level(args[4]);
4552 if (level < 0) {
4553 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4554 exit(1);
4555 }
4556 }
4557
Robert Tsai81ae1952007-12-05 10:47:29 +01004558 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004559 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004560 if (!sk) {
4561 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004562 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004563 err_code |= ERR_ALERT | ERR_FATAL;
4564 goto out;
4565 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004566 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004567 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004568 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004569 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004570 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4571 err_code |= ERR_ALERT | ERR_FATAL;
4572 goto out;
4573 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004574 logsrv.addr = *sk;
4575 if (!get_host_port(&logsrv.addr))
4576 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004578
4579 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004580 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004581 curproxy->logfac1 = facility;
4582 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004583 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004584 }
4585 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004586 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004587 curproxy->logfac2 = facility;
4588 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004589 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004590 }
4591 else {
4592 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004593 err_code |= ERR_ALERT | ERR_FATAL;
4594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004595 }
4596 }
4597 else {
4598 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4599 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004600 err_code |= ERR_ALERT | ERR_FATAL;
4601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004602 }
4603 }
4604 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004605 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004606 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004607
Willy Tarreau977b8e42006-12-29 14:19:17 +01004608 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004609 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004610
Willy Tarreaubaaee002006-06-26 02:48:02 +02004611 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004612 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4613 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004616 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004617
4618 /* we must first clear any optional default setting */
4619 curproxy->options &= ~PR_O_TPXY_MASK;
4620 free(curproxy->iface_name);
4621 curproxy->iface_name = NULL;
4622 curproxy->iface_len = 0;
4623
Willy Tarreaud5191e72010-02-09 20:50:45 +01004624 sk = str2sa(args[1]);
4625 if (!sk) {
4626 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4627 err_code |= ERR_ALERT | ERR_FATAL;
4628 goto out;
4629 }
4630 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004631 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004632
4633 cur_arg = 2;
4634 while (*(args[cur_arg])) {
4635 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004636#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4637#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004638 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4639 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4640 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004643 }
4644#endif
4645 if (!*args[cur_arg + 1]) {
4646 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4647 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004648 err_code |= ERR_ALERT | ERR_FATAL;
4649 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004650 }
4651
4652 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004653 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004654 curproxy->options |= PR_O_TPXY_CLI;
4655 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004656 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004657 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004658 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4659 char *name, *end;
4660
4661 name = args[cur_arg+1] + 7;
4662 while (isspace(*name))
4663 name++;
4664
4665 end = name;
4666 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4667 end++;
4668
4669 curproxy->options &= ~PR_O_TPXY_MASK;
4670 curproxy->options |= PR_O_TPXY_DYN;
4671 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4672 curproxy->bind_hdr_len = end - name;
4673 memcpy(curproxy->bind_hdr_name, name, end - name);
4674 curproxy->bind_hdr_name[end-name] = '\0';
4675 curproxy->bind_hdr_occ = -1;
4676
4677 /* now look for an occurrence number */
4678 while (isspace(*end))
4679 end++;
4680 if (*end == ',') {
4681 end++;
4682 name = end;
4683 if (*end == '-')
4684 end++;
4685 while (isdigit(*end))
4686 end++;
4687 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4688 }
4689
4690 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4691 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4692 " occurrences values smaller than %d.\n",
4693 file, linenum, MAX_HDR_HISTORY);
4694 err_code |= ERR_ALERT | ERR_FATAL;
4695 goto out;
4696 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004697 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004698 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004699 if (!sk) {
4700 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4701 err_code |= ERR_ALERT | ERR_FATAL;
4702 goto out;
4703 }
4704 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004705 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004706 }
4707 global.last_checks |= LSTCHK_NETADM;
4708#if !defined(CONFIG_HAP_LINUX_TPROXY)
4709 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004710#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004711#else /* no TPROXY support */
4712 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004713 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004714 err_code |= ERR_ALERT | ERR_FATAL;
4715 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004716#endif
4717 cur_arg += 2;
4718 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004719 }
4720
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004721 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4722#ifdef SO_BINDTODEVICE
4723 if (!*args[cur_arg + 1]) {
4724 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4725 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004726 err_code |= ERR_ALERT | ERR_FATAL;
4727 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004728 }
4729 if (curproxy->iface_name)
4730 free(curproxy->iface_name);
4731
4732 curproxy->iface_name = strdup(args[cur_arg + 1]);
4733 curproxy->iface_len = strlen(curproxy->iface_name);
4734 global.last_checks |= LSTCHK_NETADM;
4735#else
4736 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4737 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004738 err_code |= ERR_ALERT | ERR_FATAL;
4739 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004740#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004741 cur_arg += 2;
4742 continue;
4743 }
4744 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4745 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004746 err_code |= ERR_ALERT | ERR_FATAL;
4747 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004750 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4751 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4752 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004753 err_code |= ERR_ALERT | ERR_FATAL;
4754 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004755 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004756 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004757 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4759 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004760 err_code |= ERR_ALERT | ERR_FATAL;
4761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004762 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004763
4764 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4765 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004766 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004767 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769 }
4770 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004771 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4772 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004773 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004774 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 }
4777 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004778 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4779 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004780 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004781 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004783 }
4784 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004785 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4786 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004787 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004788 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004790 }
4791 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004792 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4793 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004794 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004795 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004797 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004798 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004799 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4800 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004801 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004802 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004803 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004804 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004805 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004806 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4807 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004808 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004809 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004810 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004811 }
4812 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004813 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4814 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004815 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004816 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004817 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004818 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004819 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004820 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004821 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4822 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004823 err_code |= ERR_ALERT | ERR_FATAL;
4824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004825 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004826
4827 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4828 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004829 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004830 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004832 }
4833 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004834 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4835 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004836 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004837 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004839 }
4840 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004841 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4842 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004843 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004844 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004846 }
4847 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004848 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4849 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004850 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004851 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004853 }
4854 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004855 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4856 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004857 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004858 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004859 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004860 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004861 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004862 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4863 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004864 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004865 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004866 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004867 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004869 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004870
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 if (curproxy == &defproxy) {
4872 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004873 err_code |= ERR_ALERT | ERR_FATAL;
4874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004875 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004876 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004877 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878
Willy Tarreaubaaee002006-06-26 02:48:02 +02004879 if (*(args[1]) == 0) {
4880 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004881 err_code |= ERR_ALERT | ERR_FATAL;
4882 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004883 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004884
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004885 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4886 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4887 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4888 file, linenum, args[0]);
4889 err_code |= ERR_ALERT | ERR_FATAL;
4890 goto out;
4891 }
4892 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4893 }
4894 else if (*args[2]) {
4895 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4896 file, linenum, args[0], args[2]);
4897 err_code |= ERR_ALERT | ERR_FATAL;
4898 goto out;
4899 }
4900
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004901 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004902 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004903 wl->s = strdup(args[1]);
4904 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004905 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 }
4907 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004908 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004909 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4910 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004911 err_code |= ERR_ALERT | ERR_FATAL;
4912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004914
Willy Tarreauade5ec42010-01-28 19:33:49 +01004915 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4916 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004917 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004918 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 }
4921 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004922 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4923 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004924 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004925 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004927 }
4928 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004929 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4930 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004931 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004932 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004934 }
4935 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004936 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4938 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004939 err_code |= ERR_ALERT | ERR_FATAL;
4940 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004941 }
4942
Willy Tarreauade5ec42010-01-28 19:33:49 +01004943 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4944 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004945 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004946 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004948 }
4949 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004950 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4951 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004952 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004953 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 }
4956 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004957 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4958 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004959 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004960 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962 }
4963 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004964 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004965
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 if (curproxy == &defproxy) {
4967 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004968 err_code |= ERR_ALERT | ERR_FATAL;
4969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004970 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004971 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004972 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004973
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 if (*(args[1]) == 0) {
4975 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004976 err_code |= ERR_ALERT | ERR_FATAL;
4977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004978 }
4979
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004980 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4981 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4982 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4983 file, linenum, args[0]);
4984 err_code |= ERR_ALERT | ERR_FATAL;
4985 goto out;
4986 }
4987 err_code |= warnif_cond_requires_req(cond, file, linenum);
4988 }
4989 else if (*args[2]) {
4990 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4991 file, linenum, args[0], args[2]);
4992 err_code |= ERR_ALERT | ERR_FATAL;
4993 goto out;
4994 }
4995
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004996 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004997 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004998 wl->s = strdup(args[1]);
4999 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005000 }
5001 else if (!strcmp(args[0], "errorloc") ||
5002 !strcmp(args[0], "errorloc302") ||
5003 !strcmp(args[0], "errorloc303")) { /* error location */
5004 int errnum, errlen;
5005 char *err;
5006
Willy Tarreau977b8e42006-12-29 14:19:17 +01005007 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005008 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005009
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005011 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005012 err_code |= ERR_ALERT | ERR_FATAL;
5013 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005014 }
5015
5016 errnum = atol(args[1]);
5017 if (!strcmp(args[0], "errorloc303")) {
5018 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5019 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5020 } else {
5021 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5022 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5023 }
5024
Willy Tarreau0f772532006-12-23 20:51:41 +01005025 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5026 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005027 chunk_destroy(&curproxy->errmsg[rc]);
5028 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005029 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005031 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005032
5033 if (rc >= HTTP_ERR_SIZE) {
5034 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5035 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005036 free(err);
5037 }
5038 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005039 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5040 int errnum, errlen, fd;
5041 char *err;
5042 struct stat stat;
5043
5044 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005045 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005046
5047 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005048 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005049 err_code |= ERR_ALERT | ERR_FATAL;
5050 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005051 }
5052
5053 fd = open(args[2], O_RDONLY);
5054 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5055 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5056 file, linenum, args[2], args[1]);
5057 if (fd >= 0)
5058 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005061 }
5062
Willy Tarreau27a674e2009-08-17 07:23:33 +02005063 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005064 errlen = stat.st_size;
5065 } else {
5066 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005067 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005069 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005070 }
5071
5072 err = malloc(errlen); /* malloc() must succeed during parsing */
5073 errnum = read(fd, err, errlen);
5074 if (errnum != errlen) {
5075 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5076 file, linenum, args[2], args[1]);
5077 close(fd);
5078 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005079 err_code |= ERR_ALERT | ERR_FATAL;
5080 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005081 }
5082 close(fd);
5083
5084 errnum = atol(args[1]);
5085 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5086 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005087 chunk_destroy(&curproxy->errmsg[rc]);
5088 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005089 break;
5090 }
5091 }
5092
5093 if (rc >= HTTP_ERR_SIZE) {
5094 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5095 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005096 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005097 free(err);
5098 }
5099 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005100 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005101 struct cfg_kw_list *kwl;
5102 int index;
5103
5104 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5105 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5106 if (kwl->kw[index].section != CFG_LISTEN)
5107 continue;
5108 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5109 /* prepare error message just in case */
5110 snprintf(trash, sizeof(trash),
5111 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005112 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5113 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005114 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005117 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005118 else if (rc > 0) {
5119 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005120 err_code |= ERR_WARN;
5121 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005122 }
Willy Tarreau93893792009-07-23 13:19:11 +02005123 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005124 }
5125 }
5126 }
5127
Willy Tarreau6daf3432008-01-22 16:44:08 +01005128 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005131 }
Willy Tarreau93893792009-07-23 13:19:11 +02005132 out:
5133 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005134}
5135
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005136int
5137cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5138{
5139
5140 int err_code = 0;
5141 const char *err;
5142
5143 if (!strcmp(args[0], "userlist")) { /* new userlist */
5144 struct userlist *newul;
5145
5146 if (!*args[1]) {
5147 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5148 file, linenum, args[0]);
5149 err_code |= ERR_ALERT | ERR_FATAL;
5150 goto out;
5151 }
5152
5153 err = invalid_char(args[1]);
5154 if (err) {
5155 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5156 file, linenum, *err, args[0], args[1]);
5157 err_code |= ERR_ALERT | ERR_FATAL;
5158 goto out;
5159 }
5160
5161 for (newul = userlist; newul; newul = newul->next)
5162 if (!strcmp(newul->name, args[1])) {
5163 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5164 file, linenum, args[1]);
5165 err_code |= ERR_WARN;
5166 goto out;
5167 }
5168
5169 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5170 if (!newul) {
5171 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5172 err_code |= ERR_ALERT | ERR_ABORT;
5173 goto out;
5174 }
5175
5176 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5177 newul->name = strdup(args[1]);
5178
5179 if (!newul->groupusers | !newul->name) {
5180 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5181 err_code |= ERR_ALERT | ERR_ABORT;
5182 goto out;
5183 }
5184
5185 newul->next = userlist;
5186 userlist = newul;
5187
5188 } else if (!strcmp(args[0], "group")) { /* new group */
5189 int cur_arg, i;
5190 const char *err;
5191
5192 if (!*args[1]) {
5193 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5194 file, linenum, args[0]);
5195 err_code |= ERR_ALERT | ERR_FATAL;
5196 goto out;
5197 }
5198
5199 err = invalid_char(args[1]);
5200 if (err) {
5201 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5202 file, linenum, *err, args[0], args[1]);
5203 err_code |= ERR_ALERT | ERR_FATAL;
5204 goto out;
5205 }
5206
5207 for(i = 0; i < userlist->grpcnt; i++)
5208 if (!strcmp(userlist->groups[i], args[1])) {
5209 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5210 file, linenum, args[1], userlist->name);
5211 err_code |= ERR_ALERT;
5212 goto out;
5213 }
5214
5215 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5216 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5217 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5218 err_code |= ERR_ALERT | ERR_FATAL;
5219 goto out;
5220 }
5221
5222 cur_arg = 2;
5223
5224 while (*args[cur_arg]) {
5225 if (!strcmp(args[cur_arg], "users")) {
5226 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5227 cur_arg += 2;
5228 continue;
5229 } else {
5230 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5231 file, linenum, args[0]);
5232 err_code |= ERR_ALERT | ERR_FATAL;
5233 goto out;
5234 }
5235 }
5236
5237 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5238 } else if (!strcmp(args[0], "user")) { /* new user */
5239 struct auth_users *newuser;
5240 int cur_arg;
5241
5242 if (!*args[1]) {
5243 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5244 file, linenum, args[0]);
5245 err_code |= ERR_ALERT | ERR_FATAL;
5246 goto out;
5247 }
5248
5249 for (newuser = userlist->users; newuser; newuser = newuser->next)
5250 if (!strcmp(newuser->user, args[1])) {
5251 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5252 file, linenum, args[1], userlist->name);
5253 err_code |= ERR_ALERT;
5254 goto out;
5255 }
5256
5257 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5258 if (!newuser) {
5259 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5260 err_code |= ERR_ALERT | ERR_ABORT;
5261 goto out;
5262 }
5263
5264 newuser->user = strdup(args[1]);
5265
5266 newuser->next = userlist->users;
5267 userlist->users = newuser;
5268
5269 cur_arg = 2;
5270
5271 while (*args[cur_arg]) {
5272 if (!strcmp(args[cur_arg], "password")) {
5273#ifndef CONFIG_HAP_CRYPT
5274 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5275 file, linenum);
5276 err_code |= ERR_ALERT;
5277#endif
5278 newuser->pass = strdup(args[cur_arg + 1]);
5279 cur_arg += 2;
5280 continue;
5281 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5282 newuser->pass = strdup(args[cur_arg + 1]);
5283 newuser->flags |= AU_O_INSECURE;
5284 cur_arg += 2;
5285 continue;
5286 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005287 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005288 cur_arg += 2;
5289 continue;
5290 } else {
5291 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5292 file, linenum, args[0]);
5293 err_code |= ERR_ALERT | ERR_FATAL;
5294 goto out;
5295 }
5296 }
5297 } else {
5298 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5299 err_code |= ERR_ALERT | ERR_FATAL;
5300 }
5301
5302out:
5303 return err_code;
5304}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305
5306/*
5307 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005308 * Returns the error code, 0 if OK, or any combination of :
5309 * - ERR_ABORT: must abort ASAP
5310 * - ERR_FATAL: we can continue parsing but not start the service
5311 * - ERR_WARN: a warning has been emitted
5312 * - ERR_ALERT: an alert has been emitted
5313 * Only the two first ones can stop processing, the two others are just
5314 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005315 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005316int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005318 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005319 FILE *f;
5320 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005322 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005323
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324 if ((f=fopen(file,"r")) == NULL)
5325 return -1;
5326
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005327 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005328 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005329 char *end;
5330 char *args[MAX_LINE_ARGS + 1];
5331 char *line = thisline;
5332
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333 linenum++;
5334
5335 end = line + strlen(line);
5336
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005337 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5338 /* Check if we reached the limit and the last char is not \n.
5339 * Watch out for the last line without the terminating '\n'!
5340 */
5341 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005342 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005343 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005344 }
5345
Willy Tarreaubaaee002006-06-26 02:48:02 +02005346 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005347 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005348 line++;
5349
5350 arg = 0;
5351 args[arg] = line;
5352
5353 while (*line && arg < MAX_LINE_ARGS) {
5354 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5355 * C equivalent value. Other combinations left unchanged (eg: \1).
5356 */
5357 if (*line == '\\') {
5358 int skip = 0;
5359 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5360 *line = line[1];
5361 skip = 1;
5362 }
5363 else if (line[1] == 'r') {
5364 *line = '\r';
5365 skip = 1;
5366 }
5367 else if (line[1] == 'n') {
5368 *line = '\n';
5369 skip = 1;
5370 }
5371 else if (line[1] == 't') {
5372 *line = '\t';
5373 skip = 1;
5374 }
5375 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005376 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005377 unsigned char hex1, hex2;
5378 hex1 = toupper(line[2]) - '0';
5379 hex2 = toupper(line[3]) - '0';
5380 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5381 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5382 *line = (hex1<<4) + hex2;
5383 skip = 3;
5384 }
5385 else {
5386 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005387 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005388 }
5389 }
5390 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005391 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005392 end -= skip;
5393 }
5394 line++;
5395 }
5396 else if (*line == '#' || *line == '\n' || *line == '\r') {
5397 /* end of string, end of loop */
5398 *line = 0;
5399 break;
5400 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005401 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005402 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005403 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005404 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005405 line++;
5406 args[++arg] = line;
5407 }
5408 else {
5409 line++;
5410 }
5411 }
5412
5413 /* empty line */
5414 if (!**args)
5415 continue;
5416
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005417 if (*line) {
5418 /* we had to stop due to too many args.
5419 * Let's terminate the string, print the offending part then cut the
5420 * last arg.
5421 */
5422 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5423 line++;
5424 *line = '\0';
5425
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005426 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005427 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005428 err_code |= ERR_ALERT | ERR_FATAL;
5429 args[arg] = line;
5430 }
5431
Willy Tarreau540abe42007-05-02 20:50:16 +02005432 /* zero out remaining args and ensure that at least one entry
5433 * is zeroed out.
5434 */
5435 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005436 args[arg] = line;
5437 }
5438
Willy Tarreau3842f002009-06-14 11:39:52 +02005439 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005440 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005441 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005442 for (arg=0; *args[arg+1]; arg++)
5443 args[arg] = args[arg+1]; // shift args after inversion
5444 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005445 else if (!strcmp(args[0], "default")) {
5446 kwm = KWM_DEF;
5447 for (arg=0; *args[arg+1]; arg++)
5448 args[arg] = args[arg+1]; // shift args after inversion
5449 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005450
Willy Tarreau3842f002009-06-14 11:39:52 +02005451 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5452 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005453 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005454 }
5455
Willy Tarreau977b8e42006-12-29 14:19:17 +01005456 if (!strcmp(args[0], "listen") ||
5457 !strcmp(args[0], "frontend") ||
5458 !strcmp(args[0], "backend") ||
5459 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005460 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005461 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005462 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005463 cursection = strdup(args[0]);
5464 }
5465 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005466 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005467 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005468 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005469 }
5470 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005471 confsect = CFG_USERLIST;
5472 free(cursection);
5473 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005474 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005475 else if (!strcmp(args[0], "peers")) {
5476 confsect = CFG_PEERS;
5477 free(cursection);
5478 cursection = strdup(args[0]);
5479 }
5480
Willy Tarreaubaaee002006-06-26 02:48:02 +02005481 /* else it's a section keyword */
5482
5483 switch (confsect) {
5484 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005485 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005486 break;
5487 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005488 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005489 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005490 case CFG_USERLIST:
5491 err_code |= cfg_parse_users(file, linenum, args, kwm);
5492 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005493 case CFG_PEERS:
5494 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5495 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005496 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005497 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005498 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005500
5501 if (err_code & ERR_ABORT)
5502 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005503 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005504 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005505 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005506 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005507 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005508}
5509
Willy Tarreaubb925012009-07-23 13:36:36 +02005510/*
5511 * Returns the error code, 0 if OK, or any combination of :
5512 * - ERR_ABORT: must abort ASAP
5513 * - ERR_FATAL: we can continue parsing but not start the service
5514 * - ERR_WARN: a warning has been emitted
5515 * - ERR_ALERT: an alert has been emitted
5516 * Only the two first ones can stop processing, the two others are just
5517 * indicators.
5518 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005519int check_config_validity()
5520{
5521 int cfgerr = 0;
5522 struct proxy *curproxy = NULL;
5523 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005524 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005525 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005526 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005527
5528 /*
5529 * Now, check for the integrity of all that we have collected.
5530 */
5531
5532 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005533 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005534
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005535 /* first, we will invert the proxy list order */
5536 curproxy = NULL;
5537 while (proxy) {
5538 struct proxy *next;
5539
5540 next = proxy->next;
5541 proxy->next = curproxy;
5542 curproxy = proxy;
5543 if (!next)
5544 break;
5545 proxy = next;
5546 }
5547
Willy Tarreaubaaee002006-06-26 02:48:02 +02005548 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005549 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005550 err_code |= ERR_ALERT | ERR_FATAL;
5551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005552 }
5553
5554 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005555 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005556 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005557 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005558 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005559 unsigned int next_id;
5560
5561 if (!curproxy->uuid) {
5562 /* proxy ID not set, use automatic numbering with first
5563 * spare entry starting with next_pxid.
5564 */
5565 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5566 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5567 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005568 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005569 next_pxid++;
5570
Willy Tarreau55ea7572007-06-17 19:56:27 +02005571
Willy Tarreaubaaee002006-06-26 02:48:02 +02005572 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005573 /* ensure we don't keep listeners uselessly bound */
5574 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005575 curproxy = curproxy->next;
5576 continue;
5577 }
5578
Willy Tarreauff01a212009-03-15 13:46:16 +01005579 switch (curproxy->mode) {
5580 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005581 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005582 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005583 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5584 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005585 cfgerr++;
5586 }
5587
5588 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005589 Warning("config : servers will be ignored for %s '%s'.\n",
5590 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005591 break;
5592
5593 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005594 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005595 break;
5596
5597 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005598 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005599 break;
5600 }
5601
5602 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005603 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5604 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 cfgerr++;
5606 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005607
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005608 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005609 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005610 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005611 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5612 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005613 cfgerr++;
5614 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005616 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005617 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5618 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005619 cfgerr++;
5620 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621#endif
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005622 else if (curproxy->options2 & PR_O2_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005623 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5624 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005625 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005626 }
5627 }
5628 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005629 !(curproxy->options2 & PR_O2_DISPATCH)) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005630 /* If no LB algo is set in a backend, and we're not in
5631 * transparent mode, dispatch mode nor proxy mode, we
5632 * want to use balance roundrobin by default.
5633 */
5634 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5635 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005636 }
5637 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005638
Willy Tarreaud6cc5322011-03-04 17:30:54 +01005639 if (curproxy->options2 & PR_O2_DISPATCH) {
5640 curproxy->options &= ~PR_O_TRANSP;
5641 curproxy->options &= ~PR_O_HTTP_PROXY;
5642 }
5643 else if (curproxy->options & PR_O_HTTP_PROXY) {
5644 curproxy->options2 &= ~PR_O2_DISPATCH;
5645 curproxy->options &= ~PR_O_TRANSP;
5646 }
5647 else if (curproxy->options & PR_O_TRANSP) {
5648 curproxy->options2 &= ~PR_O2_DISPATCH;
5649 curproxy->options &= ~PR_O_HTTP_PROXY;
5650 }
5651
Willy Tarreau82936582007-11-30 15:20:09 +01005652 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5653 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005654 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5655 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005656 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005657 }
5658
Willy Tarreauef781042010-01-27 11:53:01 +01005659 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5660 curproxy->options &= ~PR_O2_CHK_SNDST;
5661 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5662 "send-state", proxy_type_str(curproxy), curproxy->id);
5663 err_code |= ERR_WARN;
5664 }
5665
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005666 /* if a default backend was specified, let's find it */
5667 if (curproxy->defbe.name) {
5668 struct proxy *target;
5669
Alex Williams96532db2009-11-01 21:27:13 -05005670 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005671 if (!target) {
5672 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5673 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005674 cfgerr++;
5675 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005676 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5677 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005678 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005679 } else {
5680 free(curproxy->defbe.name);
5681 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005682 /* we force the backend to be present on at least all of
5683 * the frontend's processes.
5684 */
5685 target->bind_proc = curproxy->bind_proc ?
5686 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 }
5688 }
5689
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005690 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005691 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5692 /* map jump target for ACT_SETBE in req_rep chain */
5693 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005694 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005695 struct proxy *target;
5696
Willy Tarreaua496b602006-12-17 23:15:24 +01005697 if (exp->action != ACT_SETBE)
5698 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005699
Alex Williams96532db2009-11-01 21:27:13 -05005700 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005701 if (!target) {
5702 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5703 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005704 cfgerr++;
5705 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005706 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5707 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005708 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005709 } else {
5710 free((void *)exp->replace);
5711 exp->replace = (const char *)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 Tarreaua496b602006-12-17 23:15:24 +01005717 }
5718 }
5719 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005720
5721 /* find the target proxy for 'use_backend' rules */
5722 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005723 struct proxy *target;
5724
Alex Williams96532db2009-11-01 21:27:13 -05005725 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005726
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005727 if (!target) {
5728 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5729 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005730 cfgerr++;
5731 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005732 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5733 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005734 cfgerr++;
5735 } else {
5736 free((void *)rule->be.name);
5737 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005738 /* we force the backend to be present on at least all of
5739 * the frontend's processes.
5740 */
5741 target->bind_proc = curproxy->bind_proc ?
5742 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005743 }
5744 }
5745
Emeric Brunb982a3d2010-01-04 15:45:53 +01005746 /* find the target table for 'stick' rules */
5747 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5748 struct proxy *target;
5749
Emeric Brun1d33b292010-01-04 15:47:17 +01005750 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5751 if (mrule->flags & STK_IS_STORE)
5752 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5753
Emeric Brunb982a3d2010-01-04 15:45:53 +01005754 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005755 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005756 else
5757 target = curproxy;
5758
5759 if (!target) {
5760 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5761 curproxy->id, mrule->table.name);
5762 cfgerr++;
5763 }
5764 else if (target->table.size == 0) {
5765 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5766 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5767 cfgerr++;
5768 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005769 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005770 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5771 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5772 cfgerr++;
5773 }
5774 else {
5775 free((void *)mrule->table.name);
5776 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005777 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005778 }
5779 }
5780
5781 /* find the target table for 'store response' rules */
5782 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5783 struct proxy *target;
5784
Emeric Brun1d33b292010-01-04 15:47:17 +01005785 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5786
Emeric Brunb982a3d2010-01-04 15:45:53 +01005787 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005788 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005789 else
5790 target = curproxy;
5791
5792 if (!target) {
5793 Alert("Proxy '%s': unable to find store table '%s'.\n",
5794 curproxy->id, mrule->table.name);
5795 cfgerr++;
5796 }
5797 else if (target->table.size == 0) {
5798 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5799 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5800 cfgerr++;
5801 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005802 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005803 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5804 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5805 cfgerr++;
5806 }
5807 else {
5808 free((void *)mrule->table.name);
5809 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005810 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005811 }
5812 }
5813
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005814 /* find the target table for 'tcp-request' layer 4 rules */
5815 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5816 struct proxy *target;
5817
Willy Tarreau56123282010-08-06 19:06:56 +02005818 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005819 continue;
5820
5821 if (trule->act_prm.trk_ctr.table.n)
5822 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5823 else
5824 target = curproxy;
5825
5826 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005827 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5828 curproxy->id, trule->act_prm.trk_ctr.table.n,
5829 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005830 cfgerr++;
5831 }
5832 else if (target->table.size == 0) {
5833 Alert("Proxy '%s': table '%s' used but not configured.\n",
5834 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5835 cfgerr++;
5836 }
5837 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005838 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 +02005839 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5840 cfgerr++;
5841 }
5842 else {
5843 free(trule->act_prm.trk_ctr.table.n);
5844 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005845 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005846 * to pass a list of counters to track and allocate them right here using
5847 * stktable_alloc_data_type().
5848 */
5849 }
5850 }
5851
Willy Tarreaud1f96522010-08-03 19:34:32 +02005852 /* find the target table for 'tcp-request' layer 6 rules */
5853 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5854 struct proxy *target;
5855
Willy Tarreau56123282010-08-06 19:06:56 +02005856 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005857 continue;
5858
5859 if (trule->act_prm.trk_ctr.table.n)
5860 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5861 else
5862 target = curproxy;
5863
5864 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005865 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5866 curproxy->id, trule->act_prm.trk_ctr.table.n,
5867 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005868 cfgerr++;
5869 }
5870 else if (target->table.size == 0) {
5871 Alert("Proxy '%s': table '%s' used but not configured.\n",
5872 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5873 cfgerr++;
5874 }
5875 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005876 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 +02005877 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5878 cfgerr++;
5879 }
5880 else {
5881 free(trule->act_prm.trk_ctr.table.n);
5882 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005883 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005884 * to pass a list of counters to track and allocate them right here using
5885 * stktable_alloc_data_type().
5886 */
5887 }
5888 }
5889
Emeric Brun32da3c42010-09-23 18:39:19 +02005890 if (curproxy->table.peers.name) {
5891 struct peers *curpeers = peers;
5892
5893 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5894 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5895 free((void *)curproxy->table.peers.name);
5896 curproxy->table.peers.p = peers;
5897 break;
5898 }
5899 }
5900
5901 if (!curpeers) {
5902 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5903 curproxy->id, curproxy->table.peers.name);
5904 cfgerr++;
5905 }
5906 else if (!curpeers->peers_fe) {
5907 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5908 curproxy->id, curpeers->id);
5909 cfgerr++;
5910 }
5911 }
5912
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005913 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005914 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005915 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5916 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5917 "proxy", curproxy->id);
5918 cfgerr++;
5919 goto out_uri_auth_compat;
5920 }
5921
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005922 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005923 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005924 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005925 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005926
Willy Tarreau95fa4692010-02-01 13:05:50 +01005927 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5928 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005929
5930 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005931 uri_auth_compat_req[i++] = "realm";
5932 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5933 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005934
Willy Tarreau95fa4692010-02-01 13:05:50 +01005935 uri_auth_compat_req[i++] = "unless";
5936 uri_auth_compat_req[i++] = "{";
5937 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5938 uri_auth_compat_req[i++] = "}";
5939 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005940
Willy Tarreauff011f22011-01-06 17:51:27 +01005941 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5942 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005943 cfgerr++;
5944 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005945 }
5946
Willy Tarreauff011f22011-01-06 17:51:27 +01005947 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005948
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005949 if (curproxy->uri_auth->auth_realm) {
5950 free(curproxy->uri_auth->auth_realm);
5951 curproxy->uri_auth->auth_realm = NULL;
5952 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005953
5954 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005955 }
5956out_uri_auth_compat:
5957
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005958 cfgerr += acl_find_targets(curproxy);
5959
Willy Tarreau2738a142006-07-08 17:28:09 +02005960 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005961 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005962 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005963 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005964 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005965 " | While not properly invalid, you will certainly encounter various problems\n"
5966 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005967 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005968 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005969 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005970 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005971
Willy Tarreau1fa31262007-12-03 00:36:16 +01005972 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5973 * We must still support older configurations, so let's find out whether those
5974 * parameters have been set or must be copied from contimeouts.
5975 */
5976 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005977 if (!curproxy->timeout.tarpit ||
5978 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005979 /* tarpit timeout not set. We search in the following order:
5980 * default.tarpit, curr.connect, default.connect.
5981 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005982 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005983 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005984 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005985 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005986 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005987 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005988 }
5989 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005990 (!curproxy->timeout.queue ||
5991 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005992 /* queue timeout not set. We search in the following order:
5993 * default.queue, curr.connect, default.connect.
5994 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005995 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005996 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005997 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005998 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005999 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006000 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006001 }
6002 }
6003
Willy Tarreau07a54902010-03-29 18:33:29 +02006004 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006005 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6006 curproxy->check_req = (char *)malloc(curproxy->check_len);
6007 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006008 }
6009
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006010 /* The small pools required for the capture lists */
6011 if (curproxy->nb_req_cap)
6012 curproxy->req_cap_pool = create_pool("ptrcap",
6013 curproxy->nb_req_cap * sizeof(char *),
6014 MEM_F_SHARED);
6015 if (curproxy->nb_rsp_cap)
6016 curproxy->rsp_cap_pool = create_pool("ptrcap",
6017 curproxy->nb_rsp_cap * sizeof(char *),
6018 MEM_F_SHARED);
6019
Willy Tarreau1d4154a2007-05-13 22:57:02 +02006020 curproxy->hdr_idx_pool = create_pool("hdr_idx",
6021 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6022 MEM_F_SHARED);
6023
Willy Tarreaubaaee002006-06-26 02:48:02 +02006024 /* first, we will invert the servers list order */
6025 newsrv = NULL;
6026 while (curproxy->srv) {
6027 struct server *next;
6028
6029 next = curproxy->srv->next;
6030 curproxy->srv->next = newsrv;
6031 newsrv = curproxy->srv;
6032 if (!next)
6033 break;
6034 curproxy->srv = next;
6035 }
6036
Willy Tarreaudd701652010-05-25 23:03:02 +02006037 /* assign automatic UIDs to servers which don't have one yet */
6038 next_id = 1;
6039 newsrv = curproxy->srv;
6040 while (newsrv != NULL) {
6041 if (!newsrv->puid) {
6042 /* server ID not set, use automatic numbering with first
6043 * spare entry starting with next_svid.
6044 */
6045 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6046 newsrv->conf.id.key = newsrv->puid = next_id;
6047 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6048 }
6049 next_id++;
6050 newsrv = newsrv->next;
6051 }
6052
Willy Tarreau20697042007-11-15 23:26:18 +01006053 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006054 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006055
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006056 /* We have to initialize the server lookup mechanism depending
6057 * on what LB algorithm was choosen.
6058 */
6059
6060 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6061 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6062 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006063 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6064 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6065 init_server_map(curproxy);
6066 } else {
6067 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6068 fwrr_init_server_groups(curproxy);
6069 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006070 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006071
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006072 case BE_LB_KIND_LC:
6073 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006074 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006075 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006076
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006077 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006078 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6079 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6080 chash_init_server_tree(curproxy);
6081 } else {
6082 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6083 init_server_map(curproxy);
6084 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006085 break;
6086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006087
6088 if (curproxy->options & PR_O_LOGASAP)
6089 curproxy->to_log &= ~LW_BYTES;
6090
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006091 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6092 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6093 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6094 proxy_type_str(curproxy), curproxy->id);
6095 err_code |= ERR_WARN;
6096 }
6097
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006098 if (curproxy->mode != PR_MODE_HTTP) {
6099 int optnum;
6100
6101 if (curproxy->options & PR_O_COOK_ANY) {
6102 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6103 proxy_type_str(curproxy), curproxy->id);
6104 err_code |= ERR_WARN;
6105 }
6106
6107 if (curproxy->uri_auth) {
6108 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6109 proxy_type_str(curproxy), curproxy->id);
6110 err_code |= ERR_WARN;
6111 curproxy->uri_auth = NULL;
6112 }
6113
6114 if (curproxy->options & PR_O_FWDFOR) {
6115 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6116 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6117 err_code |= ERR_WARN;
6118 curproxy->options &= ~PR_O_FWDFOR;
6119 }
6120
6121 if (curproxy->options & PR_O_ORGTO) {
6122 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6123 "originalto", proxy_type_str(curproxy), curproxy->id);
6124 err_code |= ERR_WARN;
6125 curproxy->options &= ~PR_O_ORGTO;
6126 }
6127
6128 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6129 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6130 (curproxy->cap & cfg_opts[optnum].cap) &&
6131 (curproxy->options & cfg_opts[optnum].val)) {
6132 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6133 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6134 err_code |= ERR_WARN;
6135 curproxy->options &= ~cfg_opts[optnum].val;
6136 }
6137 }
6138
6139 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6140 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6141 (curproxy->cap & cfg_opts2[optnum].cap) &&
6142 (curproxy->options2 & cfg_opts2[optnum].val)) {
6143 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6144 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6145 err_code |= ERR_WARN;
6146 curproxy->options2 &= ~cfg_opts2[optnum].val;
6147 }
6148 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006149
Willy Tarreauefa5f512010-03-30 20:13:29 +02006150#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006151 if (curproxy->bind_hdr_occ) {
6152 curproxy->bind_hdr_occ = 0;
6153 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6154 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6155 err_code |= ERR_WARN;
6156 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006157#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006158 }
6159
Willy Tarreaubaaee002006-06-26 02:48:02 +02006160 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006161 * ensure that we're not cross-dressing a TCP server into HTTP.
6162 */
6163 newsrv = curproxy->srv;
6164 while (newsrv != NULL) {
6165 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006166 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6167 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006168 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006169 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006170
Willy Tarreauefa5f512010-03-30 20:13:29 +02006171#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006172 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6173 newsrv->bind_hdr_occ = 0;
6174 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6175 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6176 err_code |= ERR_WARN;
6177 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006178#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006179 newsrv = newsrv->next;
6180 }
6181
6182 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006183 * If this server supports a maxconn parameter, it needs a dedicated
6184 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006185 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006186 */
6187 newsrv = curproxy->srv;
6188 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006189 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006190 /* Only 'minconn' was specified, or it was higher than or equal
6191 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6192 * this will avoid further useless expensive computations.
6193 */
6194 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006195 } else if (newsrv->maxconn && !newsrv->minconn) {
6196 /* minconn was not specified, so we set it to maxconn */
6197 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006198 }
6199
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006200 if (newsrv->trackit) {
6201 struct proxy *px;
6202 struct server *srv;
6203 char *pname, *sname;
6204
6205 pname = newsrv->trackit;
6206 sname = strrchr(pname, '/');
6207
6208 if (sname)
6209 *sname++ = '\0';
6210 else {
6211 sname = pname;
6212 pname = NULL;
6213 }
6214
6215 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006216 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006217 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006218 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6219 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006220 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006221 cfgerr++;
6222 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006223 }
6224 } else
6225 px = curproxy;
6226
6227 srv = findserver(px, sname);
6228 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006229 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6230 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006231 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006232 cfgerr++;
6233 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006234 }
6235
6236 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006237 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006238 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006239 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006240 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006241 cfgerr++;
6242 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006243 }
6244
6245 if (curproxy != px &&
6246 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006247 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006248 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006249 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006250 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006251 cfgerr++;
6252 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006253 }
6254
6255 newsrv->tracked = srv;
6256 newsrv->tracknext = srv->tracknext;
6257 srv->tracknext = newsrv;
6258
6259 free(newsrv->trackit);
6260 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006261 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006262 newsrv = newsrv->next;
6263 }
6264
Willy Tarreauc1a21672009-08-16 22:37:44 +02006265 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006266 curproxy->accept = frontend_accept;
6267
Willy Tarreauc1a21672009-08-16 22:37:44 +02006268 if (curproxy->tcp_req.inspect_delay ||
6269 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006270 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006271
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006272 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006273 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006274 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006275 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006276
6277 /* both TCP and HTTP must check switching rules */
6278 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6279 }
6280
6281 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006282 if (curproxy->tcp_req.inspect_delay ||
6283 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6284 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6285
Emeric Brun97679e72010-09-23 17:56:44 +02006286 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6287 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6288
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006289 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006290 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006291 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006292 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006293
6294 /* If the backend does requires RDP cookie persistence, we have to
6295 * enable the corresponding analyser.
6296 */
6297 if (curproxy->options2 & PR_O2_RDPC_PRST)
6298 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6299 }
6300
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006301 listener = NULL;
6302 while (curproxy->listen) {
6303 struct listener *next;
6304
6305 next = curproxy->listen->next;
6306 curproxy->listen->next = listener;
6307 listener = curproxy->listen;
6308
6309 if (!next)
6310 break;
6311
6312 curproxy->listen = next;
6313 }
6314
Willy Tarreaue6b98942007-10-29 01:09:36 +01006315 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006316 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006317 listener = curproxy->listen;
6318 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006319 if (!listener->luid) {
6320 /* listener ID not set, use automatic numbering with first
6321 * spare entry starting with next_luid.
6322 */
6323 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6324 listener->conf.id.key = listener->luid = next_id;
6325 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006326 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006327 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006328
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006329 /* enable separate counters */
6330 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6331 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6332 if (!listener->name) {
6333 sprintf(trash, "sock-%d", listener->luid);
6334 listener->name = strdup(trash);
6335 }
6336 }
6337
Willy Tarreaue6b98942007-10-29 01:09:36 +01006338 if (curproxy->options & PR_O_TCP_NOLING)
6339 listener->options |= LI_O_NOLINGER;
6340 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006341 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006342 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006343 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006344 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006345 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006346 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006347
Willy Tarreau8a956912010-10-15 14:27:08 +02006348 if (listener->options & LI_O_ACC_PROXY)
6349 listener->analysers |= AN_REQ_DECODE_PROXY;
6350
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006351 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6352 listener->options |= LI_O_TCP_RULES;
6353
Willy Tarreaude3041d2010-05-31 10:56:17 +02006354 if (curproxy->mon_mask.s_addr)
6355 listener->options |= LI_O_CHK_MONNET;
6356
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006357 /* smart accept mode is automatic in HTTP mode */
6358 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6359 (curproxy->mode == PR_MODE_HTTP &&
6360 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6361 listener->options |= LI_O_NOQUICKACK;
6362
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006363 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006364 listener = listener->next;
6365 }
6366
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006367 /* Check multi-process mode compatibility for the current proxy */
6368 if (global.nbproc > 1) {
6369 int nbproc = 0;
6370 if (curproxy->bind_proc) {
6371 int proc;
6372 for (proc = 0; proc < global.nbproc; proc++) {
6373 if (curproxy->bind_proc & (1 << proc)) {
6374 nbproc++;
6375 }
6376 }
6377 } else {
6378 nbproc = global.nbproc;
6379 }
6380 if (curproxy->table.peers.name) {
6381 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6382 curproxy->id);
6383 cfgerr++;
6384 }
6385 if (nbproc > 1) {
6386 if (curproxy->uri_auth) {
6387 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6388 curproxy->id);
6389 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6390 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6391 curproxy->id);
6392 }
6393 }
6394 if (curproxy->appsession_name) {
6395 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6396 curproxy->id);
6397 }
6398 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6399 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6400 curproxy->id);
6401 }
6402 }
6403 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006404
6405 /* create the task associated with the proxy */
6406 curproxy->task = task_new();
6407 if (curproxy->task) {
6408 curproxy->task->context = curproxy;
6409 curproxy->task->process = manage_proxy;
6410 /* no need to queue, it will be done automatically if some
6411 * listener gets limited.
6412 */
6413 curproxy->task->expire = TICK_ETERNITY;
6414 } else {
6415 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6416 curproxy->id);
6417 cfgerr++;
6418 }
6419
Willy Tarreaubaaee002006-06-26 02:48:02 +02006420 curproxy = curproxy->next;
6421 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006422
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006423 /* Check multi-process mode compatibility */
6424 if (global.nbproc > 1) {
6425 if (global.stats_fe) {
6426 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6427 }
6428 }
6429
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006430 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6431 struct auth_users *curuser;
6432 int g;
6433
6434 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6435 unsigned int group_mask = 0;
6436 char *group = NULL;
6437
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006438 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006439 continue;
6440
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006441 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006442
6443 for (g = 0; g < curuserlist->grpcnt; g++)
6444 if (!strcmp(curuserlist->groups[g], group))
6445 break;
6446
6447 if (g == curuserlist->grpcnt) {
6448 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6449 curuserlist->name, group, curuser->user);
6450 err_code |= ERR_ALERT | ERR_FATAL;
6451 goto out;
6452 }
6453
6454 group_mask |= (1 << g);
6455 }
6456
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006457 free(curuser->u.groups);
6458 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006459 }
6460
6461 for (g = 0; g < curuserlist->grpcnt; g++) {
6462 char *user = NULL;
6463
6464 if (!curuserlist->groupusers[g])
6465 continue;
6466
6467 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6468 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6469 if (!strcmp(curuser->user, user))
6470 break;
6471
6472 if (!curuser) {
6473 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6474 curuserlist->name, user, curuserlist->groups[g]);
6475 err_code |= ERR_ALERT | ERR_FATAL;
6476 goto out;
6477 }
6478
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006479 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006480 }
6481
6482 free(curuserlist->groupusers[g]);
6483 }
6484
6485 free(curuserlist->groupusers);
6486
6487#ifdef DEBUG_AUTH
6488 for (g = 0; g < curuserlist->grpcnt; g++) {
6489 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6490
6491 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6492 if (curuser->group_mask & (1 << g))
6493 fprintf(stderr, " %s", curuser->user);
6494 }
6495
6496 fprintf(stderr, "\n");
6497 }
6498#endif
6499
Willy Tarreaufbb78422011-06-05 15:38:35 +02006500 }
6501
6502 /* automatically compute fullconn if not set. We must not do it in the
6503 * loop above because cross-references are not yet fully resolved.
6504 */
6505 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6506 /* If <fullconn> is not set, let's set it to 10% of the sum of
6507 * the possible incoming frontend's maxconns.
6508 */
6509 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6510 struct proxy *fe;
6511 int total = 0;
6512
6513 /* sum up the number of maxconns of frontends which
6514 * reference this backend at least once or which are
6515 * the same one ('listen').
6516 */
6517 for (fe = proxy; fe; fe = fe->next) {
6518 struct switching_rule *rule;
6519 struct hdr_exp *exp;
6520 int found = 0;
6521
6522 if (!(fe->cap & PR_CAP_FE))
6523 continue;
6524
6525 if (fe == curproxy) /* we're on a "listen" instance */
6526 found = 1;
6527
6528 if (fe->defbe.be == curproxy) /* "default_backend" */
6529 found = 1;
6530
6531 /* check if a "use_backend" rule matches */
6532 if (!found) {
6533 list_for_each_entry(rule, &fe->switching_rules, list) {
6534 if (rule->be.backend == curproxy) {
6535 found = 1;
6536 break;
6537 }
6538 }
6539 }
6540
6541 /* check if a "reqsetbe" rule matches */
6542 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6543 if (exp->action == ACT_SETBE &&
6544 (struct proxy *)exp->replace == curproxy) {
6545 found = 1;
6546 break;
6547 }
6548 }
6549
6550 /* now we've checked all possible ways to reference a backend
6551 * from a frontend.
6552 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006553 if (!found)
6554 continue;
6555 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006556 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006557 /* we have the sum of the maxconns in <total>. We only
6558 * keep 10% of that sum to set the default fullconn, with
6559 * a hard minimum of 1 (to avoid a divide by zero).
6560 */
6561 curproxy->fullconn = (total + 9) / 10;
6562 if (!curproxy->fullconn)
6563 curproxy->fullconn = 1;
6564 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006565 }
6566
Willy Tarreau056f5682010-06-06 15:51:11 +02006567 /* initialize stick-tables on backend capable proxies. This must not
6568 * be done earlier because the data size may be discovered while parsing
6569 * other proxies.
6570 */
6571 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006572 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006573
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006574 /*
6575 * Recount currently required checks.
6576 */
6577
6578 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6579 int optnum;
6580
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006581 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6582 if (curproxy->options & cfg_opts[optnum].val)
6583 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006584
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006585 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6586 if (curproxy->options2 & cfg_opts2[optnum].val)
6587 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006588 }
6589
Willy Tarreaubb925012009-07-23 13:36:36 +02006590 if (cfgerr > 0)
6591 err_code |= ERR_ALERT | ERR_FATAL;
6592 out:
6593 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006594}
6595
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006596/*
6597 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6598 * parsing sessions.
6599 */
6600void cfg_register_keywords(struct cfg_kw_list *kwl)
6601{
6602 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6603}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006604
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006605/*
6606 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6607 */
6608void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6609{
6610 LIST_DEL(&kwl->list);
6611 LIST_INIT(&kwl->list);
6612}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006613
6614/*
6615 * Local variables:
6616 * c-indent-level: 8
6617 * c-basic-offset: 8
6618 * End:
6619 */