blob: 2a085944407063fab110de0b0dece11fd6c456ca [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020047#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020048#include <proto/lb_fwlc.h>
49#include <proto/lb_fwrr.h>
50#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010052#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020053#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010054#include <proto/protocols.h>
55#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020056#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010057#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010058#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020059#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010061#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010063#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064
65
Willy Tarreauf3c69202006-07-09 16:42:34 +020066/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
67 * ssl-hello-chk option to ensure that the remote server speaks SSL.
68 *
69 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
70 */
71const char sslv3_client_hello_pkt[] = {
72 "\x16" /* ContentType : 0x16 = Hanshake */
73 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
74 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
75 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
76 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
77 "\x03\x00" /* Hello Version : 0x0300 = v3 */
78 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
79 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
80 "\x00" /* Session ID length : empty (no session ID) */
81 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
82 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
83 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
84 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
85 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
86 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
87 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
88 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
89 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
90 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
91 "\x00\x38" "\x00\x39" "\x00\x3A"
92 "\x01" /* Compression Length : 0x01 = 1 byte for types */
93 "\x00" /* Compression Type : 0x00 = NULL compression */
94};
95
Willy Tarreau3842f002009-06-14 11:39:52 +020096/* various keyword modifiers */
97enum kw_mod {
98 KWM_STD = 0, /* normal */
99 KWM_NO, /* "no" prefixed before the keyword */
100 KWM_DEF, /* "default" prefixed before the keyword */
101};
102
Willy Tarreau13943ab2006-12-31 00:24:10 +0100103/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100104struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100105 const char *name;
106 unsigned int val;
107 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100108 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100109 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100110};
111
112/* proxy->options */
113static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100115 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
116 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
117 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
118 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
119 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
120 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
121 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
122 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
125 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
127 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
128 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
129 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
130 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100131#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100132 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100133#else
134 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100135#endif
136
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100137 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138};
139
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140/* proxy->options2 */
141static const struct cfg_opt cfg_opts2[] =
142{
143#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
145 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100147#else
148 { "splice-request", 0, 0, 0, 0 },
149 { "splice-response", 0, 0, 0, 0 },
150 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
153 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
154 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
155 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
156 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
157 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
158 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
160 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
161 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200162 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200163 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100164 { NULL, 0, 0, 0 }
165};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166
Willy Tarreau6daf3432008-01-22 16:44:08 +0100167static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
169int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100170int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200172/* List head of all known configuration keywords */
173static struct cfg_kw_list cfg_keywords = {
174 .list = LIST_HEAD_INIT(cfg_keywords.list)
175};
176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177/*
178 * converts <str> to a list of listeners which are dynamically allocated.
179 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
180 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
181 * - <port> is a numerical port from 1 to 65535 ;
182 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
183 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200184 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100186static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187{
188 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100189 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200190 int port, end;
191
192 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 while (next && *next) {
195 struct sockaddr_storage ss;
196
197 str = next;
198 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100199 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 *next++ = 0;
201 }
202
Emeric Bruned760922010-10-22 17:59:25 +0200203 if (*str == '/') {
204 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
205 /* so compute max path */
206 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
207 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
Emeric Bruned760922010-10-22 17:59:25 +0200209 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100210 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
211 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200212 goto fail;
213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200216 ss.ss_family = AF_UNIX;
217 if (global.unix_bind.prefix) {
218 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
219 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 }
Emeric Bruned760922010-10-22 17:59:25 +0200221 else {
222 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
223 }
224 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 }
226 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100227 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100229 ss2 = str2sa_range(str, &port, &end);
230 if (!ss2) {
231 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
232 file, line, str);
233 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 if (!port) {
237 Alert("parsing [%s:%d] : missing port number: '%s'\n",
238 file, line, str);
239 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 /* OK the address looks correct */
243 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Emeric Bruned760922010-10-22 17:59:25 +0200245 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100246 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
247 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200248 goto fail;
249 }
250
251 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100252 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
253 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200254 goto fail;
255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256 }
257
258 for (; port <= end; port++) {
259 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200260 l->next = curproxy->listen;
261 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
263 l->fd = -1;
264 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100265 l->state = LI_INIT;
266
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100267 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100269 tcpv4_add_listener(l);
270 }
Emeric Bruned760922010-10-22 17:59:25 +0200271 else if (ss.ss_family == AF_INET6) {
272 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
273 tcpv6_add_listener(l);
274 }
275 else {
276 l->perm.ux.gid = l->perm.ux.uid = -1;
277 l->perm.ux.mode = 0;
278 uxst_add_listener(l);
279 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200280
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200281 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100282 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283 } /* end for(port) */
284 } /* end while(next) */
285 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200286 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200287 fail:
288 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200289 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290}
291
Willy Tarreau977b8e42006-12-29 14:19:17 +0100292/*
293 * Sends a warning if proxy <proxy> does not have at least one of the
294 * capabilities in <cap>. An optionnal <hint> may be added at the end
295 * of the warning to help the user. Returns 1 if a warning was emitted
296 * or 0 if the condition is valid.
297 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100298int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299{
300 char *msg;
301
302 switch (cap) {
303 case PR_CAP_BE: msg = "no backend"; break;
304 case PR_CAP_FE: msg = "no frontend"; break;
305 case PR_CAP_RS: msg = "no ruleset"; break;
306 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
307 default: msg = "not enough"; break;
308 }
309
310 if (!(proxy->cap & cap)) {
311 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100312 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100313 return 1;
314 }
315 return 0;
316}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317
Willy Tarreau61d18892009-03-31 10:49:21 +0200318/* Report a warning if a rule is placed after a 'block' rule.
319 * Return 1 if the warning has been emitted, otherwise 0.
320 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100321int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200322{
323 if (!LIST_ISEMPTY(&proxy->block_cond)) {
324 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
325 file, line, arg);
326 return 1;
327 }
328 return 0;
329}
330
331/* Report a warning if a rule is placed after a reqrewrite rule.
332 * Return 1 if the warning has been emitted, otherwise 0.
333 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100334int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200335{
336 if (proxy->req_exp) {
337 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
338 file, line, arg);
339 return 1;
340 }
341 return 0;
342}
343
344/* Report a warning if a rule is placed after a reqadd rule.
345 * Return 1 if the warning has been emitted, otherwise 0.
346 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100347int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200348{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100349 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200350 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
351 file, line, arg);
352 return 1;
353 }
354 return 0;
355}
356
357/* Report a warning if a rule is placed after a redirect rule.
358 * Return 1 if the warning has been emitted, otherwise 0.
359 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100360int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200361{
362 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
363 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
364 file, line, arg);
365 return 1;
366 }
367 return 0;
368}
369
370/* Report a warning if a rule is placed after a 'use_backend' rule.
371 * Return 1 if the warning has been emitted, otherwise 0.
372 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100373int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200374{
375 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
376 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
377 file, line, arg);
378 return 1;
379 }
380 return 0;
381}
382
383/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
387 warnif_rule_after_reqadd(proxy, file, line, arg) ||
388 warnif_rule_after_redirect(proxy, file, line, arg) ||
389 warnif_rule_after_use_backend(proxy, file, line, arg);
390}
391
392/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
395 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
396 warnif_rule_after_redirect(proxy, file, line, arg) ||
397 warnif_rule_after_use_backend(proxy, file, line, arg);
398}
399
400/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 return warnif_rule_after_redirect(proxy, file, line, arg) ||
404 warnif_rule_after_use_backend(proxy, file, line, arg);
405}
406
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100407/* Report it if a request ACL condition uses some response-only parameters. It
408 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
409 * Note that <cond> may be NULL and then will be ignored.
410 */
411static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
412{
413 struct acl *acl;
414
415 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
416 return 0;
417
418 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
419 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
420 file, line, acl ? acl->name : "(unknown)");
421 return ERR_WARN;
422}
423
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100424/* Report it if a request ACL condition uses some request-only volatile parameters.
425 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
426 * Note that <cond> may be NULL and then will be ignored.
427 */
428static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
429{
430 struct acl *acl;
431
432 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
433 return 0;
434
435 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
436 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
437 file, line, acl ? acl->name : "(unknown)");
438 return ERR_WARN;
439}
440
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100441
Willy Tarreaubaaee002006-06-26 02:48:02 +0200442/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 * parse a line in a <global> section. Returns the error code, 0 if OK, or
444 * any combination of :
445 * - ERR_ABORT: must abort ASAP
446 * - ERR_FATAL: we can continue parsing but not start the service
447 * - ERR_WARN: a warning has been emitted
448 * - ERR_ALERT: an alert has been emitted
449 * Only the two first ones can stop processing, the two others are just
450 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200451 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200452int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453{
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455
456 if (!strcmp(args[0], "global")) { /* new section */
457 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200459 }
460 else if (!strcmp(args[0], "daemon")) {
461 global.mode |= MODE_DAEMON;
462 }
463 else if (!strcmp(args[0], "debug")) {
464 global.mode |= MODE_DEBUG;
465 }
466 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100467 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200469 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100470 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200471 }
472 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100473 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100476 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200477 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100478 else if (!strcmp(args[0], "nosplice")) {
479 global.tune.options &= ~GTUNE_USE_SPLICE;
480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481 else if (!strcmp(args[0], "quiet")) {
482 global.mode |= MODE_QUIET;
483 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200484 else if (!strcmp(args[0], "tune.maxpollevents")) {
485 if (global.tune.maxpollevents != 0) {
486 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200487 err_code |= ERR_ALERT;
488 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200489 }
490 if (*(args[1]) == 0) {
491 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200492 err_code |= ERR_ALERT | ERR_FATAL;
493 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200494 }
495 global.tune.maxpollevents = atol(args[1]);
496 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100497 else if (!strcmp(args[0], "tune.maxaccept")) {
498 if (global.tune.maxaccept != 0) {
499 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200500 err_code |= ERR_ALERT;
501 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100502 }
503 if (*(args[1]) == 0) {
504 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100507 }
508 global.tune.maxaccept = atol(args[1]);
509 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200510 else if (!strcmp(args[0], "tune.chksize")) {
511 if (*(args[1]) == 0) {
512 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
513 err_code |= ERR_ALERT | ERR_FATAL;
514 goto out;
515 }
516 global.tune.chksize = atol(args[1]);
517 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200518 else if (!strcmp(args[0], "tune.bufsize")) {
519 if (*(args[1]) == 0) {
520 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT | ERR_FATAL;
522 goto out;
523 }
524 global.tune.bufsize = atol(args[1]);
525 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
526 global.tune.maxrewrite = global.tune.bufsize / 2;
527 }
528 else if (!strcmp(args[0], "tune.maxrewrite")) {
529 if (*(args[1]) == 0) {
530 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
531 err_code |= ERR_ALERT | ERR_FATAL;
532 goto out;
533 }
534 global.tune.maxrewrite = atol(args[1]);
535 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
536 global.tune.maxrewrite = global.tune.bufsize / 2;
537 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100538 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
539 if (global.tune.client_rcvbuf != 0) {
540 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
541 err_code |= ERR_ALERT;
542 goto out;
543 }
544 if (*(args[1]) == 0) {
545 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
546 err_code |= ERR_ALERT | ERR_FATAL;
547 goto out;
548 }
549 global.tune.client_rcvbuf = atol(args[1]);
550 }
551 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
552 if (global.tune.server_rcvbuf != 0) {
553 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT;
555 goto out;
556 }
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.server_rcvbuf = atol(args[1]);
563 }
564 else if (!strcmp(args[0], "tune.sndbuf.client")) {
565 if (global.tune.client_sndbuf != 0) {
566 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
567 err_code |= ERR_ALERT;
568 goto out;
569 }
570 if (*(args[1]) == 0) {
571 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
572 err_code |= ERR_ALERT | ERR_FATAL;
573 goto out;
574 }
575 global.tune.client_sndbuf = atol(args[1]);
576 }
577 else if (!strcmp(args[0], "tune.sndbuf.server")) {
578 if (global.tune.server_sndbuf != 0) {
579 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT;
581 goto out;
582 }
583 if (*(args[1]) == 0) {
584 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
585 err_code |= ERR_ALERT | ERR_FATAL;
586 goto out;
587 }
588 global.tune.server_sndbuf = atol(args[1]);
589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 else if (!strcmp(args[0], "uid")) {
591 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200592 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200593 err_code |= ERR_ALERT;
594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
596 if (*(args[1]) == 0) {
597 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200598 err_code |= ERR_ALERT | ERR_FATAL;
599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 }
601 global.uid = atol(args[1]);
602 }
603 else if (!strcmp(args[0], "gid")) {
604 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200605 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200606 err_code |= ERR_ALERT;
607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 }
609 if (*(args[1]) == 0) {
610 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200611 err_code |= ERR_ALERT | ERR_FATAL;
612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 }
614 global.gid = atol(args[1]);
615 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200616 /* user/group name handling */
617 else if (!strcmp(args[0], "user")) {
618 struct passwd *ha_user;
619 if (global.uid != 0) {
620 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
622 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200623 }
624 errno = 0;
625 ha_user = getpwnam(args[1]);
626 if (ha_user != NULL) {
627 global.uid = (int)ha_user->pw_uid;
628 }
629 else {
630 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200631 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200632 }
633 }
634 else if (!strcmp(args[0], "group")) {
635 struct group *ha_group;
636 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200637 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200638 err_code |= ERR_ALERT;
639 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200640 }
641 errno = 0;
642 ha_group = getgrnam(args[1]);
643 if (ha_group != NULL) {
644 global.gid = (int)ha_group->gr_gid;
645 }
646 else {
647 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200648 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200649 }
650 }
651 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 else if (!strcmp(args[0], "nbproc")) {
653 if (global.nbproc != 0) {
654 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200655 err_code |= ERR_ALERT;
656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 }
658 if (*(args[1]) == 0) {
659 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT | ERR_FATAL;
661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 }
663 global.nbproc = atol(args[1]);
664 }
665 else if (!strcmp(args[0], "maxconn")) {
666 if (global.maxconn != 0) {
667 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200668 err_code |= ERR_ALERT;
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 }
671 if (*(args[1]) == 0) {
672 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT | ERR_FATAL;
674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 }
676 global.maxconn = atol(args[1]);
677#ifdef SYSTEM_MAXCONN
678 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
679 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
680 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200681 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
683#endif /* SYSTEM_MAXCONN */
684 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100685 else if (!strcmp(args[0], "maxpipes")) {
686 if (global.maxpipes != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT;
689 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100695 }
696 global.maxpipes = atol(args[1]);
697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 else if (!strcmp(args[0], "ulimit-n")) {
699 if (global.rlimit_nofile != 0) {
700 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT;
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 }
704 if (*(args[1]) == 0) {
705 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200708 }
709 global.rlimit_nofile = atol(args[1]);
710 }
711 else if (!strcmp(args[0], "chroot")) {
712 if (global.chroot != NULL) {
713 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200714 err_code |= ERR_ALERT;
715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716 }
717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722 global.chroot = strdup(args[1]);
723 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200724 else if (!strcmp(args[0], "description")) {
725 int i, len=0;
726 char *d;
727
728 if (!*args[1]) {
729 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
730 file, linenum, args[0]);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734
735 for(i=1; *args[i]; i++)
736 len += strlen(args[i])+1;
737
738 if (global.desc)
739 free(global.desc);
740
741 global.desc = d = (char *)calloc(1, len);
742
743 d += sprintf(d, "%s", args[1]);
744 for(i=2; *args[i]; i++)
745 d += sprintf(d, " %s", args[i]);
746 }
747 else if (!strcmp(args[0], "node")) {
748 int i;
749 char c;
750
751 for (i=0; args[1][i]; i++) {
752 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100753 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
754 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200755 break;
756 }
757
758 if (!i || args[1][i]) {
759 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
760 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
761 file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765
766 if (global.node)
767 free(global.node);
768
769 global.node = strdup(args[1]);
770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 else if (!strcmp(args[0], "pidfile")) {
772 if (global.pidfile != NULL) {
773 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT;
775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 }
782 global.pidfile = strdup(args[1]);
783 }
Emeric Bruned760922010-10-22 17:59:25 +0200784 else if (!strcmp(args[0], "unix-bind")) {
785 int cur_arg = 1;
786 while (*(args[cur_arg])) {
787 if (!strcmp(args[cur_arg], "prefix")) {
788 if (global.unix_bind.prefix != NULL) {
789 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
790 err_code |= ERR_ALERT;
791 cur_arg += 2;
792 continue;
793 }
794
795 if (*(args[cur_arg+1]) == 0) {
796 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800 global.unix_bind.prefix = strdup(args[cur_arg+1]);
801 cur_arg += 2;
802 continue;
803 }
804
805 if (!strcmp(args[cur_arg], "mode")) {
806
807 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
808 cur_arg += 2;
809 continue;
810 }
811
812 if (!strcmp(args[cur_arg], "uid")) {
813
814 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
815 cur_arg += 2;
816 continue;
817 }
818
819 if (!strcmp(args[cur_arg], "gid")) {
820
821 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
822 cur_arg += 2;
823 continue;
824 }
825
826 if (!strcmp(args[cur_arg], "user")) {
827 struct passwd *user;
828
829 user = getpwnam(args[cur_arg + 1]);
830 if (!user) {
831 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
832 file, linenum, args[0], args[cur_arg + 1 ]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
836
837 global.unix_bind.ux.uid = user->pw_uid;
838 cur_arg += 2;
839 continue;
840 }
841
842 if (!strcmp(args[cur_arg], "group")) {
843 struct group *group;
844
845 group = getgrnam(args[cur_arg + 1]);
846 if (!group) {
847 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
848 file, linenum, args[0], args[cur_arg + 1 ]);
849 err_code |= ERR_ALERT | ERR_FATAL;
850 goto out;
851 }
852
853 global.unix_bind.ux.gid = group->gr_gid;
854 cur_arg += 2;
855 continue;
856 }
857
858 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
859 file, linenum, args[0]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
862 }
863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200864 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100865 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200866 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867
868 if (*(args[1]) == 0 || *(args[2]) == 0) {
869 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872 }
873
874 facility = get_log_facility(args[2]);
875 if (facility < 0) {
876 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200877 err_code |= ERR_ALERT | ERR_FATAL;
878 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879 }
880
881 level = 7; /* max syslog level = debug */
882 if (*(args[3])) {
883 level = get_log_level(args[3]);
884 if (level < 0) {
885 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200886 err_code |= ERR_ALERT | ERR_FATAL;
887 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888 }
889 }
890
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200891 minlvl = 0; /* limit syslog level to this level (emerg) */
892 if (*(args[4])) {
893 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200894 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200895 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200896 err_code |= ERR_ALERT | ERR_FATAL;
897 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200898 }
899 }
900
Robert Tsai81ae1952007-12-05 10:47:29 +0100901 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100902 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100903 if (!sk) {
904 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100905 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100909 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100910 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100911 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100912 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100913 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100917 logsrv.addr = *sk;
918 if (!get_host_port(&logsrv.addr))
919 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921
922 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100923 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 global.logfac1 = facility;
925 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200926 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100929 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 global.logfac2 = facility;
931 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200932 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 }
934 else {
935 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200936 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200938 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100939 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
940 char *name;
941 int len;
942
943 if (global.log_send_hostname != NULL) {
944 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
945 err_code |= ERR_ALERT;
946 goto out;
947 }
948
949 if (*(args[1]))
950 name = args[1];
951 else
952 name = hostname;
953
954 len = strlen(name);
955
956 /* We'll add a space after the name to respect the log format */
957 free(global.log_send_hostname);
958 global.log_send_hostname = malloc(len + 2);
959 snprintf(global.log_send_hostname, len + 2, "%s ", name);
960 }
Kevinm48936af2010-12-22 16:08:21 +0000961 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
962 if (*(args[1]) == 0) {
963 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
966 }
967 free(global.log_tag);
968 global.log_tag = strdup(args[1]);
969 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200970 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
971 if (global.spread_checks != 0) {
972 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200973 err_code |= ERR_ALERT;
974 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200975 }
976 if (*(args[1]) == 0) {
977 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200980 }
981 global.spread_checks = atol(args[1]);
982 if (global.spread_checks < 0 || global.spread_checks > 50) {
983 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200984 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 }
987 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200988 struct cfg_kw_list *kwl;
989 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200990 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200991
992 list_for_each_entry(kwl, &cfg_keywords.list, list) {
993 for (index = 0; kwl->kw[index].kw != NULL; index++) {
994 if (kwl->kw[index].section != CFG_GLOBAL)
995 continue;
996 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
997 /* prepare error message just in case */
998 snprintf(trash, sizeof(trash),
999 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001000 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1001 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001002 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001003 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001004 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001005 else if (rc > 0) {
1006 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001007 err_code |= ERR_WARN;
1008 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001009 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001010 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001011 }
1012 }
1013 }
1014
Willy Tarreaubaaee002006-06-26 02:48:02 +02001015 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001016 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001018
Willy Tarreau058e9072009-07-20 09:30:05 +02001019 out:
1020 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021}
1022
Willy Tarreau97cb7802010-01-03 20:23:58 +01001023/* Perform the most basic initialization of a proxy :
1024 * memset(), list_init(*), reset_timeouts(*).
1025 */
1026static void init_new_proxy(struct proxy *p)
1027{
1028 memset(p, 0, sizeof(struct proxy));
1029 LIST_INIT(&p->pendconns);
1030 LIST_INIT(&p->acl);
Willy Tarreauff011f22011-01-06 17:51:27 +01001031 LIST_INIT(&p->http_req_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001032 LIST_INIT(&p->block_cond);
1033 LIST_INIT(&p->redirect_rules);
1034 LIST_INIT(&p->mon_fail_cond);
1035 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001036 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +01001037 LIST_INIT(&p->sticking_rules);
1038 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001039 LIST_INIT(&p->tcp_req.inspect_rules);
Emeric Brun97679e72010-09-23 17:56:44 +02001040 LIST_INIT(&p->tcp_rep.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +02001041 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01001042 LIST_INIT(&p->req_add);
1043 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001044
1045 /* Timeouts are defined as -1 */
1046 proxy_reset_timeouts(p);
Emeric Brun97679e72010-09-23 17:56:44 +02001047 p->tcp_rep.inspect_delay = TICK_ETERNITY;
Willy Tarreau97cb7802010-01-03 20:23:58 +01001048}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001050void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001052 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 defproxy.mode = PR_MODE_TCP;
1054 defproxy.state = PR_STNEW;
1055 defproxy.maxconn = cfg_maxpconn;
1056 defproxy.conn_retries = CONN_RETRIES;
1057 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001058
1059 defproxy.defsrv.inter = DEF_CHKINTR;
1060 defproxy.defsrv.fastinter = 0;
1061 defproxy.defsrv.downinter = 0;
1062 defproxy.defsrv.rise = DEF_RISETIME;
1063 defproxy.defsrv.fall = DEF_FALLTIME;
1064 defproxy.defsrv.check_port = 0;
1065 defproxy.defsrv.maxqueue = 0;
1066 defproxy.defsrv.minconn = 0;
1067 defproxy.defsrv.maxconn = 0;
1068 defproxy.defsrv.slowstart = 0;
1069 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1070 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1071 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072}
1073
Willy Tarreauade5ec42010-01-28 19:33:49 +01001074
1075static int create_cond_regex_rule(const char *file, int line,
1076 struct proxy *px, int dir, int action, int flags,
1077 const char *cmd, const char *reg, const char *repl,
1078 const char **cond_start)
1079{
1080 regex_t *preg = NULL;
1081 const char *err;
1082 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001083 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001084
1085 if (px == &defproxy) {
1086 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1087 err_code |= ERR_ALERT | ERR_FATAL;
1088 goto err;
1089 }
1090
1091 if (*reg == 0) {
1092 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto err;
1095 }
1096
1097 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1098 err_code |= ERR_WARN;
1099
Willy Tarreau5321c422010-01-28 20:35:13 +01001100 if (cond_start &&
1101 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1102 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1103 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1104 file, line, cmd);
1105 err_code |= ERR_ALERT | ERR_FATAL;
1106 goto err;
1107 }
1108 }
1109 else if (cond_start && **cond_start) {
1110 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1111 file, line, cmd, *cond_start);
1112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto err;
1114 }
1115
1116 if (dir == ACL_DIR_REQ)
1117 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001118 else
1119 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001120
Willy Tarreauade5ec42010-01-28 19:33:49 +01001121 preg = calloc(1, sizeof(regex_t));
1122 if (!preg) {
1123 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1124 err_code = ERR_ALERT | ERR_FATAL;
1125 goto err;
1126 }
1127
1128 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1129 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1130 err_code = ERR_ALERT | ERR_FATAL;
1131 goto err;
1132 }
1133
1134 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001135 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001136 if (repl && err) {
1137 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1138 file, line, cmd, *err);
1139 err_code |= ERR_ALERT | ERR_FATAL;
1140 goto err;
1141 }
1142
1143 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1144 err_code |= ERR_WARN;
1145
1146 return err_code;
1147 err:
1148 free(preg);
1149 return err_code;
1150}
1151
Willy Tarreaubaaee002006-06-26 02:48:02 +02001152/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001153 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001154 * Returns the error code, 0 if OK, or any combination of :
1155 * - ERR_ABORT: must abort ASAP
1156 * - ERR_FATAL: we can continue parsing but not start the service
1157 * - ERR_WARN: a warning has been emitted
1158 * - ERR_ALERT: an alert has been emitted
1159 * Only the two first ones can stop processing, the two others are just
1160 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001161 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001162int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1163{
1164 static struct peers *curpeers = NULL;
1165 struct peer *newpeer = NULL;
1166 const char *err;
1167 int err_code = 0;
1168
1169 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1170
1171 err = invalid_char(args[1]);
1172 if (err) {
1173 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1174 file, linenum, *err, args[0], args[1]);
1175 err_code |= ERR_ALERT | ERR_FATAL;
1176 }
1177
1178 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1179 /*
1180 * If there are two proxies with the same name only following
1181 * combinations are allowed:
1182 */
1183 if (strcmp(curpeers->id, args[1]) == 0) {
1184 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1185 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1186 err_code |= ERR_WARN;
1187 }
1188 }
1189
1190 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1191 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1192 err_code |= ERR_ALERT | ERR_ABORT;
1193 goto out;
1194 }
1195
1196 curpeers->next = peers;
1197 peers = curpeers;
1198 curpeers->conf.file = file;
1199 curpeers->conf.line = linenum;
1200 curpeers->last_change = now.tv_sec;
1201 curpeers->id = strdup(args[1]);
1202 }
1203 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1204 char *rport, *raddr;
1205 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001206 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001207
1208 if (!*args[2]) {
1209 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1210 file, linenum, args[0]);
1211 err_code |= ERR_ALERT | ERR_FATAL;
1212 goto out;
1213 }
1214
1215 err = invalid_char(args[1]);
1216 if (err) {
1217 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1218 file, linenum, *err, args[1]);
1219 err_code |= ERR_ALERT | ERR_FATAL;
1220 goto out;
1221 }
1222
1223 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1224 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1225 err_code |= ERR_ALERT | ERR_ABORT;
1226 goto out;
1227 }
1228
1229 /* the peers are linked backwards first */
1230 curpeers->count++;
1231 newpeer->next = curpeers->remote;
1232 curpeers->remote = newpeer;
1233 newpeer->peers = curpeers;
1234 newpeer->conf.file = file;
1235 newpeer->conf.line = linenum;
1236
1237 newpeer->last_change = now.tv_sec;
1238 newpeer->id = strdup(args[1]);
1239
1240 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001241 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001242 if (rport) {
1243 *rport++ = 0;
1244 realport = atol(rport);
1245 }
1246 if (!realport) {
1247 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1248 err_code |= ERR_ALERT | ERR_FATAL;
1249 goto out;
1250 }
1251
Willy Tarreaufab5a432011-03-04 15:31:53 +01001252 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001253 free(raddr);
1254 if (!sk) {
1255 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1256 err_code |= ERR_ALERT | ERR_FATAL;
1257 goto out;
1258 }
1259 newpeer->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001260
1261 switch (newpeer->addr.ss_family) {
1262 case AF_INET:
1263 ((struct sockaddr_in *)&newpeer->addr)->sin_port = htons(realport);
1264 break;
1265 case AF_INET6:
1266 ((struct sockaddr_in6 *)&newpeer->addr)->sin6_port = htons(realport);
1267 break;
1268 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001269
1270 if (strcmp(newpeer->id, localpeer) == 0) {
1271 /* Current is local peer, it define a frontend */
1272 newpeer->local = 1;
1273
1274 if (!curpeers->peers_fe) {
1275 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1276 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1277 err_code |= ERR_ALERT | ERR_ABORT;
1278 goto out;
1279 }
1280 curpeers->peers_fe->parent = curpeers;
1281
1282 LIST_INIT(&(curpeers->peers_fe)->pendconns);
1283 LIST_INIT(&(curpeers->peers_fe)->acl);
1284 LIST_INIT(&(curpeers->peers_fe)->block_cond);
1285 LIST_INIT(&(curpeers->peers_fe)->redirect_rules);
1286 LIST_INIT(&(curpeers->peers_fe)->mon_fail_cond);
1287 LIST_INIT(&(curpeers->peers_fe)->switching_rules);
1288 LIST_INIT(&(curpeers->peers_fe)->tcp_req.inspect_rules);
1289 LIST_INIT(&(curpeers->peers_fe)->tcp_rep.inspect_rules);
1290
1291 proxy_reset_timeouts(curpeers->peers_fe);
1292
1293 curpeers->peers_fe->last_change = now.tv_sec;
1294 curpeers->peers_fe->id = strdup(args[1]);
1295 curpeers->peers_fe->cap = PR_CAP_FE;
1296 curpeers->peers_fe->maxconn = 65000;
1297 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1298 curpeers->peers_fe->timeout.connect = 5000;
1299 curpeers->peers_fe->accept = peer_accept;
1300 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001301 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001302 err_code |= ERR_FATAL;
1303 goto out;
1304 }
1305 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1306 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1307 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1308 curpeers->peers_fe->listen->accept = session_accept;
1309 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1310 curpeers->peers_fe->listen->handler = process_session;
1311 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1312 }
1313 }
1314 } /* neither "peer" nor "peers" */
1315 else if (*args[0] != 0) {
1316 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1317 err_code |= ERR_ALERT | ERR_FATAL;
1318 goto out;
1319 }
1320
1321out:
1322 return err_code;
1323}
1324
1325
Willy Tarreau3842f002009-06-14 11:39:52 +02001326int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001327{
1328 static struct proxy *curproxy = NULL;
1329 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001330 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001331 int rc;
1332 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001333 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001334 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001335
Willy Tarreau977b8e42006-12-29 14:19:17 +01001336 if (!strcmp(args[0], "listen"))
1337 rc = PR_CAP_LISTEN;
1338 else if (!strcmp(args[0], "frontend"))
1339 rc = PR_CAP_FE | PR_CAP_RS;
1340 else if (!strcmp(args[0], "backend"))
1341 rc = PR_CAP_BE | PR_CAP_RS;
1342 else if (!strcmp(args[0], "ruleset"))
1343 rc = PR_CAP_RS;
1344 else
1345 rc = PR_CAP_NONE;
1346
1347 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001348 if (!*args[1]) {
1349 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1350 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1351 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001352 err_code |= ERR_ALERT | ERR_ABORT;
1353 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001354 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001355
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001356 err = invalid_char(args[1]);
1357 if (err) {
1358 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1359 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001360 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001361 }
1362
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001363 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1364 /*
1365 * If there are two proxies with the same name only following
1366 * combinations are allowed:
1367 *
1368 * listen backend frontend ruleset
1369 * listen - - - -
1370 * backend - - OK -
1371 * frontend - OK - -
1372 * ruleset - - - -
1373 */
1374
1375 if (!strcmp(curproxy->id, args[1]) &&
1376 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1377 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001378 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1379 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1380 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001381 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001382 }
1383 }
1384
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1386 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001387 err_code |= ERR_ALERT | ERR_ABORT;
1388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001390
Willy Tarreau97cb7802010-01-03 20:23:58 +01001391 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 curproxy->next = proxy;
1393 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001394 curproxy->conf.file = file;
1395 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001396 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001397 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001398 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399
1400 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001401 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001402 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001403 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001404 err_code |= ERR_FATAL;
1405 goto out;
1406 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001407 new = curproxy->listen;
1408 while (new != last) {
1409 new->conf.file = file;
1410 new->conf.line = linenum;
1411 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001412 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001413 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 }
1415
1416 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001417 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001418 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001419
Willy Tarreaubaaee002006-06-26 02:48:02 +02001420 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001422 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001423 curproxy->no_options = defproxy.no_options;
1424 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001425 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001426 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001427 curproxy->except_net = defproxy.except_net;
1428 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001429 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001430 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001432 if (defproxy.fwdfor_hdr_len) {
1433 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1434 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1435 }
1436
Willy Tarreaub86db342009-11-30 11:50:16 +01001437 if (defproxy.orgto_hdr_len) {
1438 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1439 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1440 }
1441
Willy Tarreau977b8e42006-12-29 14:19:17 +01001442 if (curproxy->cap & PR_CAP_FE) {
1443 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001444 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001445 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001446
1447 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001448 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1449 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001450
1451 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1452 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453
Willy Tarreau977b8e42006-12-29 14:19:17 +01001454 if (curproxy->cap & PR_CAP_BE) {
1455 curproxy->fullconn = defproxy.fullconn;
1456 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001458 if (defproxy.check_req) {
1459 curproxy->check_req = calloc(1, defproxy.check_len);
1460 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1461 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001462 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463
Willy Tarreau977b8e42006-12-29 14:19:17 +01001464 if (defproxy.cookie_name)
1465 curproxy->cookie_name = strdup(defproxy.cookie_name);
1466 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001467 if (defproxy.cookie_domain)
1468 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001469
Willy Tarreau31936852010-10-06 16:59:56 +02001470 if (defproxy.cookie_maxidle)
1471 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1472
1473 if (defproxy.cookie_maxlife)
1474 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1475
Emeric Brun647caf12009-06-30 17:57:00 +02001476 if (defproxy.rdp_cookie_name)
1477 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1478 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1479
Willy Tarreau01732802007-11-01 22:48:15 +01001480 if (defproxy.url_param_name)
1481 curproxy->url_param_name = strdup(defproxy.url_param_name);
1482 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001483
Benoitaffb4812009-03-25 13:02:10 +01001484 if (defproxy.hh_name)
1485 curproxy->hh_name = strdup(defproxy.hh_name);
1486 curproxy->hh_len = defproxy.hh_len;
1487 curproxy->hh_match_domain = defproxy.hh_match_domain;
1488
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001489 if (defproxy.iface_name)
1490 curproxy->iface_name = strdup(defproxy.iface_name);
1491 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001494 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001495 if (defproxy.capture_name)
1496 curproxy->capture_name = strdup(defproxy.capture_name);
1497 curproxy->capture_namelen = defproxy.capture_namelen;
1498 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001499 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500
Willy Tarreau977b8e42006-12-29 14:19:17 +01001501 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001502 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001503 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001504 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001505 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001506 curproxy->uri_auth = defproxy.uri_auth;
1507 curproxy->mon_net = defproxy.mon_net;
1508 curproxy->mon_mask = defproxy.mon_mask;
1509 if (defproxy.monitor_uri)
1510 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1511 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001512 if (defproxy.defbe.name)
1513 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001514 }
1515
1516 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001517 curproxy->timeout.connect = defproxy.timeout.connect;
1518 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001519 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001520 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001521 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001522 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001523 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001524 curproxy->source_addr = defproxy.source_addr;
1525 }
1526
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527 curproxy->mode = defproxy.mode;
1528 curproxy->logfac1 = defproxy.logfac1;
1529 curproxy->logsrv1 = defproxy.logsrv1;
1530 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001531 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532 curproxy->logfac2 = defproxy.logfac2;
1533 curproxy->logsrv2 = defproxy.logsrv2;
1534 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001535 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001536 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001537 curproxy->conf.used_listener_id = EB_ROOT;
1538 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001539
Willy Tarreau93893792009-07-23 13:19:11 +02001540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001541 }
1542 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1543 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001544 /* FIXME-20070101: we should do this too at the end of the
1545 * config parsing to free all default values.
1546 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001547 free(defproxy.check_req);
1548 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001549 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001550 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001551 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001552 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001553 free(defproxy.capture_name);
1554 free(defproxy.monitor_uri);
1555 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001556 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001557 free(defproxy.fwdfor_hdr_name);
1558 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001559 free(defproxy.orgto_hdr_name);
1560 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001561
Willy Tarreaua534fea2008-08-03 12:19:50 +02001562 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001563 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001564
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565 /* we cannot free uri_auth because it might already be used */
1566 init_default_instance();
1567 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001568 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 }
1571 else if (curproxy == NULL) {
1572 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001573 err_code |= ERR_ALERT | ERR_FATAL;
1574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001575 }
1576
Willy Tarreau977b8e42006-12-29 14:19:17 +01001577
1578 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001580 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001581 int cur_arg;
1582
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 if (curproxy == &defproxy) {
1584 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001585 err_code |= ERR_ALERT | ERR_FATAL;
1586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001588 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001589 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590
Emeric Bruned760922010-10-22 17:59:25 +02001591 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001592 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001593 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001594 err_code |= ERR_ALERT | ERR_FATAL;
1595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001597
1598 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001599
1600 /* NOTE: the following line might create several listeners if there
1601 * are comma-separated IPs or port ranges. So all further processing
1602 * will have to be applied to all listeners created after last_listen.
1603 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001604 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001605 err_code |= ERR_ALERT | ERR_FATAL;
1606 goto out;
1607 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001608
Willy Tarreau90a570f2009-10-04 20:54:54 +02001609 new_listen = curproxy->listen;
1610 while (new_listen != last_listen) {
1611 new_listen->conf.file = file;
1612 new_listen->conf.line = linenum;
1613 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001614 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001615 }
1616
Emeric Bruned760922010-10-22 17:59:25 +02001617 /* Set default global rights and owner for unix bind */
1618 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1619 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1620 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001621 cur_arg = 2;
1622 while (*(args[cur_arg])) {
1623 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1624#ifdef SO_BINDTODEVICE
1625 struct listener *l;
1626
Emeric Bruned760922010-10-22 17:59:25 +02001627 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1628 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1629 file, linenum, args[0], args[cur_arg]);
1630 err_code |= ERR_ALERT | ERR_FATAL;
1631 goto out;
1632 }
1633
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001634 if (!*args[cur_arg + 1]) {
1635 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1636 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001637 err_code |= ERR_ALERT | ERR_FATAL;
1638 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001639 }
1640
1641 for (l = curproxy->listen; l != last_listen; l = l->next)
1642 l->interface = strdup(args[cur_arg + 1]);
1643
1644 global.last_checks |= LSTCHK_NETADM;
1645
1646 cur_arg += 2;
1647 continue;
1648#else
1649 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1650 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001653#endif
1654 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001655 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1656#ifdef TCP_MAXSEG
1657 struct listener *l;
1658 int mss;
1659
Emeric Bruned760922010-10-22 17:59:25 +02001660 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1661 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1662 file, linenum, args[0], args[cur_arg]);
1663 err_code |= ERR_ALERT | ERR_FATAL;
1664 goto out;
1665 }
1666
Willy Tarreaube1b9182009-06-14 18:48:19 +02001667 if (!*args[cur_arg + 1]) {
1668 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1669 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001670 err_code |= ERR_ALERT | ERR_FATAL;
1671 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001672 }
1673
Willy Tarreau48a7e722010-12-24 15:26:39 +01001674 mss = atoi(args[cur_arg + 1]);
1675 if (!mss || abs(mss) > 65535) {
1676 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001677 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001678 err_code |= ERR_ALERT | ERR_FATAL;
1679 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001680 }
1681
1682 for (l = curproxy->listen; l != last_listen; l = l->next)
1683 l->maxseg = mss;
1684
1685 cur_arg += 2;
1686 continue;
1687#else
1688 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1689 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001690 err_code |= ERR_ALERT | ERR_FATAL;
1691 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001692#endif
1693 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001694
1695 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1696#ifdef TCP_DEFER_ACCEPT
1697 struct listener *l;
1698
1699 for (l = curproxy->listen; l != last_listen; l = l->next)
1700 l->options |= LI_O_DEF_ACCEPT;
1701
1702 cur_arg ++;
1703 continue;
1704#else
1705 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1706 file, linenum, args[0], args[cur_arg]);
1707 err_code |= ERR_ALERT | ERR_FATAL;
1708 goto out;
1709#endif
1710 }
1711
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001712 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001713#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001714 struct listener *l;
1715
Emeric Bruned760922010-10-22 17:59:25 +02001716 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1717 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1718 file, linenum, args[0], args[cur_arg]);
1719 err_code |= ERR_ALERT | ERR_FATAL;
1720 goto out;
1721 }
1722
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001723 for (l = curproxy->listen; l != last_listen; l = l->next)
1724 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001725
1726 cur_arg ++;
1727 continue;
1728#else
1729 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1730 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001731 err_code |= ERR_ALERT | ERR_FATAL;
1732 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001733#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001734 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001735
Willy Tarreau8a956912010-10-15 14:27:08 +02001736 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1737 struct listener *l;
1738
1739 for (l = curproxy->listen; l != last_listen; l = l->next)
1740 l->options |= LI_O_ACC_PROXY;
1741
1742 cur_arg ++;
1743 continue;
1744 }
1745
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001746 if (!strcmp(args[cur_arg], "name")) {
1747 struct listener *l;
1748
1749 for (l = curproxy->listen; l != last_listen; l = l->next)
1750 l->name = strdup(args[cur_arg + 1]);
1751
1752 cur_arg += 2;
1753 continue;
1754 }
1755
1756 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001757 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001758 struct listener *l;
1759
1760 if (curproxy->listen->next != last_listen) {
1761 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1762 file, linenum, args[cur_arg]);
1763 err_code |= ERR_ALERT | ERR_FATAL;
1764 goto out;
1765 }
1766
1767 if (!*args[cur_arg + 1]) {
1768 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1769 file, linenum, args[cur_arg]);
1770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
1772 }
1773
1774 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001775 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001776
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001777 if (curproxy->listen->luid <= 0) {
1778 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001779 file, linenum);
1780 err_code |= ERR_ALERT | ERR_FATAL;
1781 goto out;
1782 }
1783
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001784 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1785 if (node) {
1786 l = container_of(node, struct listener, conf.id);
1787 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1788 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1789 err_code |= ERR_ALERT | ERR_FATAL;
1790 goto out;
1791 }
1792 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1793
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001794 cur_arg += 2;
1795 continue;
1796 }
1797
Emeric Bruned760922010-10-22 17:59:25 +02001798 if (!strcmp(args[cur_arg], "mode")) {
1799
1800 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1801 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1802 file, linenum, args[0], args[cur_arg]);
1803 err_code |= ERR_ALERT | ERR_FATAL;
1804 goto out;
1805 }
1806
1807 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1808
1809 cur_arg += 2;
1810 continue;
1811 }
1812
1813 if (!strcmp(args[cur_arg], "uid")) {
1814
1815 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1816 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1817 file, linenum, args[0], args[cur_arg]);
1818 err_code |= ERR_ALERT | ERR_FATAL;
1819 goto out;
1820 }
1821
1822 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1823 cur_arg += 2;
1824 continue;
1825 }
1826
1827 if (!strcmp(args[cur_arg], "gid")) {
1828
1829 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1830 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1831 file, linenum, args[0], args[cur_arg]);
1832 err_code |= ERR_ALERT | ERR_FATAL;
1833 goto out;
1834 }
1835
1836 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1837 cur_arg += 2;
1838 continue;
1839 }
1840
1841 if (!strcmp(args[cur_arg], "user")) {
1842 struct passwd *user;
1843
1844 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1845 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1846 file, linenum, args[0], args[cur_arg]);
1847 err_code |= ERR_ALERT | ERR_FATAL;
1848 goto out;
1849 }
1850 user = getpwnam(args[cur_arg + 1]);
1851 if (!user) {
1852 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1853 file, linenum, args[0], args[cur_arg + 1 ]);
1854 err_code |= ERR_ALERT | ERR_FATAL;
1855 goto out;
1856 }
1857
1858 curproxy->listen->perm.ux.uid = user->pw_uid;
1859 cur_arg += 2;
1860 continue;
1861 }
1862
1863 if (!strcmp(args[cur_arg], "group")) {
1864 struct group *group;
1865
1866 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1867 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1868 file, linenum, args[0], args[cur_arg]);
1869 err_code |= ERR_ALERT | ERR_FATAL;
1870 goto out;
1871 }
1872 group = getgrnam(args[cur_arg + 1]);
1873 if (!group) {
1874 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1875 file, linenum, args[0], args[cur_arg + 1 ]);
1876 err_code |= ERR_ALERT | ERR_FATAL;
1877 goto out;
1878 }
1879
1880 curproxy->listen->perm.ux.gid = group->gr_gid;
1881 cur_arg += 2;
1882 continue;
1883 }
1884
Willy Tarreau8a956912010-10-15 14:27:08 +02001885 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001886 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001889 }
Willy Tarreau93893792009-07-23 13:19:11 +02001890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001891 }
1892 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1893 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1894 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1895 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001896 err_code |= ERR_ALERT | ERR_FATAL;
1897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001898 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001899 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001900 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001901
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 /* flush useless bits */
1903 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001906 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001907 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001908 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001909
Willy Tarreau1c47f852006-07-09 08:22:27 +02001910 if (!*args[1]) {
1911 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1912 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001913 err_code |= ERR_ALERT | ERR_FATAL;
1914 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001915 }
1916
Willy Tarreaua534fea2008-08-03 12:19:50 +02001917 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001918 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001919 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001920 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001921 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1922
Willy Tarreau93893792009-07-23 13:19:11 +02001923 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1926 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1927 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1928 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1929 else {
1930 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 }
1934 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001935 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001936 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001937
1938 if (curproxy == &defproxy) {
1939 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1940 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001941 err_code |= ERR_ALERT | ERR_FATAL;
1942 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001943 }
1944
1945 if (!*args[1]) {
1946 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1947 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001948 err_code |= ERR_ALERT | ERR_FATAL;
1949 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001950 }
1951
1952 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001953 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001954
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001955 if (curproxy->uuid <= 0) {
1956 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001957 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001958 err_code |= ERR_ALERT | ERR_FATAL;
1959 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001960 }
1961
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001962 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1963 if (node) {
1964 struct proxy *target = container_of(node, struct proxy, conf.id);
1965 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1966 file, linenum, proxy_type_str(curproxy), curproxy->id,
1967 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1968 err_code |= ERR_ALERT | ERR_FATAL;
1969 goto out;
1970 }
1971 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001972 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001973 else if (!strcmp(args[0], "description")) {
1974 int i, len=0;
1975 char *d;
1976
Cyril Bonté99ed3272010-01-24 23:29:44 +01001977 if (curproxy == &defproxy) {
1978 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1979 file, linenum, args[0]);
1980 err_code |= ERR_ALERT | ERR_FATAL;
1981 goto out;
1982 }
1983
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001984 if (!*args[1]) {
1985 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1986 file, linenum, args[0]);
1987 return -1;
1988 }
1989
1990 for(i=1; *args[i]; i++)
1991 len += strlen(args[i])+1;
1992
1993 d = (char *)calloc(1, len);
1994 curproxy->desc = d;
1995
1996 d += sprintf(d, "%s", args[1]);
1997 for(i=2; *args[i]; i++)
1998 d += sprintf(d, " %s", args[i]);
1999
2000 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002001 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2002 curproxy->state = PR_STSTOPPED;
2003 }
2004 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2005 curproxy->state = PR_STNEW;
2006 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002007 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2008 int cur_arg = 1;
2009 unsigned int set = 0;
2010
2011 while (*args[cur_arg]) {
2012 int u;
2013 if (strcmp(args[cur_arg], "all") == 0) {
2014 set = 0;
2015 break;
2016 }
2017 else if (strcmp(args[cur_arg], "odd") == 0) {
2018 set |= 0x55555555;
2019 }
2020 else if (strcmp(args[cur_arg], "even") == 0) {
2021 set |= 0xAAAAAAAA;
2022 }
2023 else {
2024 u = str2uic(args[cur_arg]);
2025 if (u < 1 || u > 32) {
2026 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2027 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002028 err_code |= ERR_ALERT | ERR_FATAL;
2029 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002030 }
2031 if (u > global.nbproc) {
2032 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2033 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002035 }
2036 set |= 1 << (u - 1);
2037 }
2038 cur_arg++;
2039 }
2040 curproxy->bind_proc = set;
2041 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002042 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002043 if (curproxy == &defproxy) {
2044 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002045 err_code |= ERR_ALERT | ERR_FATAL;
2046 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002047 }
2048
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002049 err = invalid_char(args[1]);
2050 if (err) {
2051 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2052 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002053 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002054 }
2055
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002056 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2057 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2058 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002061 }
2062 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2064 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002065
Willy Tarreau977b8e42006-12-29 14:19:17 +01002066 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002067 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002068
Willy Tarreaubaaee002006-06-26 02:48:02 +02002069 if (*(args[1]) == 0) {
2070 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2071 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002072 err_code |= ERR_ALERT | ERR_FATAL;
2073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002075
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002076 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002077 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002078 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002079 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002080 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081 curproxy->cookie_name = strdup(args[1]);
2082 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002083
Willy Tarreaubaaee002006-06-26 02:48:02 +02002084 cur_arg = 2;
2085 while (*(args[cur_arg])) {
2086 if (!strcmp(args[cur_arg], "rewrite")) {
2087 curproxy->options |= PR_O_COOK_RW;
2088 }
2089 else if (!strcmp(args[cur_arg], "indirect")) {
2090 curproxy->options |= PR_O_COOK_IND;
2091 }
2092 else if (!strcmp(args[cur_arg], "insert")) {
2093 curproxy->options |= PR_O_COOK_INS;
2094 }
2095 else if (!strcmp(args[cur_arg], "nocache")) {
2096 curproxy->options |= PR_O_COOK_NOC;
2097 }
2098 else if (!strcmp(args[cur_arg], "postonly")) {
2099 curproxy->options |= PR_O_COOK_POST;
2100 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002101 else if (!strcmp(args[cur_arg], "preserve")) {
2102 curproxy->options2 |= PR_O2_COOK_PSV;
2103 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 else if (!strcmp(args[cur_arg], "prefix")) {
2105 curproxy->options |= PR_O_COOK_PFX;
2106 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002107 else if (!strcmp(args[cur_arg], "domain")) {
2108 if (!*args[cur_arg + 1]) {
2109 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2110 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002111 err_code |= ERR_ALERT | ERR_FATAL;
2112 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002113 }
2114
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002115 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002116 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002117 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2118 " dots nor does not start with a dot."
2119 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002120 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002121 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002122 }
2123
2124 err = invalid_domainchar(args[cur_arg + 1]);
2125 if (err) {
2126 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2127 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002128 err_code |= ERR_ALERT | ERR_FATAL;
2129 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002130 }
2131
Willy Tarreau68a897b2009-12-03 23:28:34 +01002132 if (!curproxy->cookie_domain) {
2133 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2134 } else {
2135 /* one domain was already specified, add another one by
2136 * building the string which will be returned along with
2137 * the cookie.
2138 */
2139 char *new_ptr;
2140 int new_len = strlen(curproxy->cookie_domain) +
2141 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2142 new_ptr = malloc(new_len);
2143 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2144 free(curproxy->cookie_domain);
2145 curproxy->cookie_domain = new_ptr;
2146 }
Willy Tarreau31936852010-10-06 16:59:56 +02002147 cur_arg++;
2148 }
2149 else if (!strcmp(args[cur_arg], "maxidle")) {
2150 unsigned int maxidle;
2151 const char *res;
2152
2153 if (!*args[cur_arg + 1]) {
2154 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2155 file, linenum, args[cur_arg]);
2156 err_code |= ERR_ALERT | ERR_FATAL;
2157 goto out;
2158 }
2159
2160 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2161 if (res) {
2162 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2163 file, linenum, *res, args[cur_arg]);
2164 err_code |= ERR_ALERT | ERR_FATAL;
2165 goto out;
2166 }
2167 curproxy->cookie_maxidle = maxidle;
2168 cur_arg++;
2169 }
2170 else if (!strcmp(args[cur_arg], "maxlife")) {
2171 unsigned int maxlife;
2172 const char *res;
2173
2174 if (!*args[cur_arg + 1]) {
2175 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2176 file, linenum, args[cur_arg]);
2177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
2179 }
2180
2181 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2182 if (res) {
2183 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2184 file, linenum, *res, args[cur_arg]);
2185 err_code |= ERR_ALERT | ERR_FATAL;
2186 goto out;
2187 }
2188 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002189 cur_arg++;
2190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002191 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002192 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002194 err_code |= ERR_ALERT | ERR_FATAL;
2195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002196 }
2197 cur_arg++;
2198 }
2199 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2200 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2201 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002202 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 }
2204
2205 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2206 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2207 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002208 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002210
2211 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2212 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2213 file, linenum);
2214 err_code |= ERR_ALERT | ERR_FATAL;
2215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002216 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002217 else if (!strcmp(args[0], "persist")) { /* persist */
2218 if (*(args[1]) == 0) {
2219 Alert("parsing [%s:%d] : missing persist method.\n",
2220 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002221 err_code |= ERR_ALERT | ERR_FATAL;
2222 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002223 }
2224
2225 if (!strncmp(args[1], "rdp-cookie", 10)) {
2226 curproxy->options2 |= PR_O2_RDPC_PRST;
2227
Emeric Brunb982a3d2010-01-04 15:45:53 +01002228 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002229 const char *beg, *end;
2230
2231 beg = args[1] + 11;
2232 end = strchr(beg, ')');
2233
2234 if (!end || end == beg) {
2235 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2236 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002239 }
2240
2241 free(curproxy->rdp_cookie_name);
2242 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2243 curproxy->rdp_cookie_len = end-beg;
2244 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002245 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002246 free(curproxy->rdp_cookie_name);
2247 curproxy->rdp_cookie_name = strdup("msts");
2248 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2249 }
2250 else { /* syntax */
2251 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2252 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002253 err_code |= ERR_ALERT | ERR_FATAL;
2254 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002255 }
2256 }
2257 else {
2258 Alert("parsing [%s:%d] : unknown persist method.\n",
2259 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002262 }
2263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002265 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002267 if (curproxy == &defproxy) {
2268 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
2271 }
2272
Willy Tarreau977b8e42006-12-29 14:19:17 +01002273 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002274 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002275
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002277 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002278 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002281 }
2282 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002283 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284 curproxy->appsession_name = strdup(args[1]);
2285 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2286 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002287 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2288 if (err) {
2289 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2290 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002293 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002294 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002295
Willy Tarreau51041c72007-09-09 21:56:53 +02002296 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2297 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002298 err_code |= ERR_ALERT | ERR_ABORT;
2299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002301
2302 cur_arg = 6;
2303 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002304 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2305 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002306 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002307 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002308 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002309 } else if (!strcmp(args[cur_arg], "prefix")) {
2310 curproxy->options2 |= PR_O2_AS_PFX;
2311 } else if (!strcmp(args[cur_arg], "mode")) {
2312 if (!*args[cur_arg + 1]) {
2313 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2314 file, linenum, args[0], args[cur_arg]);
2315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
2317 }
2318
2319 cur_arg++;
2320 if (!strcmp(args[cur_arg], "query-string")) {
2321 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2322 curproxy->options2 |= PR_O2_AS_M_QS;
2323 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2324 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2325 curproxy->options2 |= PR_O2_AS_M_PP;
2326 } else {
2327 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
2330 }
2331 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002332 cur_arg++;
2333 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 } /* Url App Session */
2335 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002336 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002337 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002338
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002340 if (curproxy == &defproxy) {
2341 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
2344 }
2345
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 if (*(args[4]) == 0) {
2347 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2348 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002349 err_code |= ERR_ALERT | ERR_FATAL;
2350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002352 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 curproxy->capture_name = strdup(args[2]);
2354 curproxy->capture_namelen = strlen(curproxy->capture_name);
2355 curproxy->capture_len = atol(args[4]);
2356 if (curproxy->capture_len >= CAPTURE_LEN) {
2357 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2358 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 curproxy->capture_len = CAPTURE_LEN - 1;
2361 }
2362 curproxy->to_log |= LW_COOKIE;
2363 }
2364 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2365 struct cap_hdr *hdr;
2366
2367 if (curproxy == &defproxy) {
2368 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002369 err_code |= ERR_ALERT | ERR_FATAL;
2370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 }
2372
2373 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2374 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2375 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 }
2379
2380 hdr = calloc(sizeof(struct cap_hdr), 1);
2381 hdr->next = curproxy->req_cap;
2382 hdr->name = strdup(args[3]);
2383 hdr->namelen = strlen(args[3]);
2384 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002385 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 hdr->index = curproxy->nb_req_cap++;
2387 curproxy->req_cap = hdr;
2388 curproxy->to_log |= LW_REQHDR;
2389 }
2390 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2391 struct cap_hdr *hdr;
2392
2393 if (curproxy == &defproxy) {
2394 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002395 err_code |= ERR_ALERT | ERR_FATAL;
2396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 }
2398
2399 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2400 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2401 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002402 err_code |= ERR_ALERT | ERR_FATAL;
2403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 }
2405 hdr = calloc(sizeof(struct cap_hdr), 1);
2406 hdr->next = curproxy->rsp_cap;
2407 hdr->name = strdup(args[3]);
2408 hdr->namelen = strlen(args[3]);
2409 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002410 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 hdr->index = curproxy->nb_rsp_cap++;
2412 curproxy->rsp_cap = hdr;
2413 curproxy->to_log |= LW_RSPHDR;
2414 }
2415 else {
2416 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2417 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 }
2421 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002423 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002425
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 if (*(args[1]) == 0) {
2427 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2428 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 }
2432 curproxy->conn_retries = atol(args[1]);
2433 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002434 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002435 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002436
2437 if (curproxy == &defproxy) {
2438 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
2441 }
2442
Willy Tarreauff011f22011-01-06 17:51:27 +01002443 if (!LIST_ISEMPTY(&curproxy->http_req_rules) && !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002444 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2445 file, linenum, args[0]);
2446 err_code |= ERR_WARN;
2447 }
2448
Willy Tarreauff011f22011-01-06 17:51:27 +01002449 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002450
Willy Tarreauff011f22011-01-06 17:51:27 +01002451 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002452 err_code |= ERR_ALERT | ERR_ABORT;
2453 goto out;
2454 }
2455
Willy Tarreauff011f22011-01-06 17:51:27 +01002456 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2457 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002458 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002459 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002460 if (curproxy == &defproxy) {
2461 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002462 err_code |= ERR_ALERT | ERR_FATAL;
2463 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002464 }
2465
Willy Tarreauef6494c2010-01-28 17:12:36 +01002466 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002467 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2468 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002471 }
2472
Willy Tarreauef6494c2010-01-28 17:12:36 +01002473 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002474 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2475 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002478 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002479
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002480 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002481 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002482 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002483 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002484 struct redirect_rule *rule;
2485 int cur_arg;
2486 int type = REDIRECT_TYPE_NONE;
2487 int code = 302;
2488 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002489 char *cookie = NULL;
2490 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002491 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002492
Cyril Bonté99ed3272010-01-24 23:29:44 +01002493 if (curproxy == &defproxy) {
2494 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2495 err_code |= ERR_ALERT | ERR_FATAL;
2496 goto out;
2497 }
2498
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002499 cur_arg = 1;
2500 while (*(args[cur_arg])) {
2501 if (!strcmp(args[cur_arg], "location")) {
2502 if (!*args[cur_arg + 1]) {
2503 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2504 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002507 }
2508
2509 type = REDIRECT_TYPE_LOCATION;
2510 cur_arg++;
2511 destination = args[cur_arg];
2512 }
2513 else if (!strcmp(args[cur_arg], "prefix")) {
2514 if (!*args[cur_arg + 1]) {
2515 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2516 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002517 err_code |= ERR_ALERT | ERR_FATAL;
2518 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002519 }
2520
2521 type = REDIRECT_TYPE_PREFIX;
2522 cur_arg++;
2523 destination = args[cur_arg];
2524 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002525 else if (!strcmp(args[cur_arg], "set-cookie")) {
2526 if (!*args[cur_arg + 1]) {
2527 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2528 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002531 }
2532
2533 cur_arg++;
2534 cookie = args[cur_arg];
2535 cookie_set = 1;
2536 }
2537 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2538 if (!*args[cur_arg + 1]) {
2539 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2540 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002541 err_code |= ERR_ALERT | ERR_FATAL;
2542 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002543 }
2544
2545 cur_arg++;
2546 cookie = args[cur_arg];
2547 cookie_set = 0;
2548 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002549 else if (!strcmp(args[cur_arg],"code")) {
2550 if (!*args[cur_arg + 1]) {
2551 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2552 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002555 }
2556 cur_arg++;
2557 code = atol(args[cur_arg]);
2558 if (code < 301 || code > 303) {
2559 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2560 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002561 err_code |= ERR_ALERT | ERR_FATAL;
2562 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002563 }
2564 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002565 else if (!strcmp(args[cur_arg],"drop-query")) {
2566 flags |= REDIRECT_FLAG_DROP_QS;
2567 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002568 else if (!strcmp(args[cur_arg],"append-slash")) {
2569 flags |= REDIRECT_FLAG_APPEND_SLASH;
2570 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002571 else if (strcmp(args[cur_arg], "if") == 0 ||
2572 strcmp(args[cur_arg], "unless") == 0) {
2573 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2574 if (!cond) {
2575 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2576 file, linenum, args[0]);
2577 err_code |= ERR_ALERT | ERR_FATAL;
2578 goto out;
2579 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002580 break;
2581 }
2582 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002583 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002584 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002585 err_code |= ERR_ALERT | ERR_FATAL;
2586 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002587 }
2588 cur_arg++;
2589 }
2590
2591 if (type == REDIRECT_TYPE_NONE) {
2592 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2593 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002596 }
2597
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002598 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2599 rule->cond = cond;
2600 rule->rdr_str = strdup(destination);
2601 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002602 if (cookie) {
2603 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002604 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002605 */
2606 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002607 if (cookie_set) {
2608 rule->cookie_str = malloc(rule->cookie_len + 10);
2609 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2610 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2611 rule->cookie_len += 9;
2612 } else {
2613 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002614 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002615 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2616 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002617 }
2618 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002619 rule->type = type;
2620 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002621 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002622 LIST_INIT(&rule->list);
2623 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002624 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2625 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002626 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002627 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002628 struct switching_rule *rule;
2629
Willy Tarreaub099aca2008-10-12 17:26:37 +02002630 if (curproxy == &defproxy) {
2631 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002632 err_code |= ERR_ALERT | ERR_FATAL;
2633 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002634 }
2635
Willy Tarreau55ea7572007-06-17 19:56:27 +02002636 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002637 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002638
2639 if (*(args[1]) == 0) {
2640 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002643 }
2644
Willy Tarreauef6494c2010-01-28 17:12:36 +01002645 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002646 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2647 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002650 }
2651
Willy Tarreauef6494c2010-01-28 17:12:36 +01002652 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002653 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002654 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002657 }
2658
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002659 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002660
Willy Tarreau55ea7572007-06-17 19:56:27 +02002661 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2662 rule->cond = cond;
2663 rule->be.name = strdup(args[1]);
2664 LIST_INIT(&rule->list);
2665 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2666 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002667 else if ((!strcmp(args[0], "force-persist")) ||
2668 (!strcmp(args[0], "ignore-persist"))) {
2669 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002670
2671 if (curproxy == &defproxy) {
2672 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2673 err_code |= ERR_ALERT | ERR_FATAL;
2674 goto out;
2675 }
2676
2677 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2678 err_code |= ERR_WARN;
2679
Willy Tarreauef6494c2010-01-28 17:12:36 +01002680 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002681 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2682 file, linenum, args[0]);
2683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
2685 }
2686
Willy Tarreauef6494c2010-01-28 17:12:36 +01002687 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002688 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2689 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
2692 }
2693
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002694 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002695
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002696 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002697 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002698 if (!strcmp(args[0], "force-persist")) {
2699 rule->type = PERSIST_TYPE_FORCE;
2700 } else {
2701 rule->type = PERSIST_TYPE_IGNORE;
2702 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002703 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002704 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002705 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002706 else if (!strcmp(args[0], "stick-table")) {
2707 int myidx = 1;
2708
Emeric Brun32da3c42010-09-23 18:39:19 +02002709 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002710 curproxy->table.type = (unsigned int)-1;
2711 while (*args[myidx]) {
2712 const char *err;
2713
2714 if (strcmp(args[myidx], "size") == 0) {
2715 myidx++;
2716 if (!*(args[myidx])) {
2717 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2718 file, linenum, args[myidx-1]);
2719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
2721 }
2722 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2723 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2724 file, linenum, *err, args[myidx-1]);
2725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
2727 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002728 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002729 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002730 else if (strcmp(args[myidx], "peers") == 0) {
2731 myidx++;
2732 if (!*(args[myidx])) {
2733 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2734 file, linenum, args[myidx-1]);
2735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
2737 }
2738 curproxy->table.peers.name = strdup(args[myidx++]);
2739 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002740 else if (strcmp(args[myidx], "expire") == 0) {
2741 myidx++;
2742 if (!*(args[myidx])) {
2743 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2744 file, linenum, args[myidx-1]);
2745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
2747 }
2748 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2749 if (err) {
2750 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2751 file, linenum, *err, args[myidx-1]);
2752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
2754 }
2755 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002756 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002757 }
2758 else if (strcmp(args[myidx], "nopurge") == 0) {
2759 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002760 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002761 }
2762 else if (strcmp(args[myidx], "type") == 0) {
2763 myidx++;
2764 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2765 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2766 file, linenum, args[myidx]);
2767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
2769 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002770 /* myidx already points to next arg */
2771 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002772 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002773 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002774 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002775
2776 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002777 nw = args[myidx];
2778 while (*nw) {
2779 /* the "store" keyword supports a comma-separated list */
2780 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002781 sa = NULL; /* store arg */
2782 while (*nw && *nw != ',') {
2783 if (*nw == '(') {
2784 *nw = 0;
2785 sa = ++nw;
2786 while (*nw != ')') {
2787 if (!*nw) {
2788 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2789 file, linenum, args[0], cw);
2790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
2792 }
2793 nw++;
2794 }
2795 *nw = '\0';
2796 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002797 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002798 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002799 if (*nw)
2800 *nw++ = '\0';
2801 type = stktable_get_data_type(cw);
2802 if (type < 0) {
2803 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2804 file, linenum, args[0], cw);
2805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
2807 }
Willy Tarreauac782882010-06-20 10:41:54 +02002808
2809 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2810 switch (err) {
2811 case PE_NONE: break;
2812 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002813 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2814 file, linenum, args[0], cw);
2815 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002816 break;
2817
2818 case PE_ARG_MISSING:
2819 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2820 file, linenum, args[0], cw);
2821 err_code |= ERR_ALERT | ERR_FATAL;
2822 goto out;
2823
2824 case PE_ARG_NOT_USED:
2825 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2826 file, linenum, args[0], cw);
2827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
2829
2830 default:
2831 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2832 file, linenum, args[0], cw);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002835 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002836 }
2837 myidx++;
2838 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002839 else {
2840 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2841 file, linenum, args[myidx]);
2842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002844 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002845 }
2846
2847 if (!curproxy->table.size) {
2848 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2849 file, linenum);
2850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
2852 }
2853
2854 if (curproxy->table.type == (unsigned int)-1) {
2855 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2856 file, linenum);
2857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
2859 }
2860 }
2861 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002862 struct sticking_rule *rule;
2863 struct pattern_expr *expr;
2864 int myidx = 0;
2865 const char *name = NULL;
2866 int flags;
2867
2868 if (curproxy == &defproxy) {
2869 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
2872 }
2873
2874 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2875 err_code |= ERR_WARN;
2876 goto out;
2877 }
2878
2879 myidx++;
2880 if ((strcmp(args[myidx], "store") == 0) ||
2881 (strcmp(args[myidx], "store-request") == 0)) {
2882 myidx++;
2883 flags = STK_IS_STORE;
2884 }
2885 else if (strcmp(args[myidx], "store-response") == 0) {
2886 myidx++;
2887 flags = STK_IS_STORE | STK_ON_RSP;
2888 }
2889 else if (strcmp(args[myidx], "match") == 0) {
2890 myidx++;
2891 flags = STK_IS_MATCH;
2892 }
2893 else if (strcmp(args[myidx], "on") == 0) {
2894 myidx++;
2895 flags = STK_IS_MATCH | STK_IS_STORE;
2896 }
2897 else {
2898 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2899 err_code |= ERR_ALERT | ERR_FATAL;
2900 goto out;
2901 }
2902
2903 if (*(args[myidx]) == 0) {
2904 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
2907 }
2908
Emeric Brun485479d2010-09-23 18:02:19 +02002909 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002910 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002911 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
2914 }
2915
2916 if (flags & STK_ON_RSP) {
2917 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2918 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2919 file, linenum, args[0], expr->fetch->kw);
2920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
2922 }
2923 } else {
2924 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2925 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2926 file, linenum, args[0], expr->fetch->kw);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
2929 }
2930 }
2931
2932 if (strcmp(args[myidx], "table") == 0) {
2933 myidx++;
2934 name = args[myidx++];
2935 }
2936
Willy Tarreauef6494c2010-01-28 17:12:36 +01002937 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2938 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002939 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2940 file, linenum, args[0]);
2941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
2943 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002944 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002945 else if (*(args[myidx])) {
2946 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2947 file, linenum, args[0], args[myidx]);
2948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
2950 }
Emeric Brun97679e72010-09-23 17:56:44 +02002951 if (flags & STK_ON_RSP)
2952 err_code |= warnif_cond_requires_req(cond, file, linenum);
2953 else
2954 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002955
Emeric Brunb982a3d2010-01-04 15:45:53 +01002956 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2957 rule->cond = cond;
2958 rule->expr = expr;
2959 rule->flags = flags;
2960 rule->table.name = name ? strdup(name) : NULL;
2961 LIST_INIT(&rule->list);
2962 if (flags & STK_ON_RSP)
2963 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2964 else
2965 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2966 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002968 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002969 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002970
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2972 curproxy->uri_auth = NULL; /* we must detach from the default config */
2973
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002974 if (!*args[1]) {
2975 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002976 } else if (!strcmp(args[1], "admin")) {
2977 struct stats_admin_rule *rule;
2978
2979 if (curproxy == &defproxy) {
2980 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2981 err_code |= ERR_ALERT | ERR_FATAL;
2982 goto out;
2983 }
2984
2985 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2986 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2987 err_code |= ERR_ALERT | ERR_ABORT;
2988 goto out;
2989 }
2990
2991 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2992 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2993 file, linenum, args[0], args[1]);
2994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
2996 }
2997 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2998 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2999 file, linenum, args[0], args[1]);
3000 err_code |= ERR_ALERT | ERR_FATAL;
3001 goto out;
3002 }
3003
3004 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3005
3006 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3007 rule->cond = cond;
3008 LIST_INIT(&rule->list);
3009 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 } else if (!strcmp(args[1], "uri")) {
3011 if (*(args[2]) == 0) {
3012 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003015 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3016 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003017 err_code |= ERR_ALERT | ERR_ABORT;
3018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003019 }
3020 } else if (!strcmp(args[1], "realm")) {
3021 if (*(args[2]) == 0) {
3022 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003023 err_code |= ERR_ALERT | ERR_FATAL;
3024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003025 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3026 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003027 err_code |= ERR_ALERT | ERR_ABORT;
3028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003030 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003031 unsigned interval;
3032
3033 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3034 if (err) {
3035 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3036 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003039 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3040 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003041 err_code |= ERR_ALERT | ERR_ABORT;
3042 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003043 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003044 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003045 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003046
3047 if (curproxy == &defproxy) {
3048 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
3051 }
3052
3053 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3054 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3055 err_code |= ERR_ALERT | ERR_ABORT;
3056 goto out;
3057 }
3058
Willy Tarreauff011f22011-01-06 17:51:27 +01003059 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3060 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003061 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3062 file, linenum, args[0]);
3063 err_code |= ERR_WARN;
3064 }
3065
Willy Tarreauff011f22011-01-06 17:51:27 +01003066 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003067
Willy Tarreauff011f22011-01-06 17:51:27 +01003068 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003069 err_code |= ERR_ALERT | ERR_ABORT;
3070 goto out;
3071 }
3072
Willy Tarreauff011f22011-01-06 17:51:27 +01003073 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3074 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003075
Willy Tarreaubaaee002006-06-26 02:48:02 +02003076 } else if (!strcmp(args[1], "auth")) {
3077 if (*(args[2]) == 0) {
3078 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3082 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_ALERT | ERR_ABORT;
3084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 }
3086 } else if (!strcmp(args[1], "scope")) {
3087 if (*(args[2]) == 0) {
3088 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003091 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3092 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003093 err_code |= ERR_ALERT | ERR_ABORT;
3094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003095 }
3096 } else if (!strcmp(args[1], "enable")) {
3097 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3098 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003099 err_code |= ERR_ALERT | ERR_ABORT;
3100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003101 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003102 } else if (!strcmp(args[1], "hide-version")) {
3103 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3104 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003105 err_code |= ERR_ALERT | ERR_ABORT;
3106 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003107 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003108 } else if (!strcmp(args[1], "show-legends")) {
3109 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3110 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3111 err_code |= ERR_ALERT | ERR_ABORT;
3112 goto out;
3113 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003114 } else if (!strcmp(args[1], "show-node")) {
3115
3116 if (*args[2]) {
3117 int i;
3118 char c;
3119
3120 for (i=0; args[2][i]; i++) {
3121 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003122 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3123 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003124 break;
3125 }
3126
3127 if (!i || args[2][i]) {
3128 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3129 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3130 file, linenum, args[0], args[1]);
3131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
3133 }
3134 }
3135
3136 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3137 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3138 err_code |= ERR_ALERT | ERR_ABORT;
3139 goto out;
3140 }
3141 } else if (!strcmp(args[1], "show-desc")) {
3142 char *desc = NULL;
3143
3144 if (*args[2]) {
3145 int i, len=0;
3146 char *d;
3147
3148 for(i=2; *args[i]; i++)
3149 len += strlen(args[i])+1;
3150
3151 desc = d = (char *)calloc(1, len);
3152
3153 d += sprintf(d, "%s", args[2]);
3154 for(i=3; *args[i]; i++)
3155 d += sprintf(d, " %s", args[i]);
3156 }
3157
3158 if (!*args[2] && !global.desc)
3159 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3160 file, linenum, args[1]);
3161 else {
3162 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3163 free(desc);
3164 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3165 err_code |= ERR_ALERT | ERR_ABORT;
3166 goto out;
3167 }
3168 free(desc);
3169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003170 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003171stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003172 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 +01003173 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176 }
3177 }
3178 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003179 int optnum;
3180
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003181 if (*(args[1]) == '\0') {
3182 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3183 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003187
3188 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3189 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003190 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3191 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3192 file, linenum, cfg_opts[optnum].name);
3193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
3195 }
Willy Tarreau93893792009-07-23 13:19:11 +02003196 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3197 err_code |= ERR_WARN;
3198 goto out;
3199 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003200
Willy Tarreau3842f002009-06-14 11:39:52 +02003201 curproxy->no_options &= ~cfg_opts[optnum].val;
3202 curproxy->options &= ~cfg_opts[optnum].val;
3203
3204 switch (kwm) {
3205 case KWM_STD:
3206 curproxy->options |= cfg_opts[optnum].val;
3207 break;
3208 case KWM_NO:
3209 curproxy->no_options |= cfg_opts[optnum].val;
3210 break;
3211 case KWM_DEF: /* already cleared */
3212 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003213 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003214
Willy Tarreau93893792009-07-23 13:19:11 +02003215 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003216 }
3217 }
3218
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003219 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3220 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003221 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3222 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3223 file, linenum, cfg_opts2[optnum].name);
3224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
3226 }
Willy Tarreau93893792009-07-23 13:19:11 +02003227 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3228 err_code |= ERR_WARN;
3229 goto out;
3230 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003231
Willy Tarreau3842f002009-06-14 11:39:52 +02003232 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3233 curproxy->options2 &= ~cfg_opts2[optnum].val;
3234
3235 switch (kwm) {
3236 case KWM_STD:
3237 curproxy->options2 |= cfg_opts2[optnum].val;
3238 break;
3239 case KWM_NO:
3240 curproxy->no_options2 |= cfg_opts2[optnum].val;
3241 break;
3242 case KWM_DEF: /* already cleared */
3243 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003244 }
Willy Tarreau93893792009-07-23 13:19:11 +02003245 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003246 }
3247 }
3248
Willy Tarreau3842f002009-06-14 11:39:52 +02003249 if (kwm != KWM_STD) {
3250 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003251 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003252 err_code |= ERR_ALERT | ERR_FATAL;
3253 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003254 }
3255
Emeric Brun3a058f32009-06-30 18:26:00 +02003256 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003258 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003260 if (*(args[2]) != '\0') {
3261 if (!strcmp(args[2], "clf")) {
3262 curproxy->options2 |= PR_O2_CLFLOG;
3263 } else {
3264 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003265 err_code |= ERR_ALERT | ERR_FATAL;
3266 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003267 }
3268 }
3269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 else if (!strcmp(args[1], "tcplog"))
3271 /* generate a detailed TCP log */
3272 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 else if (!strcmp(args[1], "tcpka")) {
3274 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003275 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003276 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003277
3278 if (curproxy->cap & PR_CAP_FE)
3279 curproxy->options |= PR_O_TCP_CLI_KA;
3280 if (curproxy->cap & PR_CAP_BE)
3281 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 }
3283 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003284 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003285 err_code |= ERR_WARN;
3286
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003288 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003289 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003290 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003291 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003292 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003293 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003294 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003295 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 if (!*args[2]) { /* no argument */
3297 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3298 curproxy->check_len = strlen(DEF_CHECK_REQ);
3299 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003300 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 curproxy->check_req = (char *)malloc(reqlen);
3302 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003303 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003305 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 if (*args[4])
3307 reqlen += strlen(args[4]);
3308 else
3309 reqlen += strlen("HTTP/1.0");
3310
3311 curproxy->check_req = (char *)malloc(reqlen);
3312 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003313 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003315 }
3316 else if (!strcmp(args[1], "ssl-hello-chk")) {
3317 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003318 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003319 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003320
Willy Tarreaua534fea2008-08-03 12:19:50 +02003321 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003322 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003323 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003324 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003325 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003326 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003327 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003328 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003329 }
Willy Tarreau23677902007-05-08 23:50:35 +02003330 else if (!strcmp(args[1], "smtpchk")) {
3331 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003332 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003333 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003334 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003335 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003336 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003337 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003338 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003339 curproxy->options |= PR_O_SMTP_CHK;
3340
3341 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3342 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3343 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3344 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3345 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3346 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3347 curproxy->check_req = (char *)malloc(reqlen);
3348 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3349 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3350 } else {
3351 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3352 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3353 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3354 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3355 }
3356 }
3357 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003358 else if (!strcmp(args[1], "pgsql-check")) {
3359 /* use PostgreSQL request to check servers' health */
3360 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3361 err_code |= ERR_WARN;
3362
3363 free(curproxy->check_req);
3364 curproxy->check_req = NULL;
3365 curproxy->options &= ~PR_O_HTTP_CHK;
3366 curproxy->options &= ~PR_O_SMTP_CHK;
3367 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3368 curproxy->options2 &= ~PR_O2_LDAP_CHK;
3369 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3370 curproxy->options2 |= PR_O2_PGSQL_CHK;
3371
3372 if (*(args[2])) {
3373 int cur_arg = 2;
3374
3375 while (*(args[cur_arg])) {
3376 if (strcmp(args[cur_arg], "user") == 0) {
3377 char * packet;
3378 uint32_t packet_len;
3379 uint32_t pv;
3380
3381 /* suboption header - needs additional argument for it */
3382 if (*(args[cur_arg+1]) == 0) {
3383 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3384 file, linenum, args[0], args[1], args[cur_arg]);
3385 err_code |= ERR_ALERT | ERR_FATAL;
3386 goto out;
3387 }
3388
3389 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3390 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3391 pv = htonl(0x30000); /* protocol version 3.0 */
3392
3393 packet = (char*) calloc(1, packet_len);
3394
3395 memcpy(packet + 4, &pv, 4);
3396
3397 /* copy "user" */
3398 memcpy(packet + 8, "user", 4);
3399
3400 /* copy username */
3401 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3402
3403 free(curproxy->check_req);
3404 curproxy->check_req = packet;
3405 curproxy->check_len = packet_len;
3406
3407 packet_len = htonl(packet_len);
3408 memcpy(packet, &packet_len, 4);
3409 cur_arg += 2;
3410 } else {
3411 /* unknown suboption - catchall */
3412 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3413 file, linenum, args[0], args[1]);
3414 err_code |= ERR_ALERT | ERR_FATAL;
3415 goto out;
3416 }
3417 } /* end while loop */
3418 }
3419 }
3420
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003421 else if (!strcmp(args[1], "mysql-check")) {
3422 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003423 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3424 err_code |= ERR_WARN;
3425
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003426 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003427 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003428 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003429 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003430 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003431 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003432 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003433 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003434
3435 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3436 * const char mysql40_client_auth_pkt[] = {
3437 * "\x0e\x00\x00" // packet length
3438 * "\x01" // packet number
3439 * "\x00\x00" // client capabilities
3440 * "\x00\x00\x01" // max packet
3441 * "haproxy\x00" // username (null terminated string)
3442 * "\x00" // filler (always 0x00)
3443 * "\x01\x00\x00" // packet length
3444 * "\x00" // packet number
3445 * "\x01" // COM_QUIT command
3446 * };
3447 */
3448
3449 if (*(args[2])) {
3450 int cur_arg = 2;
3451
3452 while (*(args[cur_arg])) {
3453 if (strcmp(args[cur_arg], "user") == 0) {
3454 char *mysqluser;
3455 int packetlen, reqlen, userlen;
3456
3457 /* suboption header - needs additional argument for it */
3458 if (*(args[cur_arg+1]) == 0) {
3459 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3460 file, linenum, args[0], args[1], args[cur_arg]);
3461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
3463 }
3464 mysqluser = args[cur_arg + 1];
3465 userlen = strlen(mysqluser);
3466 packetlen = userlen + 7;
3467 reqlen = packetlen + 9;
3468
3469 free(curproxy->check_req);
3470 curproxy->check_req = (char *)calloc(1, reqlen);
3471 curproxy->check_len = reqlen;
3472
3473 snprintf(curproxy->check_req, 4, "%c%c%c",
3474 ((unsigned char) packetlen & 0xff),
3475 ((unsigned char) (packetlen >> 8) & 0xff),
3476 ((unsigned char) (packetlen >> 16) & 0xff));
3477
3478 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003479 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003480 curproxy->check_req[8] = 1;
3481 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3482 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3483 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3484 cur_arg += 2;
3485 } else {
3486 /* unknown suboption - catchall */
3487 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3488 file, linenum, args[0], args[1]);
3489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
3491 }
3492 } /* end while loop */
3493 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003494 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003495 else if (!strcmp(args[1], "ldap-check")) {
3496 /* use LDAP request to check servers' health */
3497 free(curproxy->check_req);
3498 curproxy->check_req = NULL;
3499 curproxy->options &= ~PR_O_HTTP_CHK;
3500 curproxy->options &= ~PR_O_SMTP_CHK;
3501 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3502 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003503 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003504 curproxy->options2 |= PR_O2_LDAP_CHK;
3505
3506 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3507 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3508 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3509 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003510 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003511 int cur_arg;
3512
3513 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3514 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003515 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003516
3517 curproxy->options |= PR_O_FWDFOR;
3518
3519 free(curproxy->fwdfor_hdr_name);
3520 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3521 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3522
3523 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3524 cur_arg = 2;
3525 while (*(args[cur_arg])) {
3526 if (!strcmp(args[cur_arg], "except")) {
3527 /* suboption except - needs additional argument for it */
3528 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3529 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3530 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003531 err_code |= ERR_ALERT | ERR_FATAL;
3532 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003533 }
3534 /* flush useless bits */
3535 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003536 cur_arg += 2;
3537 } else if (!strcmp(args[cur_arg], "header")) {
3538 /* suboption header - needs additional argument for it */
3539 if (*(args[cur_arg+1]) == 0) {
3540 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3541 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003542 err_code |= ERR_ALERT | ERR_FATAL;
3543 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003544 }
3545 free(curproxy->fwdfor_hdr_name);
3546 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3547 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3548 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003549 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003550 /* unknown suboption - catchall */
3551 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3552 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003555 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003556 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003557 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003558 else if (!strcmp(args[1], "originalto")) {
3559 int cur_arg;
3560
3561 /* insert x-original-to field, but not for the IP address listed as an except.
3562 * set default options (ie: bitfield, header name, etc)
3563 */
3564
3565 curproxy->options |= PR_O_ORGTO;
3566
3567 free(curproxy->orgto_hdr_name);
3568 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3569 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3570
3571 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3572 cur_arg = 2;
3573 while (*(args[cur_arg])) {
3574 if (!strcmp(args[cur_arg], "except")) {
3575 /* suboption except - needs additional argument for it */
3576 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3577 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3578 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003581 }
3582 /* flush useless bits */
3583 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3584 cur_arg += 2;
3585 } else if (!strcmp(args[cur_arg], "header")) {
3586 /* suboption header - needs additional argument for it */
3587 if (*(args[cur_arg+1]) == 0) {
3588 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3589 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003590 err_code |= ERR_ALERT | ERR_FATAL;
3591 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003592 }
3593 free(curproxy->orgto_hdr_name);
3594 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3595 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3596 cur_arg += 2;
3597 } else {
3598 /* unknown suboption - catchall */
3599 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3600 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003603 }
3604 } /* end while loop */
3605 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003606 else {
3607 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003608 err_code |= ERR_ALERT | ERR_FATAL;
3609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003610 }
Willy Tarreau93893792009-07-23 13:19:11 +02003611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003613 else if (!strcmp(args[0], "default_backend")) {
3614 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003616
3617 if (*(args[1]) == 0) {
3618 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003619 err_code |= ERR_ALERT | ERR_FATAL;
3620 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003621 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003622 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003623 curproxy->defbe.name = strdup(args[1]);
3624 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003625 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003626 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003627 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003628
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003629 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3630 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 /* enable reconnections to dispatch */
3633 curproxy->options |= PR_O_REDISP;
3634 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003635 else if (!strcmp(args[0], "http-check")) {
3636 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003638
3639 if (strcmp(args[1], "disable-on-404") == 0) {
3640 /* enable a graceful server shutdown on an HTTP 404 response */
3641 curproxy->options |= PR_O_DISABLE404;
3642 }
Willy Tarreauef781042010-01-27 11:53:01 +01003643 else if (strcmp(args[1], "send-state") == 0) {
3644 /* enable emission of the apparent state of a server in HTTP checks */
3645 curproxy->options2 |= PR_O2_CHK_SNDST;
3646 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003647 else if (strcmp(args[1], "expect") == 0) {
3648 const char *ptr_arg;
3649 int cur_arg;
3650
3651 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3652 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
3655 }
3656
3657 cur_arg = 2;
3658 /* consider exclamation marks, sole or at the beginning of a word */
3659 while (*(ptr_arg = args[cur_arg])) {
3660 while (*ptr_arg == '!') {
3661 curproxy->options2 ^= PR_O2_EXP_INV;
3662 ptr_arg++;
3663 }
3664 if (*ptr_arg)
3665 break;
3666 cur_arg++;
3667 }
3668 /* now ptr_arg points to the beginning of a word past any possible
3669 * exclamation mark, and cur_arg is the argument which holds this word.
3670 */
3671 if (strcmp(ptr_arg, "status") == 0) {
3672 if (!*(args[cur_arg + 1])) {
3673 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3674 file, linenum, args[0], args[1], ptr_arg);
3675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
3677 }
3678 curproxy->options2 |= PR_O2_EXP_STS;
3679 curproxy->expect_str = strdup(args[cur_arg + 1]);
3680 }
3681 else if (strcmp(ptr_arg, "string") == 0) {
3682 if (!*(args[cur_arg + 1])) {
3683 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3684 file, linenum, args[0], args[1], ptr_arg);
3685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
3687 }
3688 curproxy->options2 |= PR_O2_EXP_STR;
3689 curproxy->expect_str = strdup(args[cur_arg + 1]);
3690 }
3691 else if (strcmp(ptr_arg, "rstatus") == 0) {
3692 if (!*(args[cur_arg + 1])) {
3693 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3694 file, linenum, args[0], args[1], ptr_arg);
3695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
3697 }
3698 curproxy->options2 |= PR_O2_EXP_RSTS;
3699 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3700 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3701 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3702 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3703 err_code |= ERR_ALERT | ERR_FATAL;
3704 goto out;
3705 }
3706 }
3707 else if (strcmp(ptr_arg, "rstring") == 0) {
3708 if (!*(args[cur_arg + 1])) {
3709 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3710 file, linenum, args[0], args[1], ptr_arg);
3711 err_code |= ERR_ALERT | ERR_FATAL;
3712 goto out;
3713 }
3714 curproxy->options2 |= PR_O2_EXP_RSTR;
3715 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3716 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3717 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3718 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
3721 }
3722 }
3723 else {
3724 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3725 file, linenum, args[0], args[1], ptr_arg);
3726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
3728 }
3729 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003730 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003731 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003734 }
3735 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003736 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003737 if (curproxy == &defproxy) {
3738 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003739 err_code |= ERR_ALERT | ERR_FATAL;
3740 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003741 }
3742
Willy Tarreaub80c2302007-11-30 20:51:32 +01003743 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003744 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003745
3746 if (strcmp(args[1], "fail") == 0) {
3747 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003748 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003749 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3750 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_ALERT | ERR_FATAL;
3752 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003753 }
3754
Willy Tarreauef6494c2010-01-28 17:12:36 +01003755 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003756 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3757 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003760 }
3761 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3762 }
3763 else {
3764 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003767 }
3768 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769#ifdef TPROXY
3770 else if (!strcmp(args[0], "transparent")) {
3771 /* enable transparent proxy connections */
3772 curproxy->options |= PR_O_TRANSP;
3773 }
3774#endif
3775 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003776 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003777 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003778
Willy Tarreaubaaee002006-06-26 02:48:02 +02003779 if (*(args[1]) == 0) {
3780 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003783 }
3784 curproxy->maxconn = atol(args[1]);
3785 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003786 else if (!strcmp(args[0], "backlog")) { /* backlog */
3787 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003789
3790 if (*(args[1]) == 0) {
3791 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003794 }
3795 curproxy->backlog = atol(args[1]);
3796 }
Willy Tarreau86034312006-12-29 00:10:33 +01003797 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003798 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003800
Willy Tarreau86034312006-12-29 00:10:33 +01003801 if (*(args[1]) == 0) {
3802 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003805 }
3806 curproxy->fullconn = atol(args[1]);
3807 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003808 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3809 if (*(args[1]) == 0) {
3810 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003811 err_code |= ERR_ALERT | ERR_FATAL;
3812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003814 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3815 if (err) {
3816 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3817 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003820 }
3821 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003822 }
3823 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003824 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 if (curproxy == &defproxy) {
3826 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003829 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003830 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003832
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 if (strchr(args[1], ':') == NULL) {
3834 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003837 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003838 sk = str2sa(args[1]);
3839 if (!sk) {
3840 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
3843 }
3844 curproxy->dispatch_addr = *sk;
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01003845 curproxy->options2 |= PR_O2_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003846 }
3847 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003848 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003849 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003850
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003851 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003852 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3853 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003856 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003858 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3859 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3860 err_code |= ERR_WARN;
3861
3862 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3863 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3864 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3865 }
3866 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3867 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3868 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3869 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003870 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3871 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3872 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3873 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003874 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003875 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003876 err_code |= ERR_ALERT | ERR_FATAL;
3877 goto out;
3878 }
3879 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003880 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003881 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003882 char *rport, *raddr;
3883 short realport = 0;
3884 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003885
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003886 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003888 err_code |= ERR_ALERT | ERR_FATAL;
3889 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003890 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003891 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893
3894 if (!*args[2]) {
3895 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3896 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003899 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003900
3901 err = invalid_char(args[1]);
3902 if (err) {
3903 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3904 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003905 err_code |= ERR_ALERT | ERR_FATAL;
3906 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003907 }
3908
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003909 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003910 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003911
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003912 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3913 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3914 err_code |= ERR_ALERT | ERR_ABORT;
3915 goto out;
3916 }
3917
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003918 /* the servers are linked backwards first */
3919 newsrv->next = curproxy->srv;
3920 curproxy->srv = newsrv;
3921 newsrv->proxy = curproxy;
3922 newsrv->conf.file = file;
3923 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003924
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003925 LIST_INIT(&newsrv->pendconns);
3926 do_check = 0;
3927 newsrv->state = SRV_RUNNING; /* early server setup */
3928 newsrv->last_change = now.tv_sec;
3929 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003930
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003931 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003932 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003933 * - IP: => port=+0, relative
3934 * - IP:N => port=N, absolute
3935 * - IP:+N => port=+N, relative
3936 * - IP:-N => port=-N, relative
3937 */
3938 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003939 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003940 if (rport) {
3941 *rport++ = 0;
3942 realport = atol(rport);
3943 if (!isdigit((unsigned char)*rport))
3944 newsrv->state |= SRV_MAPPORTS;
3945 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003946 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003947
Willy Tarreaufab5a432011-03-04 15:31:53 +01003948 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003949 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003950 if (!sk) {
3951 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3952 err_code |= ERR_ALERT | ERR_FATAL;
3953 goto out;
3954 }
3955 newsrv->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01003956
3957 switch (newsrv->addr.ss_family) {
3958 case AF_INET:
3959 ((struct sockaddr_in *)&newsrv->addr)->sin_port = htons(realport);
3960 break;
3961 case AF_INET6:
3962 ((struct sockaddr_in6 *)&newsrv->addr)->sin6_port = htons(realport);
3963 break;
3964 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003965
3966 newsrv->check_port = curproxy->defsrv.check_port;
3967 newsrv->inter = curproxy->defsrv.inter;
3968 newsrv->fastinter = curproxy->defsrv.fastinter;
3969 newsrv->downinter = curproxy->defsrv.downinter;
3970 newsrv->rise = curproxy->defsrv.rise;
3971 newsrv->fall = curproxy->defsrv.fall;
3972 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3973 newsrv->minconn = curproxy->defsrv.minconn;
3974 newsrv->maxconn = curproxy->defsrv.maxconn;
3975 newsrv->slowstart = curproxy->defsrv.slowstart;
3976 newsrv->onerror = curproxy->defsrv.onerror;
3977 newsrv->consecutive_errors_limit
3978 = curproxy->defsrv.consecutive_errors_limit;
3979 newsrv->uweight = newsrv->iweight
3980 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003982 newsrv->curfd = -1; /* no health-check in progress */
3983 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003984
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003985 cur_arg = 3;
3986 } else {
3987 newsrv = &curproxy->defsrv;
3988 cur_arg = 1;
3989 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003990
Willy Tarreaubaaee002006-06-26 02:48:02 +02003991 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003992 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003993 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003994
3995 if (!*args[cur_arg + 1]) {
3996 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3997 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003998 err_code |= ERR_ALERT | ERR_FATAL;
3999 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004000 }
4001
4002 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004003 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004004
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004005 if (newsrv->puid <= 0) {
4006 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004007 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004010 }
4011
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004012 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4013 if (node) {
4014 struct server *target = container_of(node, struct server, conf.id);
4015 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4016 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
4019 }
4020 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004021 cur_arg += 2;
4022 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004023 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004024 newsrv->cookie = strdup(args[cur_arg + 1]);
4025 newsrv->cklen = strlen(args[cur_arg + 1]);
4026 cur_arg += 2;
4027 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004028 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004029 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4030 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4031 cur_arg += 2;
4032 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004033 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004034 if (!*args[cur_arg + 1]) {
4035 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4036 file, linenum, args[cur_arg]);
4037 err_code |= ERR_ALERT | ERR_FATAL;
4038 goto out;
4039 }
4040
Willy Tarreaubaaee002006-06-26 02:48:02 +02004041 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004042 if (newsrv->rise <= 0) {
4043 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4044 file, linenum, args[cur_arg]);
4045 err_code |= ERR_ALERT | ERR_FATAL;
4046 goto out;
4047 }
4048
Willy Tarreau96839092010-03-29 10:02:24 +02004049 if (newsrv->health)
4050 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051 cur_arg += 2;
4052 }
4053 else if (!strcmp(args[cur_arg], "fall")) {
4054 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004055
4056 if (!*args[cur_arg + 1]) {
4057 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4058 file, linenum, args[cur_arg]);
4059 err_code |= ERR_ALERT | ERR_FATAL;
4060 goto out;
4061 }
4062
4063 if (newsrv->fall <= 0) {
4064 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4065 file, linenum, args[cur_arg]);
4066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
4068 }
4069
Willy Tarreaubaaee002006-06-26 02:48:02 +02004070 cur_arg += 2;
4071 }
4072 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004073 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4074 if (err) {
4075 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4076 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004077 err_code |= ERR_ALERT | ERR_FATAL;
4078 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004079 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004080 if (val <= 0) {
4081 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4082 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004085 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004086 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004087 cur_arg += 2;
4088 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004089 else if (!strcmp(args[cur_arg], "fastinter")) {
4090 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4091 if (err) {
4092 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4093 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004096 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004097 if (val <= 0) {
4098 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4099 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004102 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004103 newsrv->fastinter = val;
4104 cur_arg += 2;
4105 }
4106 else if (!strcmp(args[cur_arg], "downinter")) {
4107 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4108 if (err) {
4109 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4110 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004111 err_code |= ERR_ALERT | ERR_FATAL;
4112 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004113 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004114 if (val <= 0) {
4115 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4116 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004119 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004120 newsrv->downinter = val;
4121 cur_arg += 2;
4122 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004123 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004124 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004125 if (!sk) {
4126 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
4129 }
4130 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004131 cur_arg += 2;
4132 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004133 else if (!strcmp(args[cur_arg], "port")) {
4134 newsrv->check_port = atol(args[cur_arg + 1]);
4135 cur_arg += 2;
4136 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004137 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004138 newsrv->state |= SRV_BACKUP;
4139 cur_arg ++;
4140 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004141 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4142 newsrv->state |= SRV_SEND_PROXY;
4143 cur_arg ++;
4144 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004145 else if (!strcmp(args[cur_arg], "weight")) {
4146 int w;
4147 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004148 if (w < 0 || w > 256) {
4149 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004153 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004154 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004155 cur_arg += 2;
4156 }
4157 else if (!strcmp(args[cur_arg], "minconn")) {
4158 newsrv->minconn = atol(args[cur_arg + 1]);
4159 cur_arg += 2;
4160 }
4161 else if (!strcmp(args[cur_arg], "maxconn")) {
4162 newsrv->maxconn = atol(args[cur_arg + 1]);
4163 cur_arg += 2;
4164 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004165 else if (!strcmp(args[cur_arg], "maxqueue")) {
4166 newsrv->maxqueue = atol(args[cur_arg + 1]);
4167 cur_arg += 2;
4168 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004169 else if (!strcmp(args[cur_arg], "slowstart")) {
4170 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004171 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004172 if (err) {
4173 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4174 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004175 err_code |= ERR_ALERT | ERR_FATAL;
4176 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004177 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004178 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004179 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4180 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004181 err_code |= ERR_ALERT | ERR_FATAL;
4182 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004183 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004184 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004185 cur_arg += 2;
4186 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004187 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004188
4189 if (!*args[cur_arg + 1]) {
4190 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4191 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004192 err_code |= ERR_ALERT | ERR_FATAL;
4193 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004194 }
4195
4196 newsrv->trackit = strdup(args[cur_arg + 1]);
4197
4198 cur_arg += 2;
4199 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004200 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004201 global.maxsock++;
4202 do_check = 1;
4203 cur_arg += 1;
4204 }
Willy Tarreau96839092010-03-29 10:02:24 +02004205 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4206 newsrv->state |= SRV_MAINTAIN;
4207 newsrv->state &= ~SRV_RUNNING;
4208 newsrv->health = 0;
4209 cur_arg += 1;
4210 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004211 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004212 if (!strcmp(args[cur_arg + 1], "none"))
4213 newsrv->observe = HANA_OBS_NONE;
4214 else if (!strcmp(args[cur_arg + 1], "layer4"))
4215 newsrv->observe = HANA_OBS_LAYER4;
4216 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4217 if (curproxy->mode != PR_MODE_HTTP) {
4218 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4219 file, linenum, args[cur_arg + 1]);
4220 err_code |= ERR_ALERT;
4221 }
4222 newsrv->observe = HANA_OBS_LAYER7;
4223 }
4224 else {
4225 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004226 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004227 file, linenum, args[cur_arg], args[cur_arg + 1]);
4228 err_code |= ERR_ALERT | ERR_FATAL;
4229 goto out;
4230 }
4231
4232 cur_arg += 2;
4233 }
4234 else if (!strcmp(args[cur_arg], "on-error")) {
4235 if (!strcmp(args[cur_arg + 1], "fastinter"))
4236 newsrv->onerror = HANA_ONERR_FASTINTER;
4237 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4238 newsrv->onerror = HANA_ONERR_FAILCHK;
4239 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4240 newsrv->onerror = HANA_ONERR_SUDDTH;
4241 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4242 newsrv->onerror = HANA_ONERR_MARKDWN;
4243 else {
4244 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004245 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004246 file, linenum, args[cur_arg], args[cur_arg + 1]);
4247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
4249 }
4250
4251 cur_arg += 2;
4252 }
4253 else if (!strcmp(args[cur_arg], "error-limit")) {
4254 if (!*args[cur_arg + 1]) {
4255 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4256 file, linenum, args[cur_arg]);
4257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
4259 }
4260
4261 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4262
4263 if (newsrv->consecutive_errors_limit <= 0) {
4264 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4265 file, linenum, args[cur_arg]);
4266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
4268 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004269 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004270 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004271 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004272 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004273 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004274
Willy Tarreaubaaee002006-06-26 02:48:02 +02004275 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004276#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004277 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004278 file, linenum, "source", "usesrc");
4279#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004280 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004281 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004282#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004283 err_code |= ERR_ALERT | ERR_FATAL;
4284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004285 }
4286 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004287 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4288 if (!sk) {
4289 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4290 err_code |= ERR_ALERT | ERR_FATAL;
4291 goto out;
4292 }
4293 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004294
4295 if (port_low != port_high) {
4296 int i;
4297 if (port_low <= 0 || port_low > 65535 ||
4298 port_high <= 0 || port_high > 65535 ||
4299 port_low > port_high) {
4300 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4301 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004302 err_code |= ERR_ALERT | ERR_FATAL;
4303 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004304 }
4305 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4306 for (i = 0; i < newsrv->sport_range->size; i++)
4307 newsrv->sport_range->ports[i] = port_low + i;
4308 }
4309
Willy Tarreaubaaee002006-06-26 02:48:02 +02004310 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004311 while (*(args[cur_arg])) {
4312 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004313#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4314#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004315 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4316 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4317 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004318 err_code |= ERR_ALERT | ERR_FATAL;
4319 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004320 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004321#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004322 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004323 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004324 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004327 }
4328 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004329 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004330 newsrv->state |= SRV_TPROXY_CLI;
4331 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004332 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004333 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004334 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4335 char *name, *end;
4336
4337 name = args[cur_arg+1] + 7;
4338 while (isspace(*name))
4339 name++;
4340
4341 end = name;
4342 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4343 end++;
4344
4345 newsrv->state &= ~SRV_TPROXY_MASK;
4346 newsrv->state |= SRV_TPROXY_DYN;
4347 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4348 newsrv->bind_hdr_len = end - name;
4349 memcpy(newsrv->bind_hdr_name, name, end - name);
4350 newsrv->bind_hdr_name[end-name] = '\0';
4351 newsrv->bind_hdr_occ = -1;
4352
4353 /* now look for an occurrence number */
4354 while (isspace(*end))
4355 end++;
4356 if (*end == ',') {
4357 end++;
4358 name = end;
4359 if (*end == '-')
4360 end++;
4361 while (isdigit(*end))
4362 end++;
4363 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4364 }
4365
4366 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4367 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4368 " occurrences values smaller than %d.\n",
4369 file, linenum, MAX_HDR_HISTORY);
4370 err_code |= ERR_ALERT | ERR_FATAL;
4371 goto out;
4372 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004373 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004374 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004375 if (!sk) {
4376 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4377 err_code |= ERR_ALERT | ERR_FATAL;
4378 goto out;
4379 }
4380 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004381 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004382 }
4383 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004384#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004385 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004386#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004387 cur_arg += 2;
4388 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004389#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004390 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004391 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004392 err_code |= ERR_ALERT | ERR_FATAL;
4393 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004394#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4395 } /* "usesrc" */
4396
4397 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4398#ifdef SO_BINDTODEVICE
4399 if (!*args[cur_arg + 1]) {
4400 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4401 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004402 err_code |= ERR_ALERT | ERR_FATAL;
4403 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004404 }
4405 if (newsrv->iface_name)
4406 free(newsrv->iface_name);
4407
4408 newsrv->iface_name = strdup(args[cur_arg + 1]);
4409 newsrv->iface_len = strlen(newsrv->iface_name);
4410 global.last_checks |= LSTCHK_NETADM;
4411#else
4412 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4413 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004414 err_code |= ERR_ALERT | ERR_FATAL;
4415 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004416#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004417 cur_arg += 2;
4418 continue;
4419 }
4420 /* this keyword in not an option of "source" */
4421 break;
4422 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004423 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004424 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004425 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4426 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004429 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004430 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004431 if (!defsrv)
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004432 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', '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 +01004433 file, linenum, newsrv->id);
4434 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004435 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 +01004436 file, linenum);
4437
Willy Tarreau93893792009-07-23 13:19:11 +02004438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004440 }
4441 }
4442
4443 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004444 if (newsrv->trackit) {
4445 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4446 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004447 err_code |= ERR_ALERT | ERR_FATAL;
4448 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004449 }
4450
David du Colombier6f5ccb12011-03-10 22:26:24 +01004451 switch (newsrv->check_addr.ss_family) {
4452 case AF_INET:
4453 if (!newsrv->check_port && ((struct sockaddr_in *)&newsrv->check_addr)->sin_port)
4454 newsrv->check_port = ntohs(((struct sockaddr_in *)&newsrv->check_addr)->sin_port);
4455 break;
4456 case AF_INET6:
4457 if (!newsrv->check_port && ((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port)
4458 newsrv->check_port = ntohs(((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port);
4459 break;
4460 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004461
Willy Tarreaubaaee002006-06-26 02:48:02 +02004462 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4463 newsrv->check_port = realport; /* by default */
4464 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004465 /* not yet valid, because no port was set on
4466 * the server either. We'll check if we have
4467 * a known port on the first listener.
4468 */
4469 struct listener *l;
4470 l = curproxy->listen;
4471 if (l) {
4472 int port;
4473 port = (l->addr.ss_family == AF_INET6)
4474 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4475 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4476 newsrv->check_port = port;
4477 }
4478 }
4479 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004480 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4481 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004482 err_code |= ERR_ALERT | ERR_FATAL;
4483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004485
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004486 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004487 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004488 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4489 err_code |= ERR_ALERT | ERR_ABORT;
4490 goto out;
4491 }
4492
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004493 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004494 newsrv->state |= SRV_CHECKED;
4495 }
4496
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004497 if (!defsrv) {
4498 if (newsrv->state & SRV_BACKUP)
4499 curproxy->srv_bck++;
4500 else
4501 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004502
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004503 newsrv->prev_state = newsrv->state;
4504 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505 }
4506 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004507 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004508 int facility;
4509
4510 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4511 curproxy->logfac1 = global.logfac1;
4512 curproxy->logsrv1 = global.logsrv1;
4513 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004514 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004515 curproxy->logfac2 = global.logfac2;
4516 curproxy->logsrv2 = global.logsrv2;
4517 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004518 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004519 }
4520 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004521 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004522
4523 facility = get_log_facility(args[2]);
4524 if (facility < 0) {
4525 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4526 exit(1);
4527 }
4528
4529 level = 7; /* max syslog level = debug */
4530 if (*(args[3])) {
4531 level = get_log_level(args[3]);
4532 if (level < 0) {
4533 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4534 exit(1);
4535 }
4536 }
4537
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004538 minlvl = 0; /* limit syslog level to this level (emerg) */
4539 if (*(args[4])) {
4540 minlvl = get_log_level(args[4]);
4541 if (level < 0) {
4542 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4543 exit(1);
4544 }
4545 }
4546
Robert Tsai81ae1952007-12-05 10:47:29 +01004547 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004548 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004549 if (!sk) {
4550 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004551 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
4554 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004555 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004556 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004557 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004558 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004559 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4560 err_code |= ERR_ALERT | ERR_FATAL;
4561 goto out;
4562 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004563 logsrv.addr = *sk;
4564 if (!get_host_port(&logsrv.addr))
4565 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004567
4568 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004569 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004570 curproxy->logfac1 = facility;
4571 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004572 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573 }
4574 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004575 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 curproxy->logfac2 = facility;
4577 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004578 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 }
4580 else {
4581 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004582 err_code |= ERR_ALERT | ERR_FATAL;
4583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004584 }
4585 }
4586 else {
4587 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4588 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004589 err_code |= ERR_ALERT | ERR_FATAL;
4590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004591 }
4592 }
4593 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004594 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004595 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004596
Willy Tarreau977b8e42006-12-29 14:19:17 +01004597 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004598 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004599
Willy Tarreaubaaee002006-06-26 02:48:02 +02004600 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004601 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4602 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004606
4607 /* we must first clear any optional default setting */
4608 curproxy->options &= ~PR_O_TPXY_MASK;
4609 free(curproxy->iface_name);
4610 curproxy->iface_name = NULL;
4611 curproxy->iface_len = 0;
4612
Willy Tarreaud5191e72010-02-09 20:50:45 +01004613 sk = str2sa(args[1]);
4614 if (!sk) {
4615 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4616 err_code |= ERR_ALERT | ERR_FATAL;
4617 goto out;
4618 }
4619 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004620 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004621
4622 cur_arg = 2;
4623 while (*(args[cur_arg])) {
4624 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004625#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4626#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004627 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4628 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4629 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004630 err_code |= ERR_ALERT | ERR_FATAL;
4631 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004632 }
4633#endif
4634 if (!*args[cur_arg + 1]) {
4635 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4636 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004639 }
4640
4641 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004642 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004643 curproxy->options |= PR_O_TPXY_CLI;
4644 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004645 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004646 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004647 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4648 char *name, *end;
4649
4650 name = args[cur_arg+1] + 7;
4651 while (isspace(*name))
4652 name++;
4653
4654 end = name;
4655 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4656 end++;
4657
4658 curproxy->options &= ~PR_O_TPXY_MASK;
4659 curproxy->options |= PR_O_TPXY_DYN;
4660 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4661 curproxy->bind_hdr_len = end - name;
4662 memcpy(curproxy->bind_hdr_name, name, end - name);
4663 curproxy->bind_hdr_name[end-name] = '\0';
4664 curproxy->bind_hdr_occ = -1;
4665
4666 /* now look for an occurrence number */
4667 while (isspace(*end))
4668 end++;
4669 if (*end == ',') {
4670 end++;
4671 name = end;
4672 if (*end == '-')
4673 end++;
4674 while (isdigit(*end))
4675 end++;
4676 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4677 }
4678
4679 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4680 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4681 " occurrences values smaller than %d.\n",
4682 file, linenum, MAX_HDR_HISTORY);
4683 err_code |= ERR_ALERT | ERR_FATAL;
4684 goto out;
4685 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004686 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004687 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004688 if (!sk) {
4689 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4690 err_code |= ERR_ALERT | ERR_FATAL;
4691 goto out;
4692 }
4693 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004694 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004695 }
4696 global.last_checks |= LSTCHK_NETADM;
4697#if !defined(CONFIG_HAP_LINUX_TPROXY)
4698 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004699#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004700#else /* no TPROXY support */
4701 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004702 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004703 err_code |= ERR_ALERT | ERR_FATAL;
4704 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004705#endif
4706 cur_arg += 2;
4707 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004708 }
4709
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004710 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4711#ifdef SO_BINDTODEVICE
4712 if (!*args[cur_arg + 1]) {
4713 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4714 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004717 }
4718 if (curproxy->iface_name)
4719 free(curproxy->iface_name);
4720
4721 curproxy->iface_name = strdup(args[cur_arg + 1]);
4722 curproxy->iface_len = strlen(curproxy->iface_name);
4723 global.last_checks |= LSTCHK_NETADM;
4724#else
4725 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4726 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004729#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004730 cur_arg += 2;
4731 continue;
4732 }
4733 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4734 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004735 err_code |= ERR_ALERT | ERR_FATAL;
4736 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004737 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004738 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004739 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4740 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4741 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004742 err_code |= ERR_ALERT | ERR_FATAL;
4743 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004744 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004745 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004746 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004747 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4748 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004749 err_code |= ERR_ALERT | ERR_FATAL;
4750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004752
4753 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4754 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004755 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004756 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 }
4759 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004760 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4761 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004762 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004763 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004765 }
4766 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004767 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4768 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004769 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004770 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004772 }
4773 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004774 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4775 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004776 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004777 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004779 }
4780 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004781 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4782 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004783 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004784 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004786 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004787 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004788 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4789 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004790 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004791 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004792 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004793 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004794 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004795 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4796 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004797 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004798 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004799 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004800 }
4801 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004802 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4803 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004804 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004805 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004806 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004807 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004808 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004809 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004810 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4811 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004812 err_code |= ERR_ALERT | ERR_FATAL;
4813 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004815
4816 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4817 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004818 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004819 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004821 }
4822 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004823 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4824 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004825 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004826 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004827 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004828 }
4829 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004830 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4831 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004832 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004833 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004835 }
4836 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004837 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4838 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004839 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004840 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 }
4843 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004844 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4845 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004846 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004847 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004849 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004850 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004851 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4852 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004853 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004854 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004855 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004856 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004857 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004858 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004859
Willy Tarreaubaaee002006-06-26 02:48:02 +02004860 if (curproxy == &defproxy) {
4861 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004862 err_code |= ERR_ALERT | ERR_FATAL;
4863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004865 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004866 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004867
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 if (*(args[1]) == 0) {
4869 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004873
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004874 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4875 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4876 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4877 file, linenum, args[0]);
4878 err_code |= ERR_ALERT | ERR_FATAL;
4879 goto out;
4880 }
4881 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4882 }
4883 else if (*args[2]) {
4884 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4885 file, linenum, args[0], args[2]);
4886 err_code |= ERR_ALERT | ERR_FATAL;
4887 goto out;
4888 }
4889
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004890 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004891 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004892 wl->s = strdup(args[1]);
4893 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004894 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004895 }
4896 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004897 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4899 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004902 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004903
Willy Tarreauade5ec42010-01-28 19:33:49 +01004904 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4905 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004906 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004907 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004909 }
4910 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004911 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4912 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004913 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004914 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004916 }
4917 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004918 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4919 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004920 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004921 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923 }
4924 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004925 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004926 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4927 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004928 err_code |= ERR_ALERT | ERR_FATAL;
4929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 }
4931
Willy Tarreauade5ec42010-01-28 19:33:49 +01004932 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4933 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004934 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004935 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937 }
4938 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004939 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4940 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004941 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004942 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944 }
4945 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004946 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4947 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004948 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004949 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 }
4952 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004953 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004954
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 if (curproxy == &defproxy) {
4956 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004957 err_code |= ERR_ALERT | ERR_FATAL;
4958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004960 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004961 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962
Willy Tarreaubaaee002006-06-26 02:48:02 +02004963 if (*(args[1]) == 0) {
4964 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967 }
4968
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004969 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4970 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4971 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4972 file, linenum, args[0]);
4973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
4975 }
4976 err_code |= warnif_cond_requires_req(cond, file, linenum);
4977 }
4978 else if (*args[2]) {
4979 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4980 file, linenum, args[0], args[2]);
4981 err_code |= ERR_ALERT | ERR_FATAL;
4982 goto out;
4983 }
4984
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004985 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004986 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004987 wl->s = strdup(args[1]);
4988 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004989 }
4990 else if (!strcmp(args[0], "errorloc") ||
4991 !strcmp(args[0], "errorloc302") ||
4992 !strcmp(args[0], "errorloc303")) { /* error location */
4993 int errnum, errlen;
4994 char *err;
4995
Willy Tarreau977b8e42006-12-29 14:19:17 +01004996 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004997 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004998
Willy Tarreaubaaee002006-06-26 02:48:02 +02004999 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005000 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 }
5004
5005 errnum = atol(args[1]);
5006 if (!strcmp(args[0], "errorloc303")) {
5007 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5008 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5009 } else {
5010 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5011 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5012 }
5013
Willy Tarreau0f772532006-12-23 20:51:41 +01005014 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5015 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005016 chunk_destroy(&curproxy->errmsg[rc]);
5017 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005018 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005021
5022 if (rc >= HTTP_ERR_SIZE) {
5023 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5024 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 free(err);
5026 }
5027 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005028 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5029 int errnum, errlen, fd;
5030 char *err;
5031 struct stat stat;
5032
5033 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005034 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005035
5036 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005037 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005038 err_code |= ERR_ALERT | ERR_FATAL;
5039 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005040 }
5041
5042 fd = open(args[2], O_RDONLY);
5043 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5044 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5045 file, linenum, args[2], args[1]);
5046 if (fd >= 0)
5047 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005048 err_code |= ERR_ALERT | ERR_FATAL;
5049 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005050 }
5051
Willy Tarreau27a674e2009-08-17 07:23:33 +02005052 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005053 errlen = stat.st_size;
5054 } else {
5055 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005056 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005057 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005058 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005059 }
5060
5061 err = malloc(errlen); /* malloc() must succeed during parsing */
5062 errnum = read(fd, err, errlen);
5063 if (errnum != errlen) {
5064 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5065 file, linenum, args[2], args[1]);
5066 close(fd);
5067 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_ALERT | ERR_FATAL;
5069 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005070 }
5071 close(fd);
5072
5073 errnum = atol(args[1]);
5074 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5075 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005076 chunk_destroy(&curproxy->errmsg[rc]);
5077 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005078 break;
5079 }
5080 }
5081
5082 if (rc >= HTTP_ERR_SIZE) {
5083 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5084 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005085 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005086 free(err);
5087 }
5088 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005090 struct cfg_kw_list *kwl;
5091 int index;
5092
5093 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5094 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5095 if (kwl->kw[index].section != CFG_LISTEN)
5096 continue;
5097 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5098 /* prepare error message just in case */
5099 snprintf(trash, sizeof(trash),
5100 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005101 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5102 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005103 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005104 err_code |= ERR_ALERT | ERR_FATAL;
5105 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005106 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005107 else if (rc > 0) {
5108 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005109 err_code |= ERR_WARN;
5110 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005111 }
Willy Tarreau93893792009-07-23 13:19:11 +02005112 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005113 }
5114 }
5115 }
5116
Willy Tarreau6daf3432008-01-22 16:44:08 +01005117 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005118 err_code |= ERR_ALERT | ERR_FATAL;
5119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005120 }
Willy Tarreau93893792009-07-23 13:19:11 +02005121 out:
5122 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005123}
5124
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005125int
5126cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5127{
5128
5129 int err_code = 0;
5130 const char *err;
5131
5132 if (!strcmp(args[0], "userlist")) { /* new userlist */
5133 struct userlist *newul;
5134
5135 if (!*args[1]) {
5136 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5137 file, linenum, args[0]);
5138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
5140 }
5141
5142 err = invalid_char(args[1]);
5143 if (err) {
5144 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5145 file, linenum, *err, args[0], args[1]);
5146 err_code |= ERR_ALERT | ERR_FATAL;
5147 goto out;
5148 }
5149
5150 for (newul = userlist; newul; newul = newul->next)
5151 if (!strcmp(newul->name, args[1])) {
5152 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5153 file, linenum, args[1]);
5154 err_code |= ERR_WARN;
5155 goto out;
5156 }
5157
5158 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5159 if (!newul) {
5160 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5161 err_code |= ERR_ALERT | ERR_ABORT;
5162 goto out;
5163 }
5164
5165 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5166 newul->name = strdup(args[1]);
5167
5168 if (!newul->groupusers | !newul->name) {
5169 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5170 err_code |= ERR_ALERT | ERR_ABORT;
5171 goto out;
5172 }
5173
5174 newul->next = userlist;
5175 userlist = newul;
5176
5177 } else if (!strcmp(args[0], "group")) { /* new group */
5178 int cur_arg, i;
5179 const char *err;
5180
5181 if (!*args[1]) {
5182 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5183 file, linenum, args[0]);
5184 err_code |= ERR_ALERT | ERR_FATAL;
5185 goto out;
5186 }
5187
5188 err = invalid_char(args[1]);
5189 if (err) {
5190 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5191 file, linenum, *err, args[0], args[1]);
5192 err_code |= ERR_ALERT | ERR_FATAL;
5193 goto out;
5194 }
5195
5196 for(i = 0; i < userlist->grpcnt; i++)
5197 if (!strcmp(userlist->groups[i], args[1])) {
5198 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5199 file, linenum, args[1], userlist->name);
5200 err_code |= ERR_ALERT;
5201 goto out;
5202 }
5203
5204 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5205 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5206 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
5209 }
5210
5211 cur_arg = 2;
5212
5213 while (*args[cur_arg]) {
5214 if (!strcmp(args[cur_arg], "users")) {
5215 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5216 cur_arg += 2;
5217 continue;
5218 } else {
5219 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5220 file, linenum, args[0]);
5221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
5223 }
5224 }
5225
5226 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5227 } else if (!strcmp(args[0], "user")) { /* new user */
5228 struct auth_users *newuser;
5229 int cur_arg;
5230
5231 if (!*args[1]) {
5232 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5233 file, linenum, args[0]);
5234 err_code |= ERR_ALERT | ERR_FATAL;
5235 goto out;
5236 }
5237
5238 for (newuser = userlist->users; newuser; newuser = newuser->next)
5239 if (!strcmp(newuser->user, args[1])) {
5240 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5241 file, linenum, args[1], userlist->name);
5242 err_code |= ERR_ALERT;
5243 goto out;
5244 }
5245
5246 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5247 if (!newuser) {
5248 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5249 err_code |= ERR_ALERT | ERR_ABORT;
5250 goto out;
5251 }
5252
5253 newuser->user = strdup(args[1]);
5254
5255 newuser->next = userlist->users;
5256 userlist->users = newuser;
5257
5258 cur_arg = 2;
5259
5260 while (*args[cur_arg]) {
5261 if (!strcmp(args[cur_arg], "password")) {
5262#ifndef CONFIG_HAP_CRYPT
5263 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5264 file, linenum);
5265 err_code |= ERR_ALERT;
5266#endif
5267 newuser->pass = strdup(args[cur_arg + 1]);
5268 cur_arg += 2;
5269 continue;
5270 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5271 newuser->pass = strdup(args[cur_arg + 1]);
5272 newuser->flags |= AU_O_INSECURE;
5273 cur_arg += 2;
5274 continue;
5275 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005276 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005277 cur_arg += 2;
5278 continue;
5279 } else {
5280 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5281 file, linenum, args[0]);
5282 err_code |= ERR_ALERT | ERR_FATAL;
5283 goto out;
5284 }
5285 }
5286 } else {
5287 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5288 err_code |= ERR_ALERT | ERR_FATAL;
5289 }
5290
5291out:
5292 return err_code;
5293}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005294
5295/*
5296 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005297 * Returns the error code, 0 if OK, or any combination of :
5298 * - ERR_ABORT: must abort ASAP
5299 * - ERR_FATAL: we can continue parsing but not start the service
5300 * - ERR_WARN: a warning has been emitted
5301 * - ERR_ALERT: an alert has been emitted
5302 * Only the two first ones can stop processing, the two others are just
5303 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005305int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005307 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 FILE *f;
5309 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005311 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312
Willy Tarreaubaaee002006-06-26 02:48:02 +02005313 if ((f=fopen(file,"r")) == NULL)
5314 return -1;
5315
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005316 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005317 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005318 char *end;
5319 char *args[MAX_LINE_ARGS + 1];
5320 char *line = thisline;
5321
Willy Tarreaubaaee002006-06-26 02:48:02 +02005322 linenum++;
5323
5324 end = line + strlen(line);
5325
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005326 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5327 /* Check if we reached the limit and the last char is not \n.
5328 * Watch out for the last line without the terminating '\n'!
5329 */
5330 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005331 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005332 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005333 }
5334
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005336 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337 line++;
5338
5339 arg = 0;
5340 args[arg] = line;
5341
5342 while (*line && arg < MAX_LINE_ARGS) {
5343 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5344 * C equivalent value. Other combinations left unchanged (eg: \1).
5345 */
5346 if (*line == '\\') {
5347 int skip = 0;
5348 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5349 *line = line[1];
5350 skip = 1;
5351 }
5352 else if (line[1] == 'r') {
5353 *line = '\r';
5354 skip = 1;
5355 }
5356 else if (line[1] == 'n') {
5357 *line = '\n';
5358 skip = 1;
5359 }
5360 else if (line[1] == 't') {
5361 *line = '\t';
5362 skip = 1;
5363 }
5364 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005365 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005366 unsigned char hex1, hex2;
5367 hex1 = toupper(line[2]) - '0';
5368 hex2 = toupper(line[3]) - '0';
5369 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5370 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5371 *line = (hex1<<4) + hex2;
5372 skip = 3;
5373 }
5374 else {
5375 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005376 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005377 }
5378 }
5379 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005380 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005381 end -= skip;
5382 }
5383 line++;
5384 }
5385 else if (*line == '#' || *line == '\n' || *line == '\r') {
5386 /* end of string, end of loop */
5387 *line = 0;
5388 break;
5389 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005390 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005391 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005392 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005393 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005394 line++;
5395 args[++arg] = line;
5396 }
5397 else {
5398 line++;
5399 }
5400 }
5401
5402 /* empty line */
5403 if (!**args)
5404 continue;
5405
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005406 if (*line) {
5407 /* we had to stop due to too many args.
5408 * Let's terminate the string, print the offending part then cut the
5409 * last arg.
5410 */
5411 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5412 line++;
5413 *line = '\0';
5414
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005415 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005416 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005417 err_code |= ERR_ALERT | ERR_FATAL;
5418 args[arg] = line;
5419 }
5420
Willy Tarreau540abe42007-05-02 20:50:16 +02005421 /* zero out remaining args and ensure that at least one entry
5422 * is zeroed out.
5423 */
5424 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005425 args[arg] = line;
5426 }
5427
Willy Tarreau3842f002009-06-14 11:39:52 +02005428 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005429 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005430 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005431 for (arg=0; *args[arg+1]; arg++)
5432 args[arg] = args[arg+1]; // shift args after inversion
5433 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005434 else if (!strcmp(args[0], "default")) {
5435 kwm = KWM_DEF;
5436 for (arg=0; *args[arg+1]; arg++)
5437 args[arg] = args[arg+1]; // shift args after inversion
5438 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005439
Willy Tarreau3842f002009-06-14 11:39:52 +02005440 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5441 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005442 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005443 }
5444
Willy Tarreau977b8e42006-12-29 14:19:17 +01005445 if (!strcmp(args[0], "listen") ||
5446 !strcmp(args[0], "frontend") ||
5447 !strcmp(args[0], "backend") ||
5448 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005449 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005450 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005451 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005452 cursection = strdup(args[0]);
5453 }
5454 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005455 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005456 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005457 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005458 }
5459 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005460 confsect = CFG_USERLIST;
5461 free(cursection);
5462 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005463 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005464 else if (!strcmp(args[0], "peers")) {
5465 confsect = CFG_PEERS;
5466 free(cursection);
5467 cursection = strdup(args[0]);
5468 }
5469
Willy Tarreaubaaee002006-06-26 02:48:02 +02005470 /* else it's a section keyword */
5471
5472 switch (confsect) {
5473 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005474 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005475 break;
5476 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005477 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005478 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005479 case CFG_USERLIST:
5480 err_code |= cfg_parse_users(file, linenum, args, kwm);
5481 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005482 case CFG_PEERS:
5483 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5484 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005485 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005486 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005487 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005488 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005489
5490 if (err_code & ERR_ABORT)
5491 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005492 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005493 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005494 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005496 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005497}
5498
Willy Tarreaubb925012009-07-23 13:36:36 +02005499/*
5500 * Returns the error code, 0 if OK, or any combination of :
5501 * - ERR_ABORT: must abort ASAP
5502 * - ERR_FATAL: we can continue parsing but not start the service
5503 * - ERR_WARN: a warning has been emitted
5504 * - ERR_ALERT: an alert has been emitted
5505 * Only the two first ones can stop processing, the two others are just
5506 * indicators.
5507 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005508int check_config_validity()
5509{
5510 int cfgerr = 0;
5511 struct proxy *curproxy = NULL;
5512 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005513 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005514 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005515 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516
5517 /*
5518 * Now, check for the integrity of all that we have collected.
5519 */
5520
5521 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005522 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005524 /* first, we will invert the proxy list order */
5525 curproxy = NULL;
5526 while (proxy) {
5527 struct proxy *next;
5528
5529 next = proxy->next;
5530 proxy->next = curproxy;
5531 curproxy = proxy;
5532 if (!next)
5533 break;
5534 proxy = next;
5535 }
5536
Willy Tarreaubaaee002006-06-26 02:48:02 +02005537 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005538 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005539 err_code |= ERR_ALERT | ERR_FATAL;
5540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005541 }
5542
5543 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005544 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005545 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005546 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005547 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005548 unsigned int next_id;
5549
5550 if (!curproxy->uuid) {
5551 /* proxy ID not set, use automatic numbering with first
5552 * spare entry starting with next_pxid.
5553 */
5554 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5555 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5556 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005557 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005558 next_pxid++;
5559
Willy Tarreau55ea7572007-06-17 19:56:27 +02005560
Willy Tarreaubaaee002006-06-26 02:48:02 +02005561 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005562 /* ensure we don't keep listeners uselessly bound */
5563 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005564 curproxy = curproxy->next;
5565 continue;
5566 }
5567
Willy Tarreauff01a212009-03-15 13:46:16 +01005568 switch (curproxy->mode) {
5569 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005570 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005571 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005572 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5573 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005574 cfgerr++;
5575 }
5576
5577 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005578 Warning("config : servers will be ignored for %s '%s'.\n",
5579 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005580 break;
5581
5582 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005583 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005584 break;
5585
5586 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005587 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005588 break;
5589 }
5590
5591 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005592 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5593 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 cfgerr++;
5595 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005596
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005597 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005598 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005599 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005600 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5601 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005602 cfgerr++;
5603 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005604#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005605 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005606 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5607 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005608 cfgerr++;
5609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610#endif
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005611 else if (curproxy->options2 & PR_O2_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005612 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5613 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005614 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005615 }
5616 }
5617 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005618 !(curproxy->options2 & PR_O2_DISPATCH)) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005619 /* If no LB algo is set in a backend, and we're not in
5620 * transparent mode, dispatch mode nor proxy mode, we
5621 * want to use balance roundrobin by default.
5622 */
5623 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5624 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005625 }
5626 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005627
Willy Tarreaud6cc5322011-03-04 17:30:54 +01005628 if (curproxy->options2 & PR_O2_DISPATCH) {
5629 curproxy->options &= ~PR_O_TRANSP;
5630 curproxy->options &= ~PR_O_HTTP_PROXY;
5631 }
5632 else if (curproxy->options & PR_O_HTTP_PROXY) {
5633 curproxy->options2 &= ~PR_O2_DISPATCH;
5634 curproxy->options &= ~PR_O_TRANSP;
5635 }
5636 else if (curproxy->options & PR_O_TRANSP) {
5637 curproxy->options2 &= ~PR_O2_DISPATCH;
5638 curproxy->options &= ~PR_O_HTTP_PROXY;
5639 }
5640
Willy Tarreau82936582007-11-30 15:20:09 +01005641 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5642 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005643 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5644 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005645 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005646 }
5647
Willy Tarreauef781042010-01-27 11:53:01 +01005648 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5649 curproxy->options &= ~PR_O2_CHK_SNDST;
5650 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5651 "send-state", proxy_type_str(curproxy), curproxy->id);
5652 err_code |= ERR_WARN;
5653 }
5654
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005655 /* if a default backend was specified, let's find it */
5656 if (curproxy->defbe.name) {
5657 struct proxy *target;
5658
Alex Williams96532db2009-11-01 21:27:13 -05005659 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005660 if (!target) {
5661 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5662 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005663 cfgerr++;
5664 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005665 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5666 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005667 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005668 } else {
5669 free(curproxy->defbe.name);
5670 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005671 /* we force the backend to be present on at least all of
5672 * the frontend's processes.
5673 */
5674 target->bind_proc = curproxy->bind_proc ?
5675 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005676 }
5677 }
5678
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005679 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005680 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5681 /* map jump target for ACT_SETBE in req_rep chain */
5682 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005683 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005684 struct proxy *target;
5685
Willy Tarreaua496b602006-12-17 23:15:24 +01005686 if (exp->action != ACT_SETBE)
5687 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005688
Alex Williams96532db2009-11-01 21:27:13 -05005689 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005690 if (!target) {
5691 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5692 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005693 cfgerr++;
5694 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005695 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5696 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005697 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005698 } else {
5699 free((void *)exp->replace);
5700 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005701 /* we force the backend to be present on at least all of
5702 * the frontend's processes.
5703 */
5704 target->bind_proc = curproxy->bind_proc ?
5705 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005706 }
5707 }
5708 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005709
5710 /* find the target proxy for 'use_backend' rules */
5711 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005712 struct proxy *target;
5713
Alex Williams96532db2009-11-01 21:27:13 -05005714 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005715
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005716 if (!target) {
5717 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5718 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005719 cfgerr++;
5720 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005721 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5722 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005723 cfgerr++;
5724 } else {
5725 free((void *)rule->be.name);
5726 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005727 /* we force the backend to be present on at least all of
5728 * the frontend's processes.
5729 */
5730 target->bind_proc = curproxy->bind_proc ?
5731 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005732 }
5733 }
5734
Emeric Brunb982a3d2010-01-04 15:45:53 +01005735 /* find the target table for 'stick' rules */
5736 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5737 struct proxy *target;
5738
Emeric Brun1d33b292010-01-04 15:47:17 +01005739 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5740 if (mrule->flags & STK_IS_STORE)
5741 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5742
Emeric Brunb982a3d2010-01-04 15:45:53 +01005743 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005744 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005745 else
5746 target = curproxy;
5747
5748 if (!target) {
5749 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5750 curproxy->id, mrule->table.name);
5751 cfgerr++;
5752 }
5753 else if (target->table.size == 0) {
5754 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5755 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5756 cfgerr++;
5757 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005758 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005759 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5760 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5761 cfgerr++;
5762 }
5763 else {
5764 free((void *)mrule->table.name);
5765 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005766 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005767 }
5768 }
5769
5770 /* find the target table for 'store response' rules */
5771 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5772 struct proxy *target;
5773
Emeric Brun1d33b292010-01-04 15:47:17 +01005774 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5775
Emeric Brunb982a3d2010-01-04 15:45:53 +01005776 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005777 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005778 else
5779 target = curproxy;
5780
5781 if (!target) {
5782 Alert("Proxy '%s': unable to find store table '%s'.\n",
5783 curproxy->id, mrule->table.name);
5784 cfgerr++;
5785 }
5786 else if (target->table.size == 0) {
5787 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5788 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5789 cfgerr++;
5790 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005791 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005792 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5793 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5794 cfgerr++;
5795 }
5796 else {
5797 free((void *)mrule->table.name);
5798 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005799 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005800 }
5801 }
5802
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005803 /* find the target table for 'tcp-request' layer 4 rules */
5804 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5805 struct proxy *target;
5806
Willy Tarreau56123282010-08-06 19:06:56 +02005807 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005808 continue;
5809
5810 if (trule->act_prm.trk_ctr.table.n)
5811 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5812 else
5813 target = curproxy;
5814
5815 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005816 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5817 curproxy->id, trule->act_prm.trk_ctr.table.n,
5818 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005819 cfgerr++;
5820 }
5821 else if (target->table.size == 0) {
5822 Alert("Proxy '%s': table '%s' used but not configured.\n",
5823 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5824 cfgerr++;
5825 }
5826 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005827 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 +02005828 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5829 cfgerr++;
5830 }
5831 else {
5832 free(trule->act_prm.trk_ctr.table.n);
5833 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005834 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005835 * to pass a list of counters to track and allocate them right here using
5836 * stktable_alloc_data_type().
5837 */
5838 }
5839 }
5840
Willy Tarreaud1f96522010-08-03 19:34:32 +02005841 /* find the target table for 'tcp-request' layer 6 rules */
5842 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5843 struct proxy *target;
5844
Willy Tarreau56123282010-08-06 19:06:56 +02005845 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005846 continue;
5847
5848 if (trule->act_prm.trk_ctr.table.n)
5849 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5850 else
5851 target = curproxy;
5852
5853 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005854 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5855 curproxy->id, trule->act_prm.trk_ctr.table.n,
5856 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005857 cfgerr++;
5858 }
5859 else if (target->table.size == 0) {
5860 Alert("Proxy '%s': table '%s' used but not configured.\n",
5861 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5862 cfgerr++;
5863 }
5864 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005865 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 +02005866 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5867 cfgerr++;
5868 }
5869 else {
5870 free(trule->act_prm.trk_ctr.table.n);
5871 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005872 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005873 * to pass a list of counters to track and allocate them right here using
5874 * stktable_alloc_data_type().
5875 */
5876 }
5877 }
5878
Emeric Brun32da3c42010-09-23 18:39:19 +02005879 if (curproxy->table.peers.name) {
5880 struct peers *curpeers = peers;
5881
5882 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5883 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5884 free((void *)curproxy->table.peers.name);
5885 curproxy->table.peers.p = peers;
5886 break;
5887 }
5888 }
5889
5890 if (!curpeers) {
5891 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5892 curproxy->id, curproxy->table.peers.name);
5893 cfgerr++;
5894 }
5895 else if (!curpeers->peers_fe) {
5896 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5897 curproxy->id, curpeers->id);
5898 cfgerr++;
5899 }
5900 }
5901
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005902 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005903 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005904 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5905 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5906 "proxy", curproxy->id);
5907 cfgerr++;
5908 goto out_uri_auth_compat;
5909 }
5910
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005911 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005912 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005913 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005914 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005915
Willy Tarreau95fa4692010-02-01 13:05:50 +01005916 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5917 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005918
5919 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005920 uri_auth_compat_req[i++] = "realm";
5921 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5922 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005923
Willy Tarreau95fa4692010-02-01 13:05:50 +01005924 uri_auth_compat_req[i++] = "unless";
5925 uri_auth_compat_req[i++] = "{";
5926 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5927 uri_auth_compat_req[i++] = "}";
5928 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005929
Willy Tarreauff011f22011-01-06 17:51:27 +01005930 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5931 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005932 cfgerr++;
5933 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005934 }
5935
Willy Tarreauff011f22011-01-06 17:51:27 +01005936 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005937
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005938 if (curproxy->uri_auth->auth_realm) {
5939 free(curproxy->uri_auth->auth_realm);
5940 curproxy->uri_auth->auth_realm = NULL;
5941 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005942
5943 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005944 }
5945out_uri_auth_compat:
5946
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005947 cfgerr += acl_find_targets(curproxy);
5948
Willy Tarreau2738a142006-07-08 17:28:09 +02005949 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005950 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005951 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005952 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005953 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005954 " | While not properly invalid, you will certainly encounter various problems\n"
5955 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005956 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005957 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005958 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005959 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005960
Willy Tarreau1fa31262007-12-03 00:36:16 +01005961 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5962 * We must still support older configurations, so let's find out whether those
5963 * parameters have been set or must be copied from contimeouts.
5964 */
5965 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005966 if (!curproxy->timeout.tarpit ||
5967 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005968 /* tarpit timeout not set. We search in the following order:
5969 * default.tarpit, curr.connect, default.connect.
5970 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005971 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005972 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005973 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005974 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005975 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005976 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005977 }
5978 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005979 (!curproxy->timeout.queue ||
5980 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005981 /* queue timeout not set. We search in the following order:
5982 * default.queue, curr.connect, default.connect.
5983 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005984 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005985 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005986 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005987 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005988 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005989 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005990 }
5991 }
5992
Willy Tarreau07a54902010-03-29 18:33:29 +02005993 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005994 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5995 curproxy->check_req = (char *)malloc(curproxy->check_len);
5996 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005997 }
5998
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005999 /* The small pools required for the capture lists */
6000 if (curproxy->nb_req_cap)
6001 curproxy->req_cap_pool = create_pool("ptrcap",
6002 curproxy->nb_req_cap * sizeof(char *),
6003 MEM_F_SHARED);
6004 if (curproxy->nb_rsp_cap)
6005 curproxy->rsp_cap_pool = create_pool("ptrcap",
6006 curproxy->nb_rsp_cap * sizeof(char *),
6007 MEM_F_SHARED);
6008
Willy Tarreau1d4154a2007-05-13 22:57:02 +02006009 curproxy->hdr_idx_pool = create_pool("hdr_idx",
6010 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6011 MEM_F_SHARED);
6012
Willy Tarreaubaaee002006-06-26 02:48:02 +02006013 /* first, we will invert the servers list order */
6014 newsrv = NULL;
6015 while (curproxy->srv) {
6016 struct server *next;
6017
6018 next = curproxy->srv->next;
6019 curproxy->srv->next = newsrv;
6020 newsrv = curproxy->srv;
6021 if (!next)
6022 break;
6023 curproxy->srv = next;
6024 }
6025
Willy Tarreaudd701652010-05-25 23:03:02 +02006026 /* assign automatic UIDs to servers which don't have one yet */
6027 next_id = 1;
6028 newsrv = curproxy->srv;
6029 while (newsrv != NULL) {
6030 if (!newsrv->puid) {
6031 /* server ID not set, use automatic numbering with first
6032 * spare entry starting with next_svid.
6033 */
6034 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6035 newsrv->conf.id.key = newsrv->puid = next_id;
6036 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6037 }
6038 next_id++;
6039 newsrv = newsrv->next;
6040 }
6041
Willy Tarreau20697042007-11-15 23:26:18 +01006042 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006043 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006044
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006045 /* We have to initialize the server lookup mechanism depending
6046 * on what LB algorithm was choosen.
6047 */
6048
6049 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6050 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6051 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006052 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6053 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6054 init_server_map(curproxy);
6055 } else {
6056 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6057 fwrr_init_server_groups(curproxy);
6058 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006059 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006060
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006061 case BE_LB_KIND_LC:
6062 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006063 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006064 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006065
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006066 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006067 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6068 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6069 chash_init_server_tree(curproxy);
6070 } else {
6071 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6072 init_server_map(curproxy);
6073 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006074 break;
6075 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006076
6077 if (curproxy->options & PR_O_LOGASAP)
6078 curproxy->to_log &= ~LW_BYTES;
6079
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006080 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6081 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6082 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6083 proxy_type_str(curproxy), curproxy->id);
6084 err_code |= ERR_WARN;
6085 }
6086
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006087 if (curproxy->mode != PR_MODE_HTTP) {
6088 int optnum;
6089
6090 if (curproxy->options & PR_O_COOK_ANY) {
6091 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6092 proxy_type_str(curproxy), curproxy->id);
6093 err_code |= ERR_WARN;
6094 }
6095
6096 if (curproxy->uri_auth) {
6097 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6098 proxy_type_str(curproxy), curproxy->id);
6099 err_code |= ERR_WARN;
6100 curproxy->uri_auth = NULL;
6101 }
6102
6103 if (curproxy->options & PR_O_FWDFOR) {
6104 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6105 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6106 err_code |= ERR_WARN;
6107 curproxy->options &= ~PR_O_FWDFOR;
6108 }
6109
6110 if (curproxy->options & PR_O_ORGTO) {
6111 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6112 "originalto", proxy_type_str(curproxy), curproxy->id);
6113 err_code |= ERR_WARN;
6114 curproxy->options &= ~PR_O_ORGTO;
6115 }
6116
6117 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6118 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6119 (curproxy->cap & cfg_opts[optnum].cap) &&
6120 (curproxy->options & cfg_opts[optnum].val)) {
6121 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6122 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6123 err_code |= ERR_WARN;
6124 curproxy->options &= ~cfg_opts[optnum].val;
6125 }
6126 }
6127
6128 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6129 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6130 (curproxy->cap & cfg_opts2[optnum].cap) &&
6131 (curproxy->options2 & cfg_opts2[optnum].val)) {
6132 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6133 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6134 err_code |= ERR_WARN;
6135 curproxy->options2 &= ~cfg_opts2[optnum].val;
6136 }
6137 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006138
Willy Tarreauefa5f512010-03-30 20:13:29 +02006139#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006140 if (curproxy->bind_hdr_occ) {
6141 curproxy->bind_hdr_occ = 0;
6142 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6143 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6144 err_code |= ERR_WARN;
6145 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006146#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006147 }
6148
Willy Tarreaubaaee002006-06-26 02:48:02 +02006149 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006150 * ensure that we're not cross-dressing a TCP server into HTTP.
6151 */
6152 newsrv = curproxy->srv;
6153 while (newsrv != NULL) {
6154 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006155 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6156 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006157 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006158 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006159
Willy Tarreauefa5f512010-03-30 20:13:29 +02006160#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006161 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6162 newsrv->bind_hdr_occ = 0;
6163 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6164 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6165 err_code |= ERR_WARN;
6166 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006167#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006168 newsrv = newsrv->next;
6169 }
6170
6171 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006172 * If this server supports a maxconn parameter, it needs a dedicated
6173 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006174 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006175 */
6176 newsrv = curproxy->srv;
6177 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006178 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006179 /* Only 'minconn' was specified, or it was higher than or equal
6180 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6181 * this will avoid further useless expensive computations.
6182 */
6183 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006184 } else if (newsrv->maxconn && !newsrv->minconn) {
6185 /* minconn was not specified, so we set it to maxconn */
6186 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006187 }
6188
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006189 if (newsrv->trackit) {
6190 struct proxy *px;
6191 struct server *srv;
6192 char *pname, *sname;
6193
6194 pname = newsrv->trackit;
6195 sname = strrchr(pname, '/');
6196
6197 if (sname)
6198 *sname++ = '\0';
6199 else {
6200 sname = pname;
6201 pname = NULL;
6202 }
6203
6204 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006205 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006206 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006207 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6208 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006209 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006210 cfgerr++;
6211 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006212 }
6213 } else
6214 px = curproxy;
6215
6216 srv = findserver(px, sname);
6217 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006218 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6219 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006220 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006221 cfgerr++;
6222 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006223 }
6224
6225 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006226 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006227 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006228 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006229 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006230 cfgerr++;
6231 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006232 }
6233
6234 if (curproxy != px &&
6235 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006236 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006237 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006238 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006239 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006240 cfgerr++;
6241 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006242 }
6243
6244 newsrv->tracked = srv;
6245 newsrv->tracknext = srv->tracknext;
6246 srv->tracknext = newsrv;
6247
6248 free(newsrv->trackit);
6249 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006250 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006251 newsrv = newsrv->next;
6252 }
6253
Willy Tarreauc1a21672009-08-16 22:37:44 +02006254 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006255 curproxy->accept = frontend_accept;
6256
Willy Tarreauc1a21672009-08-16 22:37:44 +02006257 if (curproxy->tcp_req.inspect_delay ||
6258 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006259 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006260
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006261 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006262 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006263 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006264 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006265
6266 /* both TCP and HTTP must check switching rules */
6267 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6268 }
6269
6270 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006271 if (curproxy->tcp_req.inspect_delay ||
6272 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6273 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6274
Emeric Brun97679e72010-09-23 17:56:44 +02006275 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6276 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6277
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006278 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006279 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006280 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006281 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006282
6283 /* If the backend does requires RDP cookie persistence, we have to
6284 * enable the corresponding analyser.
6285 */
6286 if (curproxy->options2 & PR_O2_RDPC_PRST)
6287 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6288 }
6289
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006290 listener = NULL;
6291 while (curproxy->listen) {
6292 struct listener *next;
6293
6294 next = curproxy->listen->next;
6295 curproxy->listen->next = listener;
6296 listener = curproxy->listen;
6297
6298 if (!next)
6299 break;
6300
6301 curproxy->listen = next;
6302 }
6303
Willy Tarreaue6b98942007-10-29 01:09:36 +01006304 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006305 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006306 listener = curproxy->listen;
6307 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006308 if (!listener->luid) {
6309 /* listener ID not set, use automatic numbering with first
6310 * spare entry starting with next_luid.
6311 */
6312 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6313 listener->conf.id.key = listener->luid = next_id;
6314 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006315 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006316 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006317
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006318 /* enable separate counters */
6319 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6320 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6321 if (!listener->name) {
6322 sprintf(trash, "sock-%d", listener->luid);
6323 listener->name = strdup(trash);
6324 }
6325 }
6326
Willy Tarreaue6b98942007-10-29 01:09:36 +01006327 if (curproxy->options & PR_O_TCP_NOLING)
6328 listener->options |= LI_O_NOLINGER;
6329 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006330 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006331 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006332 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006333 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006334 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006335 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006336
Willy Tarreau8a956912010-10-15 14:27:08 +02006337 if (listener->options & LI_O_ACC_PROXY)
6338 listener->analysers |= AN_REQ_DECODE_PROXY;
6339
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006340 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6341 listener->options |= LI_O_TCP_RULES;
6342
Willy Tarreaude3041d2010-05-31 10:56:17 +02006343 if (curproxy->mon_mask.s_addr)
6344 listener->options |= LI_O_CHK_MONNET;
6345
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006346 /* smart accept mode is automatic in HTTP mode */
6347 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6348 (curproxy->mode == PR_MODE_HTTP &&
6349 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6350 listener->options |= LI_O_NOQUICKACK;
6351
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006352 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006353 listener = listener->next;
6354 }
6355
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006356 /* Check multi-process mode compatibility for the current proxy */
6357 if (global.nbproc > 1) {
6358 int nbproc = 0;
6359 if (curproxy->bind_proc) {
6360 int proc;
6361 for (proc = 0; proc < global.nbproc; proc++) {
6362 if (curproxy->bind_proc & (1 << proc)) {
6363 nbproc++;
6364 }
6365 }
6366 } else {
6367 nbproc = global.nbproc;
6368 }
6369 if (curproxy->table.peers.name) {
6370 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6371 curproxy->id);
6372 cfgerr++;
6373 }
6374 if (nbproc > 1) {
6375 if (curproxy->uri_auth) {
6376 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6377 curproxy->id);
6378 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6379 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6380 curproxy->id);
6381 }
6382 }
6383 if (curproxy->appsession_name) {
6384 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6385 curproxy->id);
6386 }
6387 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6388 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6389 curproxy->id);
6390 }
6391 }
6392 }
6393
Willy Tarreaubaaee002006-06-26 02:48:02 +02006394 curproxy = curproxy->next;
6395 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006396
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006397 /* Check multi-process mode compatibility */
6398 if (global.nbproc > 1) {
6399 if (global.stats_fe) {
6400 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6401 }
6402 }
6403
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006404 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6405 struct auth_users *curuser;
6406 int g;
6407
6408 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6409 unsigned int group_mask = 0;
6410 char *group = NULL;
6411
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006412 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006413 continue;
6414
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006415 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006416
6417 for (g = 0; g < curuserlist->grpcnt; g++)
6418 if (!strcmp(curuserlist->groups[g], group))
6419 break;
6420
6421 if (g == curuserlist->grpcnt) {
6422 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6423 curuserlist->name, group, curuser->user);
6424 err_code |= ERR_ALERT | ERR_FATAL;
6425 goto out;
6426 }
6427
6428 group_mask |= (1 << g);
6429 }
6430
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006431 free(curuser->u.groups);
6432 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006433 }
6434
6435 for (g = 0; g < curuserlist->grpcnt; g++) {
6436 char *user = NULL;
6437
6438 if (!curuserlist->groupusers[g])
6439 continue;
6440
6441 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6442 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6443 if (!strcmp(curuser->user, user))
6444 break;
6445
6446 if (!curuser) {
6447 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6448 curuserlist->name, user, curuserlist->groups[g]);
6449 err_code |= ERR_ALERT | ERR_FATAL;
6450 goto out;
6451 }
6452
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006453 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006454 }
6455
6456 free(curuserlist->groupusers[g]);
6457 }
6458
6459 free(curuserlist->groupusers);
6460
6461#ifdef DEBUG_AUTH
6462 for (g = 0; g < curuserlist->grpcnt; g++) {
6463 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6464
6465 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6466 if (curuser->group_mask & (1 << g))
6467 fprintf(stderr, " %s", curuser->user);
6468 }
6469
6470 fprintf(stderr, "\n");
6471 }
6472#endif
6473
Willy Tarreaufbb78422011-06-05 15:38:35 +02006474 }
6475
6476 /* automatically compute fullconn if not set. We must not do it in the
6477 * loop above because cross-references are not yet fully resolved.
6478 */
6479 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6480 /* If <fullconn> is not set, let's set it to 10% of the sum of
6481 * the possible incoming frontend's maxconns.
6482 */
6483 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6484 struct proxy *fe;
6485 int total = 0;
6486
6487 /* sum up the number of maxconns of frontends which
6488 * reference this backend at least once or which are
6489 * the same one ('listen').
6490 */
6491 for (fe = proxy; fe; fe = fe->next) {
6492 struct switching_rule *rule;
6493 struct hdr_exp *exp;
6494 int found = 0;
6495
6496 if (!(fe->cap & PR_CAP_FE))
6497 continue;
6498
6499 if (fe == curproxy) /* we're on a "listen" instance */
6500 found = 1;
6501
6502 if (fe->defbe.be == curproxy) /* "default_backend" */
6503 found = 1;
6504
6505 /* check if a "use_backend" rule matches */
6506 if (!found) {
6507 list_for_each_entry(rule, &fe->switching_rules, list) {
6508 if (rule->be.backend == curproxy) {
6509 found = 1;
6510 break;
6511 }
6512 }
6513 }
6514
6515 /* check if a "reqsetbe" rule matches */
6516 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6517 if (exp->action == ACT_SETBE &&
6518 (struct proxy *)exp->replace == curproxy) {
6519 found = 1;
6520 break;
6521 }
6522 }
6523
6524 /* now we've checked all possible ways to reference a backend
6525 * from a frontend.
6526 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006527 if (!found)
6528 continue;
6529 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006530 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006531 /* we have the sum of the maxconns in <total>. We only
6532 * keep 10% of that sum to set the default fullconn, with
6533 * a hard minimum of 1 (to avoid a divide by zero).
6534 */
6535 curproxy->fullconn = (total + 9) / 10;
6536 if (!curproxy->fullconn)
6537 curproxy->fullconn = 1;
6538 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006539 }
6540
Willy Tarreau056f5682010-06-06 15:51:11 +02006541 /* initialize stick-tables on backend capable proxies. This must not
6542 * be done earlier because the data size may be discovered while parsing
6543 * other proxies.
6544 */
6545 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006546 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006547
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006548 /*
6549 * Recount currently required checks.
6550 */
6551
6552 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6553 int optnum;
6554
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006555 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6556 if (curproxy->options & cfg_opts[optnum].val)
6557 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006558
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006559 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6560 if (curproxy->options2 & cfg_opts2[optnum].val)
6561 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006562 }
6563
Willy Tarreaubb925012009-07-23 13:36:36 +02006564 if (cfgerr > 0)
6565 err_code |= ERR_ALERT | ERR_FATAL;
6566 out:
6567 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006568}
6569
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006570/*
6571 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6572 * parsing sessions.
6573 */
6574void cfg_register_keywords(struct cfg_kw_list *kwl)
6575{
6576 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6577}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006578
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006579/*
6580 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6581 */
6582void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6583{
6584 LIST_DEL(&kwl->list);
6585 LIST_INIT(&kwl->list);
6586}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006587
6588/*
6589 * Local variables:
6590 * c-indent-level: 8
6591 * c-basic-offset: 8
6592 * End:
6593 */