blob: 14171ce9fd43f42e1c2b3d2fd0906e65d0195357 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 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>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010040#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020045#include <proto/frontend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010046#include <proto/httperr.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>
56#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010057#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010059#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010061#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062
63
Willy Tarreauf3c69202006-07-09 16:42:34 +020064/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
65 * ssl-hello-chk option to ensure that the remote server speaks SSL.
66 *
67 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
68 */
69const char sslv3_client_hello_pkt[] = {
70 "\x16" /* ContentType : 0x16 = Hanshake */
71 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
72 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
73 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
74 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
75 "\x03\x00" /* Hello Version : 0x0300 = v3 */
76 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
77 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
78 "\x00" /* Session ID length : empty (no session ID) */
79 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
80 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
81 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
82 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
83 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
84 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
85 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
86 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
87 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
88 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
89 "\x00\x38" "\x00\x39" "\x00\x3A"
90 "\x01" /* Compression Length : 0x01 = 1 byte for types */
91 "\x00" /* Compression Type : 0x00 = NULL compression */
92};
93
Willy Tarreau3842f002009-06-14 11:39:52 +020094/* various keyword modifiers */
95enum kw_mod {
96 KWM_STD = 0, /* normal */
97 KWM_NO, /* "no" prefixed before the keyword */
98 KWM_DEF, /* "default" prefixed before the keyword */
99};
100
Willy Tarreau13943ab2006-12-31 00:24:10 +0100101/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100102struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100103 const char *name;
104 unsigned int val;
105 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100106 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100107 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100108};
109
110/* proxy->options */
111static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100112{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100113 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
114 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
115 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
116 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
117 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
118 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
119 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
120 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
121 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
122 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
123 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
125 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
126 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
127 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
128 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100129#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100130 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100131#endif
132
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100133 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100134};
135
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100136/* proxy->options2 */
137static const struct cfg_opt cfg_opts2[] =
138{
139#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
141 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
142 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100143#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
145 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
146 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
147 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
148 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
149 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
150 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
151 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
152 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200154 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100155 { NULL, 0, 0, 0 }
156};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200157
Willy Tarreau6daf3432008-01-22 16:44:08 +0100158static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200159static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
160int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100161int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200162
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200163/* List head of all known configuration keywords */
164static struct cfg_kw_list cfg_keywords = {
165 .list = LIST_HEAD_INIT(cfg_keywords.list)
166};
167
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168/*
169 * converts <str> to a list of listeners which are dynamically allocated.
170 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
171 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
172 * - <port> is a numerical port from 1 to 65535 ;
173 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
174 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200175 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200176 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200177static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178{
179 struct listener *l;
180 char *c, *next, *range, *dupstr;
181 int port, end;
182
183 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200184
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 while (next && *next) {
186 struct sockaddr_storage ss;
187
188 str = next;
189 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100190 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191 *next++ = 0;
192 }
193
194 /* 2) look for the addr/port delimiter, it's the last colon. */
195 if ((range = strrchr(str, ':')) == NULL) {
196 Alert("Missing port number: '%s'\n", str);
197 goto fail;
198 }
199
200 *range++ = 0;
201
202 if (strrchr(str, ':') != NULL) {
203 /* IPv6 address contains ':' */
204 memset(&ss, 0, sizeof(ss));
205 ss.ss_family = AF_INET6;
206
207 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
208 Alert("Invalid server address: '%s'\n", str);
209 goto fail;
210 }
211 }
212 else {
213 memset(&ss, 0, sizeof(ss));
214 ss.ss_family = AF_INET;
215
216 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
217 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
218 }
219 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
220 struct hostent *he;
221
222 if ((he = gethostbyname(str)) == NULL) {
223 Alert("Invalid server name: '%s'\n", str);
224 goto fail;
225 }
226 else
227 ((struct sockaddr_in *)&ss)->sin_addr =
228 *(struct in_addr *) *(he->h_addr_list);
229 }
230 }
231
232 /* 3) look for the port-end delimiter */
233 if ((c = strchr(range, '-')) != NULL) {
234 *c++ = 0;
235 end = atol(c);
236 }
237 else {
238 end = atol(range);
239 }
240
241 port = atol(range);
242
243 if (port < 1 || port > 65535) {
244 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
245 goto fail;
246 }
247
248 if (end < 1 || end > 65535) {
249 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
250 goto fail;
251 }
252
253 for (; port <= end; port++) {
254 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200255 l->next = curproxy->listen;
256 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200257
258 l->fd = -1;
259 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100260 l->state = LI_INIT;
261
262 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100264 tcpv6_add_listener(l);
265 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100267 tcpv4_add_listener(l);
268 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200269
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200270 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100271 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 } /* end for(port) */
273 } /* end while(next) */
274 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200275 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200276 fail:
277 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200278 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200279}
280
Willy Tarreau977b8e42006-12-29 14:19:17 +0100281/*
282 * Sends a warning if proxy <proxy> does not have at least one of the
283 * capabilities in <cap>. An optionnal <hint> may be added at the end
284 * of the warning to help the user. Returns 1 if a warning was emitted
285 * or 0 if the condition is valid.
286 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100287int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100288{
289 char *msg;
290
291 switch (cap) {
292 case PR_CAP_BE: msg = "no backend"; break;
293 case PR_CAP_FE: msg = "no frontend"; break;
294 case PR_CAP_RS: msg = "no ruleset"; break;
295 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
296 default: msg = "not enough"; break;
297 }
298
299 if (!(proxy->cap & cap)) {
300 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100301 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302 return 1;
303 }
304 return 0;
305}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200306
Willy Tarreau61d18892009-03-31 10:49:21 +0200307/* Report a warning if a rule is placed after a 'block' rule.
308 * Return 1 if the warning has been emitted, otherwise 0.
309 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100310int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200311{
312 if (!LIST_ISEMPTY(&proxy->block_cond)) {
313 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
314 file, line, arg);
315 return 1;
316 }
317 return 0;
318}
319
320/* Report a warning if a rule is placed after a reqrewrite rule.
321 * Return 1 if the warning has been emitted, otherwise 0.
322 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100323int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200324{
325 if (proxy->req_exp) {
326 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
327 file, line, arg);
328 return 1;
329 }
330 return 0;
331}
332
333/* Report a warning if a rule is placed after a reqadd rule.
334 * Return 1 if the warning has been emitted, otherwise 0.
335 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100336int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200337{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100338 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200339 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
340 file, line, arg);
341 return 1;
342 }
343 return 0;
344}
345
346/* Report a warning if a rule is placed after a redirect rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100349int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200350{
351 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
352 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
359/* Report a warning if a rule is placed after a 'use_backend' rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
364 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
372/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100373int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200374{
375 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
376 warnif_rule_after_reqadd(proxy, file, line, arg) ||
377 warnif_rule_after_redirect(proxy, file, line, arg) ||
378 warnif_rule_after_use_backend(proxy, file, line, arg);
379}
380
381/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100382int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200383{
384 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
385 warnif_rule_after_redirect(proxy, file, line, arg) ||
386 warnif_rule_after_use_backend(proxy, file, line, arg);
387}
388
389/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100390int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200391{
392 return warnif_rule_after_redirect(proxy, file, line, arg) ||
393 warnif_rule_after_use_backend(proxy, file, line, arg);
394}
395
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100396/* Report it if a request ACL condition uses some response-only parameters. It
397 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
398 * Note that <cond> may be NULL and then will be ignored.
399 */
400static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
401{
402 struct acl *acl;
403
404 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
405 return 0;
406
407 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
408 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
409 file, line, acl ? acl->name : "(unknown)");
410 return ERR_WARN;
411}
412
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100413/* Report it if a request ACL condition uses some request-only volatile parameters.
414 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
415 * Note that <cond> may be NULL and then will be ignored.
416 */
417static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
418{
419 struct acl *acl;
420
421 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
422 return 0;
423
424 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
425 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
426 file, line, acl ? acl->name : "(unknown)");
427 return ERR_WARN;
428}
429
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100430
Willy Tarreaubaaee002006-06-26 02:48:02 +0200431/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200432 * parse a line in a <global> section. Returns the error code, 0 if OK, or
433 * any combination of :
434 * - ERR_ABORT: must abort ASAP
435 * - ERR_FATAL: we can continue parsing but not start the service
436 * - ERR_WARN: a warning has been emitted
437 * - ERR_ALERT: an alert has been emitted
438 * Only the two first ones can stop processing, the two others are just
439 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200440 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200441int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200442{
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200444
445 if (!strcmp(args[0], "global")) { /* new section */
446 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200448 }
449 else if (!strcmp(args[0], "daemon")) {
450 global.mode |= MODE_DAEMON;
451 }
452 else if (!strcmp(args[0], "debug")) {
453 global.mode |= MODE_DEBUG;
454 }
455 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100456 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200457 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200458 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100459 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200460 }
461 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100462 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200463 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200464 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100465 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100467 else if (!strcmp(args[0], "nosplice")) {
468 global.tune.options &= ~GTUNE_USE_SPLICE;
469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 else if (!strcmp(args[0], "quiet")) {
471 global.mode |= MODE_QUIET;
472 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200473 else if (!strcmp(args[0], "tune.maxpollevents")) {
474 if (global.tune.maxpollevents != 0) {
475 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200476 err_code |= ERR_ALERT;
477 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200478 }
479 if (*(args[1]) == 0) {
480 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200481 err_code |= ERR_ALERT | ERR_FATAL;
482 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200483 }
484 global.tune.maxpollevents = atol(args[1]);
485 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100486 else if (!strcmp(args[0], "tune.maxaccept")) {
487 if (global.tune.maxaccept != 0) {
488 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200489 err_code |= ERR_ALERT;
490 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100491 }
492 if (*(args[1]) == 0) {
493 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200494 err_code |= ERR_ALERT | ERR_FATAL;
495 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100496 }
497 global.tune.maxaccept = atol(args[1]);
498 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200499 else if (!strcmp(args[0], "tune.bufsize")) {
500 if (*(args[1]) == 0) {
501 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
502 err_code |= ERR_ALERT | ERR_FATAL;
503 goto out;
504 }
505 global.tune.bufsize = atol(args[1]);
506 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
507 global.tune.maxrewrite = global.tune.bufsize / 2;
508 }
509 else if (!strcmp(args[0], "tune.maxrewrite")) {
510 if (*(args[1]) == 0) {
511 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
512 err_code |= ERR_ALERT | ERR_FATAL;
513 goto out;
514 }
515 global.tune.maxrewrite = atol(args[1]);
516 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
517 global.tune.maxrewrite = global.tune.bufsize / 2;
518 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100519 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
520 if (global.tune.client_rcvbuf != 0) {
521 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
522 err_code |= ERR_ALERT;
523 goto out;
524 }
525 if (*(args[1]) == 0) {
526 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
527 err_code |= ERR_ALERT | ERR_FATAL;
528 goto out;
529 }
530 global.tune.client_rcvbuf = atol(args[1]);
531 }
532 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
533 if (global.tune.server_rcvbuf != 0) {
534 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
535 err_code |= ERR_ALERT;
536 goto out;
537 }
538 if (*(args[1]) == 0) {
539 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
540 err_code |= ERR_ALERT | ERR_FATAL;
541 goto out;
542 }
543 global.tune.server_rcvbuf = atol(args[1]);
544 }
545 else if (!strcmp(args[0], "tune.sndbuf.client")) {
546 if (global.tune.client_sndbuf != 0) {
547 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
548 err_code |= ERR_ALERT;
549 goto out;
550 }
551 if (*(args[1]) == 0) {
552 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT | ERR_FATAL;
554 goto out;
555 }
556 global.tune.client_sndbuf = atol(args[1]);
557 }
558 else if (!strcmp(args[0], "tune.sndbuf.server")) {
559 if (global.tune.server_sndbuf != 0) {
560 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT;
562 goto out;
563 }
564 if (*(args[1]) == 0) {
565 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
566 err_code |= ERR_ALERT | ERR_FATAL;
567 goto out;
568 }
569 global.tune.server_sndbuf = atol(args[1]);
570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200571 else if (!strcmp(args[0], "uid")) {
572 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200573 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200574 err_code |= ERR_ALERT;
575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200576 }
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581 }
582 global.uid = atol(args[1]);
583 }
584 else if (!strcmp(args[0], "gid")) {
585 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200586 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200587 err_code |= ERR_ALERT;
588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 }
590 if (*(args[1]) == 0) {
591 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200592 err_code |= ERR_ALERT | ERR_FATAL;
593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200594 }
595 global.gid = atol(args[1]);
596 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200597 /* user/group name handling */
598 else if (!strcmp(args[0], "user")) {
599 struct passwd *ha_user;
600 if (global.uid != 0) {
601 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200602 err_code |= ERR_ALERT;
603 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200604 }
605 errno = 0;
606 ha_user = getpwnam(args[1]);
607 if (ha_user != NULL) {
608 global.uid = (int)ha_user->pw_uid;
609 }
610 else {
611 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 +0200612 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200613 }
614 }
615 else if (!strcmp(args[0], "group")) {
616 struct group *ha_group;
617 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200618 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200619 err_code |= ERR_ALERT;
620 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200621 }
622 errno = 0;
623 ha_group = getgrnam(args[1]);
624 if (ha_group != NULL) {
625 global.gid = (int)ha_group->gr_gid;
626 }
627 else {
628 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 +0200629 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200630 }
631 }
632 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633 else if (!strcmp(args[0], "nbproc")) {
634 if (global.nbproc != 0) {
635 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200636 err_code |= ERR_ALERT;
637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200638 }
639 if (*(args[1]) == 0) {
640 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200641 err_code |= ERR_ALERT | ERR_FATAL;
642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200643 }
644 global.nbproc = atol(args[1]);
645 }
646 else if (!strcmp(args[0], "maxconn")) {
647 if (global.maxconn != 0) {
648 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200649 err_code |= ERR_ALERT;
650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200651 }
652 if (*(args[1]) == 0) {
653 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200654 err_code |= ERR_ALERT | ERR_FATAL;
655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 }
657 global.maxconn = atol(args[1]);
658#ifdef SYSTEM_MAXCONN
659 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
660 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);
661 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200662 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200663 }
664#endif /* SYSTEM_MAXCONN */
665 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100666 else if (!strcmp(args[0], "maxpipes")) {
667 if (global.maxpipes != 0) {
668 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200669 err_code |= ERR_ALERT;
670 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100671 }
672 if (*(args[1]) == 0) {
673 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200674 err_code |= ERR_ALERT | ERR_FATAL;
675 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100676 }
677 global.maxpipes = atol(args[1]);
678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200679 else if (!strcmp(args[0], "ulimit-n")) {
680 if (global.rlimit_nofile != 0) {
681 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT;
683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200684 }
685 if (*(args[1]) == 0) {
686 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200689 }
690 global.rlimit_nofile = atol(args[1]);
691 }
692 else if (!strcmp(args[0], "chroot")) {
693 if (global.chroot != NULL) {
694 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200695 err_code |= ERR_ALERT;
696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200697 }
698 if (*(args[1]) == 0) {
699 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200700 err_code |= ERR_ALERT | ERR_FATAL;
701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200702 }
703 global.chroot = strdup(args[1]);
704 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200705 else if (!strcmp(args[0], "description")) {
706 int i, len=0;
707 char *d;
708
709 if (!*args[1]) {
710 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
711 file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715
716 for(i=1; *args[i]; i++)
717 len += strlen(args[i])+1;
718
719 if (global.desc)
720 free(global.desc);
721
722 global.desc = d = (char *)calloc(1, len);
723
724 d += sprintf(d, "%s", args[1]);
725 for(i=2; *args[i]; i++)
726 d += sprintf(d, " %s", args[i]);
727 }
728 else if (!strcmp(args[0], "node")) {
729 int i;
730 char c;
731
732 for (i=0; args[1][i]; i++) {
733 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100734 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
735 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200736 break;
737 }
738
739 if (!i || args[1][i]) {
740 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
741 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
742 file, linenum, args[0]);
743 err_code |= ERR_ALERT | ERR_FATAL;
744 goto out;
745 }
746
747 if (global.node)
748 free(global.node);
749
750 global.node = strdup(args[1]);
751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 else if (!strcmp(args[0], "pidfile")) {
753 if (global.pidfile != NULL) {
754 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT;
756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 }
758 if (*(args[1]) == 0) {
759 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200762 }
763 global.pidfile = strdup(args[1]);
764 }
765 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100766 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200767 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200768
769 if (*(args[1]) == 0 || *(args[2]) == 0) {
770 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200771 err_code |= ERR_ALERT | ERR_FATAL;
772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200773 }
774
775 facility = get_log_facility(args[2]);
776 if (facility < 0) {
777 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200778 err_code |= ERR_ALERT | ERR_FATAL;
779 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780 }
781
782 level = 7; /* max syslog level = debug */
783 if (*(args[3])) {
784 level = get_log_level(args[3]);
785 if (level < 0) {
786 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200787 err_code |= ERR_ALERT | ERR_FATAL;
788 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789 }
790 }
791
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200792 minlvl = 0; /* limit syslog level to this level (emerg) */
793 if (*(args[4])) {
794 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200795 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200796 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200797 err_code |= ERR_ALERT | ERR_FATAL;
798 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200799 }
800 }
801
Robert Tsai81ae1952007-12-05 10:47:29 +0100802 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100803 struct sockaddr_un *sk = str2sun(args[1]);
804 if (!sk) {
805 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
806 args[1], (int)sizeof(sk->sun_path) - 1);
807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
809 }
810 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100811 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100812 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100813 struct sockaddr_in *sk = str2sa(args[1]);
814 if (!sk) {
815 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
816 err_code |= ERR_ALERT | ERR_FATAL;
817 goto out;
818 }
819 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100820 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100821 if (!logsrv.u.in.sin_port)
822 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
823 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200824
825 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100826 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 global.logfac1 = facility;
828 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200829 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200830 }
831 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100832 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 global.logfac2 = facility;
834 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200835 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200836 }
837 else {
838 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200839 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200840 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200841 }
842 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
843 if (global.spread_checks != 0) {
844 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200845 err_code |= ERR_ALERT;
846 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200847 }
848 if (*(args[1]) == 0) {
849 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200850 err_code |= ERR_ALERT | ERR_FATAL;
851 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200852 }
853 global.spread_checks = atol(args[1]);
854 if (global.spread_checks < 0 || global.spread_checks > 50) {
855 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200856 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200857 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200858 }
859 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200860 struct cfg_kw_list *kwl;
861 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200862 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200863
864 list_for_each_entry(kwl, &cfg_keywords.list, list) {
865 for (index = 0; kwl->kw[index].kw != NULL; index++) {
866 if (kwl->kw[index].section != CFG_GLOBAL)
867 continue;
868 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
869 /* prepare error message just in case */
870 snprintf(trash, sizeof(trash),
871 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200872 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
873 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200874 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200875 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200876 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200877 else if (rc > 0) {
878 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200879 err_code |= ERR_WARN;
880 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200881 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200882 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200883 }
884 }
885 }
886
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200888 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200889 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200890
Willy Tarreau058e9072009-07-20 09:30:05 +0200891 out:
892 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200893}
894
Willy Tarreau97cb7802010-01-03 20:23:58 +0100895/* Perform the most basic initialization of a proxy :
896 * memset(), list_init(*), reset_timeouts(*).
897 */
898static void init_new_proxy(struct proxy *p)
899{
900 memset(p, 0, sizeof(struct proxy));
901 LIST_INIT(&p->pendconns);
902 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +0100903 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100904 LIST_INIT(&p->block_cond);
905 LIST_INIT(&p->redirect_rules);
906 LIST_INIT(&p->mon_fail_cond);
907 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +0200908 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100909 LIST_INIT(&p->sticking_rules);
910 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100911 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +0200912 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100913 LIST_INIT(&p->req_add);
914 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100915
916 /* Timeouts are defined as -1 */
917 proxy_reset_timeouts(p);
918}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200920void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100922 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 defproxy.mode = PR_MODE_TCP;
924 defproxy.state = PR_STNEW;
925 defproxy.maxconn = cfg_maxpconn;
926 defproxy.conn_retries = CONN_RETRIES;
927 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100928
929 defproxy.defsrv.inter = DEF_CHKINTR;
930 defproxy.defsrv.fastinter = 0;
931 defproxy.defsrv.downinter = 0;
932 defproxy.defsrv.rise = DEF_RISETIME;
933 defproxy.defsrv.fall = DEF_FALLTIME;
934 defproxy.defsrv.check_port = 0;
935 defproxy.defsrv.maxqueue = 0;
936 defproxy.defsrv.minconn = 0;
937 defproxy.defsrv.maxconn = 0;
938 defproxy.defsrv.slowstart = 0;
939 defproxy.defsrv.onerror = DEF_HANA_ONERR;
940 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
941 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942}
943
Willy Tarreauade5ec42010-01-28 19:33:49 +0100944
945static int create_cond_regex_rule(const char *file, int line,
946 struct proxy *px, int dir, int action, int flags,
947 const char *cmd, const char *reg, const char *repl,
948 const char **cond_start)
949{
950 regex_t *preg = NULL;
951 const char *err;
952 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +0100953 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +0100954
955 if (px == &defproxy) {
956 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
957 err_code |= ERR_ALERT | ERR_FATAL;
958 goto err;
959 }
960
961 if (*reg == 0) {
962 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
963 err_code |= ERR_ALERT | ERR_FATAL;
964 goto err;
965 }
966
967 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
968 err_code |= ERR_WARN;
969
Willy Tarreau5321c422010-01-28 20:35:13 +0100970 if (cond_start &&
971 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
972 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
973 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
974 file, line, cmd);
975 err_code |= ERR_ALERT | ERR_FATAL;
976 goto err;
977 }
978 }
979 else if (cond_start && **cond_start) {
980 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
981 file, line, cmd, *cond_start);
982 err_code |= ERR_ALERT | ERR_FATAL;
983 goto err;
984 }
985
986 if (dir == ACL_DIR_REQ)
987 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100988 else
989 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +0100990
Willy Tarreauade5ec42010-01-28 19:33:49 +0100991 preg = calloc(1, sizeof(regex_t));
992 if (!preg) {
993 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
994 err_code = ERR_ALERT | ERR_FATAL;
995 goto err;
996 }
997
998 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
999 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1000 err_code = ERR_ALERT | ERR_FATAL;
1001 goto err;
1002 }
1003
1004 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001005 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001006 if (repl && err) {
1007 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1008 file, line, cmd, *err);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto err;
1011 }
1012
1013 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1014 err_code |= ERR_WARN;
1015
1016 return err_code;
1017 err:
1018 free(preg);
1019 return err_code;
1020}
1021
Willy Tarreaubaaee002006-06-26 02:48:02 +02001022/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001023 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001024 * Returns the error code, 0 if OK, or any combination of :
1025 * - ERR_ABORT: must abort ASAP
1026 * - ERR_FATAL: we can continue parsing but not start the service
1027 * - ERR_WARN: a warning has been emitted
1028 * - ERR_ALERT: an alert has been emitted
1029 * Only the two first ones can stop processing, the two others are just
1030 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001031 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001032int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001033{
1034 static struct proxy *curproxy = NULL;
1035 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001036 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001037 int rc;
1038 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001039 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001040 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001041
Willy Tarreau977b8e42006-12-29 14:19:17 +01001042 if (!strcmp(args[0], "listen"))
1043 rc = PR_CAP_LISTEN;
1044 else if (!strcmp(args[0], "frontend"))
1045 rc = PR_CAP_FE | PR_CAP_RS;
1046 else if (!strcmp(args[0], "backend"))
1047 rc = PR_CAP_BE | PR_CAP_RS;
1048 else if (!strcmp(args[0], "ruleset"))
1049 rc = PR_CAP_RS;
1050 else
1051 rc = PR_CAP_NONE;
1052
1053 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 if (!*args[1]) {
1055 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1056 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1057 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001058 err_code |= ERR_ALERT | ERR_ABORT;
1059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001061
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001062 err = invalid_char(args[1]);
1063 if (err) {
1064 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1065 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001066 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001067 }
1068
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001069 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1070 /*
1071 * If there are two proxies with the same name only following
1072 * combinations are allowed:
1073 *
1074 * listen backend frontend ruleset
1075 * listen - - - -
1076 * backend - - OK -
1077 * frontend - OK - -
1078 * ruleset - - - -
1079 */
1080
1081 if (!strcmp(curproxy->id, args[1]) &&
1082 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1083 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001084 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1085 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1086 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001087 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001088 }
1089 }
1090
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1092 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001093 err_code |= ERR_ALERT | ERR_ABORT;
1094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001095 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001096
Willy Tarreau97cb7802010-01-03 20:23:58 +01001097 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 curproxy->next = proxy;
1099 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001100 curproxy->conf.file = file;
1101 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001102 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001104 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001105
1106 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001107 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001108 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001109 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001110 err_code |= ERR_FATAL;
1111 goto out;
1112 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001113 new = curproxy->listen;
1114 while (new != last) {
1115 new->conf.file = file;
1116 new->conf.line = linenum;
1117 new = new->next;
1118 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 global.maxsock++;
1120 }
1121
1122 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001123 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001124 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001125
Willy Tarreaubaaee002006-06-26 02:48:02 +02001126 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001128 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001129 curproxy->no_options = defproxy.no_options;
1130 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001131 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001132 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001133 curproxy->except_net = defproxy.except_net;
1134 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001135 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001136 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001137
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001138 if (defproxy.fwdfor_hdr_len) {
1139 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1140 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1141 }
1142
Willy Tarreaub86db342009-11-30 11:50:16 +01001143 if (defproxy.orgto_hdr_len) {
1144 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1145 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1146 }
1147
Willy Tarreau977b8e42006-12-29 14:19:17 +01001148 if (curproxy->cap & PR_CAP_FE) {
1149 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001150 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001151 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001152
1153 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001154 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1155 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001156
1157 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1158 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159
Willy Tarreau977b8e42006-12-29 14:19:17 +01001160 if (curproxy->cap & PR_CAP_BE) {
1161 curproxy->fullconn = defproxy.fullconn;
1162 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163
Willy Tarreau977b8e42006-12-29 14:19:17 +01001164 if (defproxy.check_req)
1165 curproxy->check_req = strdup(defproxy.check_req);
1166 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167
Willy Tarreau977b8e42006-12-29 14:19:17 +01001168 if (defproxy.cookie_name)
1169 curproxy->cookie_name = strdup(defproxy.cookie_name);
1170 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001171 if (defproxy.cookie_domain)
1172 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001173
Emeric Brun647caf12009-06-30 17:57:00 +02001174 if (defproxy.rdp_cookie_name)
1175 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1176 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1177
Willy Tarreau01732802007-11-01 22:48:15 +01001178 if (defproxy.url_param_name)
1179 curproxy->url_param_name = strdup(defproxy.url_param_name);
1180 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001181
Benoitaffb4812009-03-25 13:02:10 +01001182 if (defproxy.hh_name)
1183 curproxy->hh_name = strdup(defproxy.hh_name);
1184 curproxy->hh_len = defproxy.hh_len;
1185 curproxy->hh_match_domain = defproxy.hh_match_domain;
1186
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001187 if (defproxy.iface_name)
1188 curproxy->iface_name = strdup(defproxy.iface_name);
1189 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001192 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001193 if (defproxy.capture_name)
1194 curproxy->capture_name = strdup(defproxy.capture_name);
1195 curproxy->capture_namelen = defproxy.capture_namelen;
1196 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001198
Willy Tarreau977b8e42006-12-29 14:19:17 +01001199 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001200 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001201 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001202 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001203 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001204 curproxy->uri_auth = defproxy.uri_auth;
1205 curproxy->mon_net = defproxy.mon_net;
1206 curproxy->mon_mask = defproxy.mon_mask;
1207 if (defproxy.monitor_uri)
1208 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1209 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001210 if (defproxy.defbe.name)
1211 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001212 }
1213
1214 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001215 curproxy->timeout.connect = defproxy.timeout.connect;
1216 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001217 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001218 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001219 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001220 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001221 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001222 curproxy->source_addr = defproxy.source_addr;
1223 }
1224
Willy Tarreaubaaee002006-06-26 02:48:02 +02001225 curproxy->mode = defproxy.mode;
1226 curproxy->logfac1 = defproxy.logfac1;
1227 curproxy->logsrv1 = defproxy.logsrv1;
1228 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001229 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001230 curproxy->logfac2 = defproxy.logfac2;
1231 curproxy->logsrv2 = defproxy.logsrv2;
1232 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001233 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001234 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001235 curproxy->conf.used_listener_id = EB_ROOT;
1236 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001237
Willy Tarreau93893792009-07-23 13:19:11 +02001238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001239 }
1240 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1241 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001242 /* FIXME-20070101: we should do this too at the end of the
1243 * config parsing to free all default values.
1244 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001245 free(defproxy.check_req);
1246 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001247 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001248 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001249 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001250 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001251 free(defproxy.capture_name);
1252 free(defproxy.monitor_uri);
1253 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001254 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001255 free(defproxy.fwdfor_hdr_name);
1256 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001257 free(defproxy.orgto_hdr_name);
1258 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001259
Willy Tarreaua534fea2008-08-03 12:19:50 +02001260 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001261 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001262
Willy Tarreaubaaee002006-06-26 02:48:02 +02001263 /* we cannot free uri_auth because it might already be used */
1264 init_default_instance();
1265 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001266 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001268 }
1269 else if (curproxy == NULL) {
1270 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001271 err_code |= ERR_ALERT | ERR_FATAL;
1272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001273 }
1274
Willy Tarreau977b8e42006-12-29 14:19:17 +01001275
1276 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001277 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001278 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001279 int cur_arg;
1280
Willy Tarreaubaaee002006-06-26 02:48:02 +02001281 if (curproxy == &defproxy) {
1282 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001283 err_code |= ERR_ALERT | ERR_FATAL;
1284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001285 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001286 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001287 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001288
1289 if (strchr(args[1], ':') == NULL) {
1290 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1291 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001292 err_code |= ERR_ALERT | ERR_FATAL;
1293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001294 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001295
1296 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001297 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001298 err_code |= ERR_ALERT | ERR_FATAL;
1299 goto out;
1300 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001301
Willy Tarreau90a570f2009-10-04 20:54:54 +02001302 new_listen = curproxy->listen;
1303 while (new_listen != last_listen) {
1304 new_listen->conf.file = file;
1305 new_listen->conf.line = linenum;
1306 new_listen = new_listen->next;
1307 }
1308
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001309 cur_arg = 2;
1310 while (*(args[cur_arg])) {
1311 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1312#ifdef SO_BINDTODEVICE
1313 struct listener *l;
1314
1315 if (!*args[cur_arg + 1]) {
1316 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1317 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001318 err_code |= ERR_ALERT | ERR_FATAL;
1319 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001320 }
1321
1322 for (l = curproxy->listen; l != last_listen; l = l->next)
1323 l->interface = strdup(args[cur_arg + 1]);
1324
1325 global.last_checks |= LSTCHK_NETADM;
1326
1327 cur_arg += 2;
1328 continue;
1329#else
1330 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1331 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001332 err_code |= ERR_ALERT | ERR_FATAL;
1333 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001334#endif
1335 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001336 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1337#ifdef TCP_MAXSEG
1338 struct listener *l;
1339 int mss;
1340
1341 if (!*args[cur_arg + 1]) {
1342 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1343 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001344 err_code |= ERR_ALERT | ERR_FATAL;
1345 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001346 }
1347
1348 mss = str2uic(args[cur_arg + 1]);
1349 if (mss < 1 || mss > 65535) {
1350 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1351 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001352 err_code |= ERR_ALERT | ERR_FATAL;
1353 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001354 }
1355
1356 for (l = curproxy->listen; l != last_listen; l = l->next)
1357 l->maxseg = mss;
1358
1359 cur_arg += 2;
1360 continue;
1361#else
1362 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1363 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001364 err_code |= ERR_ALERT | ERR_FATAL;
1365 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001366#endif
1367 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001368
1369 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1370#ifdef TCP_DEFER_ACCEPT
1371 struct listener *l;
1372
1373 for (l = curproxy->listen; l != last_listen; l = l->next)
1374 l->options |= LI_O_DEF_ACCEPT;
1375
1376 cur_arg ++;
1377 continue;
1378#else
1379 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1380 file, linenum, args[0], args[cur_arg]);
1381 err_code |= ERR_ALERT | ERR_FATAL;
1382 goto out;
1383#endif
1384 }
1385
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001386 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001387#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001388 struct listener *l;
1389
1390 for (l = curproxy->listen; l != last_listen; l = l->next)
1391 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001392
1393 cur_arg ++;
1394 continue;
1395#else
1396 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1397 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001398 err_code |= ERR_ALERT | ERR_FATAL;
1399 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001400#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001401 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001402
1403 if (!strcmp(args[cur_arg], "name")) {
1404 struct listener *l;
1405
1406 for (l = curproxy->listen; l != last_listen; l = l->next)
1407 l->name = strdup(args[cur_arg + 1]);
1408
1409 cur_arg += 2;
1410 continue;
1411 }
1412
1413 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001414 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001415 struct listener *l;
1416
1417 if (curproxy->listen->next != last_listen) {
1418 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1419 file, linenum, args[cur_arg]);
1420 err_code |= ERR_ALERT | ERR_FATAL;
1421 goto out;
1422 }
1423
1424 if (!*args[cur_arg + 1]) {
1425 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1426 file, linenum, args[cur_arg]);
1427 err_code |= ERR_ALERT | ERR_FATAL;
1428 goto out;
1429 }
1430
1431 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001432 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001433
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001434 if (curproxy->listen->luid <= 0) {
1435 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001436 file, linenum);
1437 err_code |= ERR_ALERT | ERR_FATAL;
1438 goto out;
1439 }
1440
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001441 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1442 if (node) {
1443 l = container_of(node, struct listener, conf.id);
1444 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1445 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
1448 }
1449 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1450
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001451 cur_arg += 2;
1452 continue;
1453 }
1454
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001455 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001456 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001457 err_code |= ERR_ALERT | ERR_FATAL;
1458 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001460 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462 }
1463 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1464 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1465 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1466 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001467 err_code |= ERR_ALERT | ERR_FATAL;
1468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001469 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001470 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001471 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001472
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473 /* flush useless bits */
1474 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001477 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001478 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001479 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001480
Willy Tarreau1c47f852006-07-09 08:22:27 +02001481 if (!*args[1]) {
1482 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1483 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001484 err_code |= ERR_ALERT | ERR_FATAL;
1485 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001486 }
1487
Willy Tarreaua534fea2008-08-03 12:19:50 +02001488 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001489 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001490 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001491 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001492 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1493
Willy Tarreau93893792009-07-23 13:19:11 +02001494 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001495 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001496 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1497 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1498 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1499 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1500 else {
1501 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001502 err_code |= ERR_ALERT | ERR_FATAL;
1503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001504 }
1505 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001506 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001507 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001508
1509 if (curproxy == &defproxy) {
1510 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1511 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001512 err_code |= ERR_ALERT | ERR_FATAL;
1513 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001514 }
1515
1516 if (!*args[1]) {
1517 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1518 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001519 err_code |= ERR_ALERT | ERR_FATAL;
1520 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001521 }
1522
1523 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001524 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001525
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001526 if (curproxy->uuid <= 0) {
1527 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001528 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001531 }
1532
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001533 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1534 if (node) {
1535 struct proxy *target = container_of(node, struct proxy, conf.id);
1536 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1537 file, linenum, proxy_type_str(curproxy), curproxy->id,
1538 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1539 err_code |= ERR_ALERT | ERR_FATAL;
1540 goto out;
1541 }
1542 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001543 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001544 else if (!strcmp(args[0], "description")) {
1545 int i, len=0;
1546 char *d;
1547
Cyril Bonté99ed3272010-01-24 23:29:44 +01001548 if (curproxy == &defproxy) {
1549 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1550 file, linenum, args[0]);
1551 err_code |= ERR_ALERT | ERR_FATAL;
1552 goto out;
1553 }
1554
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001555 if (!*args[1]) {
1556 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1557 file, linenum, args[0]);
1558 return -1;
1559 }
1560
1561 for(i=1; *args[i]; i++)
1562 len += strlen(args[i])+1;
1563
1564 d = (char *)calloc(1, len);
1565 curproxy->desc = d;
1566
1567 d += sprintf(d, "%s", args[1]);
1568 for(i=2; *args[i]; i++)
1569 d += sprintf(d, " %s", args[i]);
1570
1571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1573 curproxy->state = PR_STSTOPPED;
1574 }
1575 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1576 curproxy->state = PR_STNEW;
1577 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001578 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1579 int cur_arg = 1;
1580 unsigned int set = 0;
1581
1582 while (*args[cur_arg]) {
1583 int u;
1584 if (strcmp(args[cur_arg], "all") == 0) {
1585 set = 0;
1586 break;
1587 }
1588 else if (strcmp(args[cur_arg], "odd") == 0) {
1589 set |= 0x55555555;
1590 }
1591 else if (strcmp(args[cur_arg], "even") == 0) {
1592 set |= 0xAAAAAAAA;
1593 }
1594 else {
1595 u = str2uic(args[cur_arg]);
1596 if (u < 1 || u > 32) {
1597 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1598 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001599 err_code |= ERR_ALERT | ERR_FATAL;
1600 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001601 }
1602 if (u > global.nbproc) {
1603 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1604 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001605 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001606 }
1607 set |= 1 << (u - 1);
1608 }
1609 cur_arg++;
1610 }
1611 curproxy->bind_proc = set;
1612 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001613 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001614 if (curproxy == &defproxy) {
1615 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001616 err_code |= ERR_ALERT | ERR_FATAL;
1617 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001618 }
1619
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001620 err = invalid_char(args[1]);
1621 if (err) {
1622 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1623 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001624 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001625 }
1626
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001627 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1628 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1629 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001630 err_code |= ERR_ALERT | ERR_FATAL;
1631 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001632 }
1633 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1635 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636
Willy Tarreau977b8e42006-12-29 14:19:17 +01001637 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001638 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001639
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640 if (*(args[1]) == 0) {
1641 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1642 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001643 err_code |= ERR_ALERT | ERR_FATAL;
1644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001645 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001646
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001647 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001648 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 curproxy->cookie_name = strdup(args[1]);
1650 curproxy->cookie_len = strlen(curproxy->cookie_name);
1651
1652 cur_arg = 2;
1653 while (*(args[cur_arg])) {
1654 if (!strcmp(args[cur_arg], "rewrite")) {
1655 curproxy->options |= PR_O_COOK_RW;
1656 }
1657 else if (!strcmp(args[cur_arg], "indirect")) {
1658 curproxy->options |= PR_O_COOK_IND;
1659 }
1660 else if (!strcmp(args[cur_arg], "insert")) {
1661 curproxy->options |= PR_O_COOK_INS;
1662 }
1663 else if (!strcmp(args[cur_arg], "nocache")) {
1664 curproxy->options |= PR_O_COOK_NOC;
1665 }
1666 else if (!strcmp(args[cur_arg], "postonly")) {
1667 curproxy->options |= PR_O_COOK_POST;
1668 }
1669 else if (!strcmp(args[cur_arg], "prefix")) {
1670 curproxy->options |= PR_O_COOK_PFX;
1671 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001672 else if (!strcmp(args[cur_arg], "domain")) {
1673 if (!*args[cur_arg + 1]) {
1674 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1675 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001676 err_code |= ERR_ALERT | ERR_FATAL;
1677 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001678 }
1679
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001680 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001681 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001682 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1683 " dots nor does not start with a dot."
1684 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001685 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001686 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001687 }
1688
1689 err = invalid_domainchar(args[cur_arg + 1]);
1690 if (err) {
1691 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1692 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001693 err_code |= ERR_ALERT | ERR_FATAL;
1694 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001695 }
1696
Willy Tarreau68a897b2009-12-03 23:28:34 +01001697 if (!curproxy->cookie_domain) {
1698 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1699 } else {
1700 /* one domain was already specified, add another one by
1701 * building the string which will be returned along with
1702 * the cookie.
1703 */
1704 char *new_ptr;
1705 int new_len = strlen(curproxy->cookie_domain) +
1706 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1707 new_ptr = malloc(new_len);
1708 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1709 free(curproxy->cookie_domain);
1710 curproxy->cookie_domain = new_ptr;
1711 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001712 cur_arg++;
1713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001715 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001716 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001717 err_code |= ERR_ALERT | ERR_FATAL;
1718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001719 }
1720 cur_arg++;
1721 }
1722 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1723 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1724 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001725 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001726 }
1727
1728 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1729 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1730 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001731 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001732 }
1733 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001734 else if (!strcmp(args[0], "persist")) { /* persist */
1735 if (*(args[1]) == 0) {
1736 Alert("parsing [%s:%d] : missing persist method.\n",
1737 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001738 err_code |= ERR_ALERT | ERR_FATAL;
1739 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001740 }
1741
1742 if (!strncmp(args[1], "rdp-cookie", 10)) {
1743 curproxy->options2 |= PR_O2_RDPC_PRST;
1744
Emeric Brunb982a3d2010-01-04 15:45:53 +01001745 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001746 const char *beg, *end;
1747
1748 beg = args[1] + 11;
1749 end = strchr(beg, ')');
1750
1751 if (!end || end == beg) {
1752 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1753 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001754 err_code |= ERR_ALERT | ERR_FATAL;
1755 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001756 }
1757
1758 free(curproxy->rdp_cookie_name);
1759 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1760 curproxy->rdp_cookie_len = end-beg;
1761 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001762 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001763 free(curproxy->rdp_cookie_name);
1764 curproxy->rdp_cookie_name = strdup("msts");
1765 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1766 }
1767 else { /* syntax */
1768 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1769 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001772 }
1773 }
1774 else {
1775 Alert("parsing [%s:%d] : unknown persist method.\n",
1776 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001777 err_code |= ERR_ALERT | ERR_FATAL;
1778 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001779 }
1780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001781 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001782 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001783
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001784 if (curproxy == &defproxy) {
1785 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1786 err_code |= ERR_ALERT | ERR_FATAL;
1787 goto out;
1788 }
1789
Willy Tarreau977b8e42006-12-29 14:19:17 +01001790 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001791 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001792
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001794 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001795 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001796 err_code |= ERR_ALERT | ERR_FATAL;
1797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001798 }
1799 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001800 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801 curproxy->appsession_name = strdup(args[1]);
1802 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1803 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001804 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1805 if (err) {
1806 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1807 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001808 err_code |= ERR_ALERT | ERR_FATAL;
1809 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001810 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001811 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001812
Willy Tarreau51041c72007-09-09 21:56:53 +02001813 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1814 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001815 err_code |= ERR_ALERT | ERR_ABORT;
1816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001817 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001818
1819 cur_arg = 6;
1820 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001821 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1822 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001823 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001824 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001825 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001826 } else if (!strcmp(args[cur_arg], "prefix")) {
1827 curproxy->options2 |= PR_O2_AS_PFX;
1828 } else if (!strcmp(args[cur_arg], "mode")) {
1829 if (!*args[cur_arg + 1]) {
1830 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1831 file, linenum, args[0], args[cur_arg]);
1832 err_code |= ERR_ALERT | ERR_FATAL;
1833 goto out;
1834 }
1835
1836 cur_arg++;
1837 if (!strcmp(args[cur_arg], "query-string")) {
1838 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1839 curproxy->options2 |= PR_O2_AS_M_QS;
1840 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1841 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1842 curproxy->options2 |= PR_O2_AS_M_PP;
1843 } else {
1844 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1845 err_code |= ERR_ALERT | ERR_FATAL;
1846 goto out;
1847 }
1848 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001849 cur_arg++;
1850 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001851 } /* Url App Session */
1852 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001853 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001854 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001855
Willy Tarreaubaaee002006-06-26 02:48:02 +02001856 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001857 if (curproxy == &defproxy) {
1858 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1859 err_code |= ERR_ALERT | ERR_FATAL;
1860 goto out;
1861 }
1862
Willy Tarreaubaaee002006-06-26 02:48:02 +02001863 if (*(args[4]) == 0) {
1864 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1865 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001866 err_code |= ERR_ALERT | ERR_FATAL;
1867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001869 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001870 curproxy->capture_name = strdup(args[2]);
1871 curproxy->capture_namelen = strlen(curproxy->capture_name);
1872 curproxy->capture_len = atol(args[4]);
1873 if (curproxy->capture_len >= CAPTURE_LEN) {
1874 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1875 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001876 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001877 curproxy->capture_len = CAPTURE_LEN - 1;
1878 }
1879 curproxy->to_log |= LW_COOKIE;
1880 }
1881 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1882 struct cap_hdr *hdr;
1883
1884 if (curproxy == &defproxy) {
1885 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 +02001886 err_code |= ERR_ALERT | ERR_FATAL;
1887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001888 }
1889
1890 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1891 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1892 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001893 err_code |= ERR_ALERT | ERR_FATAL;
1894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001895 }
1896
1897 hdr = calloc(sizeof(struct cap_hdr), 1);
1898 hdr->next = curproxy->req_cap;
1899 hdr->name = strdup(args[3]);
1900 hdr->namelen = strlen(args[3]);
1901 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001902 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001903 hdr->index = curproxy->nb_req_cap++;
1904 curproxy->req_cap = hdr;
1905 curproxy->to_log |= LW_REQHDR;
1906 }
1907 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1908 struct cap_hdr *hdr;
1909
1910 if (curproxy == &defproxy) {
1911 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 +02001912 err_code |= ERR_ALERT | ERR_FATAL;
1913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914 }
1915
1916 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1917 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1918 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001919 err_code |= ERR_ALERT | ERR_FATAL;
1920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 }
1922 hdr = calloc(sizeof(struct cap_hdr), 1);
1923 hdr->next = curproxy->rsp_cap;
1924 hdr->name = strdup(args[3]);
1925 hdr->namelen = strlen(args[3]);
1926 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001927 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001928 hdr->index = curproxy->nb_rsp_cap++;
1929 curproxy->rsp_cap = hdr;
1930 curproxy->to_log |= LW_RSPHDR;
1931 }
1932 else {
1933 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1934 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_ALERT | ERR_FATAL;
1936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 }
1938 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001940 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001941 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001942
Willy Tarreaubaaee002006-06-26 02:48:02 +02001943 if (*(args[1]) == 0) {
1944 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1945 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001946 err_code |= ERR_ALERT | ERR_FATAL;
1947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001948 }
1949 curproxy->conn_retries = atol(args[1]);
1950 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001951 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
1952 struct req_acl_rule *req_acl;
1953
1954 if (curproxy == &defproxy) {
1955 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1956 err_code |= ERR_ALERT | ERR_FATAL;
1957 goto out;
1958 }
1959
1960
1961 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
1962 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
1963 file, linenum, args[0]);
1964 err_code |= ERR_WARN;
1965 }
1966
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001967 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001968
1969 if (!req_acl) {
1970 err_code |= ERR_ALERT | ERR_ABORT;
1971 goto out;
1972 }
1973
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001974 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001975 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
1976 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001977 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001978 if (curproxy == &defproxy) {
1979 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001980 err_code |= ERR_ALERT | ERR_FATAL;
1981 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001982 }
1983
Willy Tarreauef6494c2010-01-28 17:12:36 +01001984 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001985 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1986 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001987 err_code |= ERR_ALERT | ERR_FATAL;
1988 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001989 }
1990
Willy Tarreauef6494c2010-01-28 17:12:36 +01001991 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001992 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1993 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001994 err_code |= ERR_ALERT | ERR_FATAL;
1995 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001996 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01001997
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001998 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001999 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002000 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002001 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002002 struct redirect_rule *rule;
2003 int cur_arg;
2004 int type = REDIRECT_TYPE_NONE;
2005 int code = 302;
2006 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002007 char *cookie = NULL;
2008 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002009 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002010
Cyril Bonté99ed3272010-01-24 23:29:44 +01002011 if (curproxy == &defproxy) {
2012 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2013 err_code |= ERR_ALERT | ERR_FATAL;
2014 goto out;
2015 }
2016
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002017 cur_arg = 1;
2018 while (*(args[cur_arg])) {
2019 if (!strcmp(args[cur_arg], "location")) {
2020 if (!*args[cur_arg + 1]) {
2021 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2022 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002023 err_code |= ERR_ALERT | ERR_FATAL;
2024 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002025 }
2026
2027 type = REDIRECT_TYPE_LOCATION;
2028 cur_arg++;
2029 destination = args[cur_arg];
2030 }
2031 else if (!strcmp(args[cur_arg], "prefix")) {
2032 if (!*args[cur_arg + 1]) {
2033 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2034 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002035 err_code |= ERR_ALERT | ERR_FATAL;
2036 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002037 }
2038
2039 type = REDIRECT_TYPE_PREFIX;
2040 cur_arg++;
2041 destination = args[cur_arg];
2042 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002043 else if (!strcmp(args[cur_arg], "set-cookie")) {
2044 if (!*args[cur_arg + 1]) {
2045 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2046 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002047 err_code |= ERR_ALERT | ERR_FATAL;
2048 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002049 }
2050
2051 cur_arg++;
2052 cookie = args[cur_arg];
2053 cookie_set = 1;
2054 }
2055 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2056 if (!*args[cur_arg + 1]) {
2057 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2058 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002061 }
2062
2063 cur_arg++;
2064 cookie = args[cur_arg];
2065 cookie_set = 0;
2066 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002067 else if (!strcmp(args[cur_arg],"code")) {
2068 if (!*args[cur_arg + 1]) {
2069 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2070 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002073 }
2074 cur_arg++;
2075 code = atol(args[cur_arg]);
2076 if (code < 301 || code > 303) {
2077 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2078 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002079 err_code |= ERR_ALERT | ERR_FATAL;
2080 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002081 }
2082 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002083 else if (!strcmp(args[cur_arg],"drop-query")) {
2084 flags |= REDIRECT_FLAG_DROP_QS;
2085 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002086 else if (!strcmp(args[cur_arg],"append-slash")) {
2087 flags |= REDIRECT_FLAG_APPEND_SLASH;
2088 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002089 else if (strcmp(args[cur_arg], "if") == 0 ||
2090 strcmp(args[cur_arg], "unless") == 0) {
2091 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2092 if (!cond) {
2093 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2094 file, linenum, args[0]);
2095 err_code |= ERR_ALERT | ERR_FATAL;
2096 goto out;
2097 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002098 break;
2099 }
2100 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002101 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 +02002102 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002103 err_code |= ERR_ALERT | ERR_FATAL;
2104 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002105 }
2106 cur_arg++;
2107 }
2108
2109 if (type == REDIRECT_TYPE_NONE) {
2110 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2111 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002112 err_code |= ERR_ALERT | ERR_FATAL;
2113 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002114 }
2115
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002116 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2117 rule->cond = cond;
2118 rule->rdr_str = strdup(destination);
2119 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002120 if (cookie) {
2121 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002122 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002123 */
2124 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002125 if (cookie_set) {
2126 rule->cookie_str = malloc(rule->cookie_len + 10);
2127 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2128 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2129 rule->cookie_len += 9;
2130 } else {
2131 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002132 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002133 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2134 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002135 }
2136 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002137 rule->type = type;
2138 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002139 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002140 LIST_INIT(&rule->list);
2141 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002142 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002143 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002144 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002145 struct switching_rule *rule;
2146
Willy Tarreaub099aca2008-10-12 17:26:37 +02002147 if (curproxy == &defproxy) {
2148 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002149 err_code |= ERR_ALERT | ERR_FATAL;
2150 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002151 }
2152
Willy Tarreau55ea7572007-06-17 19:56:27 +02002153 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002154 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002155
2156 if (*(args[1]) == 0) {
2157 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002158 err_code |= ERR_ALERT | ERR_FATAL;
2159 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002160 }
2161
Willy Tarreauef6494c2010-01-28 17:12:36 +01002162 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002163 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2164 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002167 }
2168
Willy Tarreauef6494c2010-01-28 17:12:36 +01002169 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002170 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002171 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002172 err_code |= ERR_ALERT | ERR_FATAL;
2173 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002174 }
2175
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002176 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002177
Willy Tarreau55ea7572007-06-17 19:56:27 +02002178 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2179 rule->cond = cond;
2180 rule->be.name = strdup(args[1]);
2181 LIST_INIT(&rule->list);
2182 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2183 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002184 else if ((!strcmp(args[0], "force-persist")) ||
2185 (!strcmp(args[0], "ignore-persist"))) {
2186 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002187
2188 if (curproxy == &defproxy) {
2189 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2190 err_code |= ERR_ALERT | ERR_FATAL;
2191 goto out;
2192 }
2193
2194 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2195 err_code |= ERR_WARN;
2196
Willy Tarreauef6494c2010-01-28 17:12:36 +01002197 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002198 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2199 file, linenum, args[0]);
2200 err_code |= ERR_ALERT | ERR_FATAL;
2201 goto out;
2202 }
2203
Willy Tarreauef6494c2010-01-28 17:12:36 +01002204 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002205 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2206 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
2209 }
2210
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002211 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002212
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002213 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002214 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002215 if (!strcmp(args[0], "force-persist")) {
2216 rule->type = PERSIST_TYPE_FORCE;
2217 } else {
2218 rule->type = PERSIST_TYPE_IGNORE;
2219 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002220 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002221 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002222 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002223 else if (!strcmp(args[0], "stick-table")) {
2224 int myidx = 1;
2225
2226 curproxy->table.type = (unsigned int)-1;
2227 while (*args[myidx]) {
2228 const char *err;
2229
2230 if (strcmp(args[myidx], "size") == 0) {
2231 myidx++;
2232 if (!*(args[myidx])) {
2233 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2234 file, linenum, args[myidx-1]);
2235 err_code |= ERR_ALERT | ERR_FATAL;
2236 goto out;
2237 }
2238 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2239 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2240 file, linenum, *err, args[myidx-1]);
2241 err_code |= ERR_ALERT | ERR_FATAL;
2242 goto out;
2243 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002244 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002245 }
2246 else if (strcmp(args[myidx], "expire") == 0) {
2247 myidx++;
2248 if (!*(args[myidx])) {
2249 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2250 file, linenum, args[myidx-1]);
2251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
2253 }
2254 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2255 if (err) {
2256 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2257 file, linenum, *err, args[myidx-1]);
2258 err_code |= ERR_ALERT | ERR_FATAL;
2259 goto out;
2260 }
2261 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002262 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002263 }
2264 else if (strcmp(args[myidx], "nopurge") == 0) {
2265 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002266 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002267 }
2268 else if (strcmp(args[myidx], "type") == 0) {
2269 myidx++;
2270 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2271 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2272 file, linenum, args[myidx]);
2273 err_code |= ERR_ALERT | ERR_FATAL;
2274 goto out;
2275 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002276 /* myidx already points to next arg */
2277 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002278 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002279 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002280 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002281
2282 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002283 nw = args[myidx];
2284 while (*nw) {
2285 /* the "store" keyword supports a comma-separated list */
2286 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002287 sa = NULL; /* store arg */
2288 while (*nw && *nw != ',') {
2289 if (*nw == '(') {
2290 *nw = 0;
2291 sa = ++nw;
2292 while (*nw != ')') {
2293 if (!*nw) {
2294 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2295 file, linenum, args[0], cw);
2296 err_code |= ERR_ALERT | ERR_FATAL;
2297 goto out;
2298 }
2299 nw++;
2300 }
2301 *nw = '\0';
2302 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002303 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002304 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002305 if (*nw)
2306 *nw++ = '\0';
2307 type = stktable_get_data_type(cw);
2308 if (type < 0) {
2309 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2310 file, linenum, args[0], cw);
2311 err_code |= ERR_ALERT | ERR_FATAL;
2312 goto out;
2313 }
Willy Tarreauac782882010-06-20 10:41:54 +02002314
2315 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2316 switch (err) {
2317 case PE_NONE: break;
2318 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002319 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2320 file, linenum, args[0], cw);
2321 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002322 break;
2323
2324 case PE_ARG_MISSING:
2325 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2326 file, linenum, args[0], cw);
2327 err_code |= ERR_ALERT | ERR_FATAL;
2328 goto out;
2329
2330 case PE_ARG_NOT_USED:
2331 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2332 file, linenum, args[0], cw);
2333 err_code |= ERR_ALERT | ERR_FATAL;
2334 goto out;
2335
2336 default:
2337 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2338 file, linenum, args[0], cw);
2339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002341 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002342 }
2343 myidx++;
2344 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002345 else {
2346 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2347 file, linenum, args[myidx]);
2348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002350 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002351 }
2352
2353 if (!curproxy->table.size) {
2354 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2355 file, linenum);
2356 err_code |= ERR_ALERT | ERR_FATAL;
2357 goto out;
2358 }
2359
2360 if (curproxy->table.type == (unsigned int)-1) {
2361 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2362 file, linenum);
2363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
2365 }
2366 }
2367 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002368 struct sticking_rule *rule;
2369 struct pattern_expr *expr;
2370 int myidx = 0;
2371 const char *name = NULL;
2372 int flags;
2373
2374 if (curproxy == &defproxy) {
2375 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
2378 }
2379
2380 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2381 err_code |= ERR_WARN;
2382 goto out;
2383 }
2384
2385 myidx++;
2386 if ((strcmp(args[myidx], "store") == 0) ||
2387 (strcmp(args[myidx], "store-request") == 0)) {
2388 myidx++;
2389 flags = STK_IS_STORE;
2390 }
2391 else if (strcmp(args[myidx], "store-response") == 0) {
2392 myidx++;
2393 flags = STK_IS_STORE | STK_ON_RSP;
2394 }
2395 else if (strcmp(args[myidx], "match") == 0) {
2396 myidx++;
2397 flags = STK_IS_MATCH;
2398 }
2399 else if (strcmp(args[myidx], "on") == 0) {
2400 myidx++;
2401 flags = STK_IS_MATCH | STK_IS_STORE;
2402 }
2403 else {
2404 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2405 err_code |= ERR_ALERT | ERR_FATAL;
2406 goto out;
2407 }
2408
2409 if (*(args[myidx]) == 0) {
2410 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
2413 }
2414
2415 expr = pattern_parse_expr(args, &myidx);
2416 if (!expr) {
2417 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
2420 }
2421
2422 if (flags & STK_ON_RSP) {
2423 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2424 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2425 file, linenum, args[0], expr->fetch->kw);
2426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
2428 }
2429 } else {
2430 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2431 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2432 file, linenum, args[0], expr->fetch->kw);
2433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
2435 }
2436 }
2437
2438 if (strcmp(args[myidx], "table") == 0) {
2439 myidx++;
2440 name = args[myidx++];
2441 }
2442
Willy Tarreauef6494c2010-01-28 17:12:36 +01002443 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2444 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002445 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2446 file, linenum, args[0]);
2447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
2449 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002450 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002451 else if (*(args[myidx])) {
2452 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2453 file, linenum, args[0], args[myidx]);
2454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
2456 }
2457
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002458 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2459
Emeric Brunb982a3d2010-01-04 15:45:53 +01002460 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2461 rule->cond = cond;
2462 rule->expr = expr;
2463 rule->flags = flags;
2464 rule->table.name = name ? strdup(name) : NULL;
2465 LIST_INIT(&rule->list);
2466 if (flags & STK_ON_RSP)
2467 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2468 else
2469 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2470 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002472 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002473 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002474
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2476 curproxy->uri_auth = NULL; /* we must detach from the default config */
2477
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002478 if (!*args[1]) {
2479 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480 } else if (!strcmp(args[1], "uri")) {
2481 if (*(args[2]) == 0) {
2482 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2486 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_ALERT | ERR_ABORT;
2488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 }
2490 } else if (!strcmp(args[1], "realm")) {
2491 if (*(args[2]) == 0) {
2492 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2496 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002497 err_code |= ERR_ALERT | ERR_ABORT;
2498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002500 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002501 unsigned interval;
2502
2503 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2504 if (err) {
2505 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2506 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002509 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2510 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002511 err_code |= ERR_ALERT | ERR_ABORT;
2512 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002513 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002514 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2515 struct req_acl_rule *req_acl;
2516
2517 if (curproxy == &defproxy) {
2518 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
2521 }
2522
2523 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2524 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2525 err_code |= ERR_ALERT | ERR_ABORT;
2526 goto out;
2527 }
2528
2529 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2530 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2531 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2532 file, linenum, args[0]);
2533 err_code |= ERR_WARN;
2534 }
2535
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002536 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002537
2538 if (!req_acl) {
2539 err_code |= ERR_ALERT | ERR_ABORT;
2540 goto out;
2541 }
2542
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002543 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002544 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2545
Willy Tarreaubaaee002006-06-26 02:48:02 +02002546 } else if (!strcmp(args[1], "auth")) {
2547 if (*(args[2]) == 0) {
2548 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2552 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_ABORT;
2554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 }
2556 } else if (!strcmp(args[1], "scope")) {
2557 if (*(args[2]) == 0) {
2558 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2562 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002563 err_code |= ERR_ALERT | ERR_ABORT;
2564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 }
2566 } else if (!strcmp(args[1], "enable")) {
2567 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2568 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_ABORT;
2570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002572 } else if (!strcmp(args[1], "hide-version")) {
2573 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2574 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_ABORT;
2576 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002577 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002578 } else if (!strcmp(args[1], "show-legends")) {
2579 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2580 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2581 err_code |= ERR_ALERT | ERR_ABORT;
2582 goto out;
2583 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002584 } else if (!strcmp(args[1], "show-node")) {
2585
2586 if (*args[2]) {
2587 int i;
2588 char c;
2589
2590 for (i=0; args[2][i]; i++) {
2591 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01002592 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
2593 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002594 break;
2595 }
2596
2597 if (!i || args[2][i]) {
2598 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2599 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2600 file, linenum, args[0], args[1]);
2601 err_code |= ERR_ALERT | ERR_FATAL;
2602 goto out;
2603 }
2604 }
2605
2606 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2607 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2608 err_code |= ERR_ALERT | ERR_ABORT;
2609 goto out;
2610 }
2611 } else if (!strcmp(args[1], "show-desc")) {
2612 char *desc = NULL;
2613
2614 if (*args[2]) {
2615 int i, len=0;
2616 char *d;
2617
2618 for(i=2; *args[i]; i++)
2619 len += strlen(args[i])+1;
2620
2621 desc = d = (char *)calloc(1, len);
2622
2623 d += sprintf(d, "%s", args[2]);
2624 for(i=3; *args[i]; i++)
2625 d += sprintf(d, " %s", args[i]);
2626 }
2627
2628 if (!*args[2] && !global.desc)
2629 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2630 file, linenum, args[1]);
2631 else {
2632 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2633 free(desc);
2634 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2635 err_code |= ERR_ALERT | ERR_ABORT;
2636 goto out;
2637 }
2638 free(desc);
2639 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002640 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002641stats_error_parsing:
2642 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2643 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002644 err_code |= ERR_ALERT | ERR_FATAL;
2645 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646 }
2647 }
2648 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002649 int optnum;
2650
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002651 if (*(args[1]) == '\0') {
2652 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2653 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002656 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002657
2658 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2659 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002660 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2661 err_code |= ERR_WARN;
2662 goto out;
2663 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002664
Willy Tarreau3842f002009-06-14 11:39:52 +02002665 curproxy->no_options &= ~cfg_opts[optnum].val;
2666 curproxy->options &= ~cfg_opts[optnum].val;
2667
2668 switch (kwm) {
2669 case KWM_STD:
2670 curproxy->options |= cfg_opts[optnum].val;
2671 break;
2672 case KWM_NO:
2673 curproxy->no_options |= cfg_opts[optnum].val;
2674 break;
2675 case KWM_DEF: /* already cleared */
2676 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002677 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002678
Willy Tarreau93893792009-07-23 13:19:11 +02002679 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002680 }
2681 }
2682
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002683 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2684 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002685 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2686 err_code |= ERR_WARN;
2687 goto out;
2688 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002689
Willy Tarreau3842f002009-06-14 11:39:52 +02002690 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2691 curproxy->options2 &= ~cfg_opts2[optnum].val;
2692
2693 switch (kwm) {
2694 case KWM_STD:
2695 curproxy->options2 |= cfg_opts2[optnum].val;
2696 break;
2697 case KWM_NO:
2698 curproxy->no_options2 |= cfg_opts2[optnum].val;
2699 break;
2700 case KWM_DEF: /* already cleared */
2701 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002702 }
Willy Tarreau93893792009-07-23 13:19:11 +02002703 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002704 }
2705 }
2706
Willy Tarreau3842f002009-06-14 11:39:52 +02002707 if (kwm != KWM_STD) {
2708 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002709 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002712 }
2713
Emeric Brun3a058f32009-06-30 18:26:00 +02002714 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002715 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002716 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002717 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002718 if (*(args[2]) != '\0') {
2719 if (!strcmp(args[2], "clf")) {
2720 curproxy->options2 |= PR_O2_CLFLOG;
2721 } else {
2722 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002725 }
2726 }
2727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728 else if (!strcmp(args[1], "tcplog"))
2729 /* generate a detailed TCP log */
2730 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 else if (!strcmp(args[1], "tcpka")) {
2732 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002733 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002734 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002735
2736 if (curproxy->cap & PR_CAP_FE)
2737 curproxy->options |= PR_O_TCP_CLI_KA;
2738 if (curproxy->cap & PR_CAP_BE)
2739 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 }
2741 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002742 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002743 err_code |= ERR_WARN;
2744
Willy Tarreaubaaee002006-06-26 02:48:02 +02002745 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002746 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002747 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002748 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002749 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002750 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002751 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002752 if (!*args[2]) { /* no argument */
2753 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2754 curproxy->check_len = strlen(DEF_CHECK_REQ);
2755 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002756 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 curproxy->check_req = (char *)malloc(reqlen);
2758 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002759 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002761 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002762 if (*args[4])
2763 reqlen += strlen(args[4]);
2764 else
2765 reqlen += strlen("HTTP/1.0");
2766
2767 curproxy->check_req = (char *)malloc(reqlen);
2768 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002769 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002771 }
2772 else if (!strcmp(args[1], "ssl-hello-chk")) {
2773 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002774 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002775 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002776
Willy Tarreaua534fea2008-08-03 12:19:50 +02002777 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002778 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002779 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002780 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002781 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002782 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 }
Willy Tarreau23677902007-05-08 23:50:35 +02002784 else if (!strcmp(args[1], "smtpchk")) {
2785 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002786 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002787 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002788 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002789 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002790 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002791 curproxy->options |= PR_O_SMTP_CHK;
2792
2793 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2794 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2795 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2796 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2797 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2798 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2799 curproxy->check_req = (char *)malloc(reqlen);
2800 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2801 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2802 } else {
2803 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2804 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2805 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2806 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2807 }
2808 }
2809 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002810 else if (!strcmp(args[1], "mysql-check")) {
2811 /* use MYSQL request to check servers' health */
2812 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002813 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002814 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002815 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02002816 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002817 curproxy->options2 |= PR_O2_MYSQL_CHK;
2818 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002819 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002820 int cur_arg;
2821
2822 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2823 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002824 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002825
2826 curproxy->options |= PR_O_FWDFOR;
2827
2828 free(curproxy->fwdfor_hdr_name);
2829 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2830 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2831
2832 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2833 cur_arg = 2;
2834 while (*(args[cur_arg])) {
2835 if (!strcmp(args[cur_arg], "except")) {
2836 /* suboption except - needs additional argument for it */
2837 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2838 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2839 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002842 }
2843 /* flush useless bits */
2844 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002845 cur_arg += 2;
2846 } else if (!strcmp(args[cur_arg], "header")) {
2847 /* suboption header - needs additional argument for it */
2848 if (*(args[cur_arg+1]) == 0) {
2849 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2850 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002851 err_code |= ERR_ALERT | ERR_FATAL;
2852 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002853 }
2854 free(curproxy->fwdfor_hdr_name);
2855 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2856 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2857 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002858 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002859 /* unknown suboption - catchall */
2860 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2861 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002862 err_code |= ERR_ALERT | ERR_FATAL;
2863 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002864 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002865 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002866 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002867 else if (!strcmp(args[1], "originalto")) {
2868 int cur_arg;
2869
2870 /* insert x-original-to field, but not for the IP address listed as an except.
2871 * set default options (ie: bitfield, header name, etc)
2872 */
2873
2874 curproxy->options |= PR_O_ORGTO;
2875
2876 free(curproxy->orgto_hdr_name);
2877 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2878 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2879
2880 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2881 cur_arg = 2;
2882 while (*(args[cur_arg])) {
2883 if (!strcmp(args[cur_arg], "except")) {
2884 /* suboption except - needs additional argument for it */
2885 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2886 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2887 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002890 }
2891 /* flush useless bits */
2892 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2893 cur_arg += 2;
2894 } else if (!strcmp(args[cur_arg], "header")) {
2895 /* suboption header - needs additional argument for it */
2896 if (*(args[cur_arg+1]) == 0) {
2897 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2898 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002899 err_code |= ERR_ALERT | ERR_FATAL;
2900 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002901 }
2902 free(curproxy->orgto_hdr_name);
2903 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2904 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2905 cur_arg += 2;
2906 } else {
2907 /* unknown suboption - catchall */
2908 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2909 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002912 }
2913 } /* end while loop */
2914 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 else {
2916 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 }
Willy Tarreau93893792009-07-23 13:19:11 +02002920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002921 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002922 else if (!strcmp(args[0], "default_backend")) {
2923 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002924 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002925
2926 if (*(args[1]) == 0) {
2927 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002930 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002931 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002932 curproxy->defbe.name = strdup(args[1]);
2933 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002935 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002936 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002937
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002938 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2939 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002940 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002941 /* enable reconnections to dispatch */
2942 curproxy->options |= PR_O_REDISP;
2943 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002944 else if (!strcmp(args[0], "http-check")) {
2945 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002946 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002947
2948 if (strcmp(args[1], "disable-on-404") == 0) {
2949 /* enable a graceful server shutdown on an HTTP 404 response */
2950 curproxy->options |= PR_O_DISABLE404;
2951 }
Willy Tarreauef781042010-01-27 11:53:01 +01002952 else if (strcmp(args[1], "send-state") == 0) {
2953 /* enable emission of the apparent state of a server in HTTP checks */
2954 curproxy->options2 |= PR_O2_CHK_SNDST;
2955 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002956 else {
2957 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002958 err_code |= ERR_ALERT | ERR_FATAL;
2959 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002960 }
2961 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002962 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002963 if (curproxy == &defproxy) {
2964 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002965 err_code |= ERR_ALERT | ERR_FATAL;
2966 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002967 }
2968
Willy Tarreaub80c2302007-11-30 20:51:32 +01002969 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002970 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002971
2972 if (strcmp(args[1], "fail") == 0) {
2973 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01002974 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002975 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2976 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002977 err_code |= ERR_ALERT | ERR_FATAL;
2978 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002979 }
2980
Willy Tarreauef6494c2010-01-28 17:12:36 +01002981 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002982 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2983 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002986 }
2987 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2988 }
2989 else {
2990 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002993 }
2994 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002995#ifdef TPROXY
2996 else if (!strcmp(args[0], "transparent")) {
2997 /* enable transparent proxy connections */
2998 curproxy->options |= PR_O_TRANSP;
2999 }
3000#endif
3001 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003002 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003003 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003004
Willy Tarreaubaaee002006-06-26 02:48:02 +02003005 if (*(args[1]) == 0) {
3006 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 }
3010 curproxy->maxconn = atol(args[1]);
3011 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003012 else if (!strcmp(args[0], "backlog")) { /* backlog */
3013 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003014 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003015
3016 if (*(args[1]) == 0) {
3017 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003020 }
3021 curproxy->backlog = atol(args[1]);
3022 }
Willy Tarreau86034312006-12-29 00:10:33 +01003023 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003024 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003025 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003026
Willy Tarreau86034312006-12-29 00:10:33 +01003027 if (*(args[1]) == 0) {
3028 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003029 err_code |= ERR_ALERT | ERR_FATAL;
3030 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003031 }
3032 curproxy->fullconn = atol(args[1]);
3033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003034 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3035 if (*(args[1]) == 0) {
3036 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003039 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003040 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3041 if (err) {
3042 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3043 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003044 err_code |= ERR_ALERT | ERR_FATAL;
3045 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003046 }
3047 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048 }
3049 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01003050 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 if (curproxy == &defproxy) {
3052 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003056 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003057 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003058
Willy Tarreaubaaee002006-06-26 02:48:02 +02003059 if (strchr(args[1], ':') == NULL) {
3060 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003064 sk = str2sa(args[1]);
3065 if (!sk) {
3066 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3067 err_code |= ERR_ALERT | ERR_FATAL;
3068 goto out;
3069 }
3070 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 }
3072 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003073 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003074 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003075
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003076 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003077 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3078 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003081 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003083 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3084 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3085 err_code |= ERR_WARN;
3086
3087 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3088 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3089 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3090 }
3091 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3092 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3093 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3094 }
3095 else {
3096 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3097 err_code |= ERR_ALERT | ERR_FATAL;
3098 goto out;
3099 }
3100 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003101 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003103 char *rport, *raddr;
3104 short realport = 0;
3105 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003107 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003111 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003112 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003113 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003114
3115 if (!*args[2]) {
3116 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3117 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003118 err_code |= ERR_ALERT | ERR_FATAL;
3119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003121
3122 err = invalid_char(args[1]);
3123 if (err) {
3124 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3125 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003126 err_code |= ERR_ALERT | ERR_FATAL;
3127 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003128 }
3129
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003130 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003131 struct sockaddr_in *sk;
3132
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003133 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3134 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3135 err_code |= ERR_ALERT | ERR_ABORT;
3136 goto out;
3137 }
3138
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003139 /* the servers are linked backwards first */
3140 newsrv->next = curproxy->srv;
3141 curproxy->srv = newsrv;
3142 newsrv->proxy = curproxy;
3143 newsrv->conf.file = file;
3144 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003146 LIST_INIT(&newsrv->pendconns);
3147 do_check = 0;
3148 newsrv->state = SRV_RUNNING; /* early server setup */
3149 newsrv->last_change = now.tv_sec;
3150 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003152 /* several ways to check the port component :
3153 * - IP => port=+0, relative
3154 * - IP: => port=+0, relative
3155 * - IP:N => port=N, absolute
3156 * - IP:+N => port=+N, relative
3157 * - IP:-N => port=-N, relative
3158 */
3159 raddr = strdup(args[2]);
3160 rport = strchr(raddr, ':');
3161 if (rport) {
3162 *rport++ = 0;
3163 realport = atol(rport);
3164 if (!isdigit((unsigned char)*rport))
3165 newsrv->state |= SRV_MAPPORTS;
3166 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003168
Willy Tarreaud5191e72010-02-09 20:50:45 +01003169 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003170 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003171 if (!sk) {
3172 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3173 err_code |= ERR_ALERT | ERR_FATAL;
3174 goto out;
3175 }
3176 newsrv->addr = *sk;
3177 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003178
3179 newsrv->check_port = curproxy->defsrv.check_port;
3180 newsrv->inter = curproxy->defsrv.inter;
3181 newsrv->fastinter = curproxy->defsrv.fastinter;
3182 newsrv->downinter = curproxy->defsrv.downinter;
3183 newsrv->rise = curproxy->defsrv.rise;
3184 newsrv->fall = curproxy->defsrv.fall;
3185 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3186 newsrv->minconn = curproxy->defsrv.minconn;
3187 newsrv->maxconn = curproxy->defsrv.maxconn;
3188 newsrv->slowstart = curproxy->defsrv.slowstart;
3189 newsrv->onerror = curproxy->defsrv.onerror;
3190 newsrv->consecutive_errors_limit
3191 = curproxy->defsrv.consecutive_errors_limit;
3192 newsrv->uweight = newsrv->iweight
3193 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003195 newsrv->curfd = -1; /* no health-check in progress */
3196 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003198 cur_arg = 3;
3199 } else {
3200 newsrv = &curproxy->defsrv;
3201 cur_arg = 1;
3202 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003203
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003205 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003206 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003207
3208 if (!*args[cur_arg + 1]) {
3209 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3210 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003213 }
3214
3215 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003216 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003217
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003218 if (newsrv->puid <= 0) {
3219 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003220 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003221 err_code |= ERR_ALERT | ERR_FATAL;
3222 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003223 }
3224
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003225 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3226 if (node) {
3227 struct server *target = container_of(node, struct server, conf.id);
3228 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3229 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3230 err_code |= ERR_ALERT | ERR_FATAL;
3231 goto out;
3232 }
3233 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003234 cur_arg += 2;
3235 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003236 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003237 newsrv->cookie = strdup(args[cur_arg + 1]);
3238 newsrv->cklen = strlen(args[cur_arg + 1]);
3239 cur_arg += 2;
3240 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003241 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003242 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3243 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3244 cur_arg += 2;
3245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003246 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003247 if (!*args[cur_arg + 1]) {
3248 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3249 file, linenum, args[cur_arg]);
3250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
3252 }
3253
Willy Tarreaubaaee002006-06-26 02:48:02 +02003254 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003255 if (newsrv->rise <= 0) {
3256 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3257 file, linenum, args[cur_arg]);
3258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
3260 }
3261
Willy Tarreau96839092010-03-29 10:02:24 +02003262 if (newsrv->health)
3263 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 cur_arg += 2;
3265 }
3266 else if (!strcmp(args[cur_arg], "fall")) {
3267 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003268
3269 if (!*args[cur_arg + 1]) {
3270 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3271 file, linenum, args[cur_arg]);
3272 err_code |= ERR_ALERT | ERR_FATAL;
3273 goto out;
3274 }
3275
3276 if (newsrv->fall <= 0) {
3277 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3278 file, linenum, args[cur_arg]);
3279 err_code |= ERR_ALERT | ERR_FATAL;
3280 goto out;
3281 }
3282
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 cur_arg += 2;
3284 }
3285 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003286 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3287 if (err) {
3288 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3289 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003292 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003293 if (val <= 0) {
3294 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3295 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003296 err_code |= ERR_ALERT | ERR_FATAL;
3297 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003298 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003299 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 cur_arg += 2;
3301 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003302 else if (!strcmp(args[cur_arg], "fastinter")) {
3303 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3304 if (err) {
3305 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3306 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003307 err_code |= ERR_ALERT | ERR_FATAL;
3308 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003309 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003310 if (val <= 0) {
3311 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3312 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003315 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003316 newsrv->fastinter = val;
3317 cur_arg += 2;
3318 }
3319 else if (!strcmp(args[cur_arg], "downinter")) {
3320 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3321 if (err) {
3322 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3323 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003324 err_code |= ERR_ALERT | ERR_FATAL;
3325 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003326 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003327 if (val <= 0) {
3328 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3329 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003330 err_code |= ERR_ALERT | ERR_FATAL;
3331 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003332 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003333 newsrv->downinter = val;
3334 cur_arg += 2;
3335 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003336 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003337 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3338 if (!sk) {
3339 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3340 err_code |= ERR_ALERT | ERR_FATAL;
3341 goto out;
3342 }
3343 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003344 cur_arg += 2;
3345 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003346 else if (!strcmp(args[cur_arg], "port")) {
3347 newsrv->check_port = atol(args[cur_arg + 1]);
3348 cur_arg += 2;
3349 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003350 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 newsrv->state |= SRV_BACKUP;
3352 cur_arg ++;
3353 }
3354 else if (!strcmp(args[cur_arg], "weight")) {
3355 int w;
3356 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003357 if (w < 0 || w > 256) {
3358 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003360 err_code |= ERR_ALERT | ERR_FATAL;
3361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003363 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 cur_arg += 2;
3365 }
3366 else if (!strcmp(args[cur_arg], "minconn")) {
3367 newsrv->minconn = atol(args[cur_arg + 1]);
3368 cur_arg += 2;
3369 }
3370 else if (!strcmp(args[cur_arg], "maxconn")) {
3371 newsrv->maxconn = atol(args[cur_arg + 1]);
3372 cur_arg += 2;
3373 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003374 else if (!strcmp(args[cur_arg], "maxqueue")) {
3375 newsrv->maxqueue = atol(args[cur_arg + 1]);
3376 cur_arg += 2;
3377 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003378 else if (!strcmp(args[cur_arg], "slowstart")) {
3379 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003380 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003381 if (err) {
3382 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3383 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003386 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01003387 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01003388 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3389 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003392 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003393 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003394 cur_arg += 2;
3395 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003396 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003397
3398 if (!*args[cur_arg + 1]) {
3399 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3400 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003401 err_code |= ERR_ALERT | ERR_FATAL;
3402 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003403 }
3404
3405 newsrv->trackit = strdup(args[cur_arg + 1]);
3406
3407 cur_arg += 2;
3408 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003409 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 global.maxsock++;
3411 do_check = 1;
3412 cur_arg += 1;
3413 }
Willy Tarreau96839092010-03-29 10:02:24 +02003414 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
3415 newsrv->state |= SRV_MAINTAIN;
3416 newsrv->state &= ~SRV_RUNNING;
3417 newsrv->health = 0;
3418 cur_arg += 1;
3419 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003420 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003421 if (!strcmp(args[cur_arg + 1], "none"))
3422 newsrv->observe = HANA_OBS_NONE;
3423 else if (!strcmp(args[cur_arg + 1], "layer4"))
3424 newsrv->observe = HANA_OBS_LAYER4;
3425 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3426 if (curproxy->mode != PR_MODE_HTTP) {
3427 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3428 file, linenum, args[cur_arg + 1]);
3429 err_code |= ERR_ALERT;
3430 }
3431 newsrv->observe = HANA_OBS_LAYER7;
3432 }
3433 else {
3434 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3435 "'l4events', 'http-responses' but get '%s'\n",
3436 file, linenum, args[cur_arg], args[cur_arg + 1]);
3437 err_code |= ERR_ALERT | ERR_FATAL;
3438 goto out;
3439 }
3440
3441 cur_arg += 2;
3442 }
3443 else if (!strcmp(args[cur_arg], "on-error")) {
3444 if (!strcmp(args[cur_arg + 1], "fastinter"))
3445 newsrv->onerror = HANA_ONERR_FASTINTER;
3446 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3447 newsrv->onerror = HANA_ONERR_FAILCHK;
3448 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3449 newsrv->onerror = HANA_ONERR_SUDDTH;
3450 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3451 newsrv->onerror = HANA_ONERR_MARKDWN;
3452 else {
3453 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3454 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3455 file, linenum, args[cur_arg], args[cur_arg + 1]);
3456 err_code |= ERR_ALERT | ERR_FATAL;
3457 goto out;
3458 }
3459
3460 cur_arg += 2;
3461 }
3462 else if (!strcmp(args[cur_arg], "error-limit")) {
3463 if (!*args[cur_arg + 1]) {
3464 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3465 file, linenum, args[cur_arg]);
3466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
3468 }
3469
3470 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3471
3472 if (newsrv->consecutive_errors_limit <= 0) {
3473 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3474 file, linenum, args[cur_arg]);
3475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
3477 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01003478 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003479 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003480 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003481 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003482 struct sockaddr_in *sk;
3483
Willy Tarreaubaaee002006-06-26 02:48:02 +02003484 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003485#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003486 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003487 file, linenum, "source", "usesrc");
3488#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003489 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003490 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003491#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003494 }
3495 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003496 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3497 if (!sk) {
3498 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
3501 }
3502 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003503
3504 if (port_low != port_high) {
3505 int i;
3506 if (port_low <= 0 || port_low > 65535 ||
3507 port_high <= 0 || port_high > 65535 ||
3508 port_low > port_high) {
3509 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3510 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003513 }
3514 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3515 for (i = 0; i < newsrv->sport_range->size; i++)
3516 newsrv->sport_range->ports[i] = port_low + i;
3517 }
3518
Willy Tarreaubaaee002006-06-26 02:48:02 +02003519 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003520 while (*(args[cur_arg])) {
3521 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003522#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3523#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003524 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3525 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3526 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003527 err_code |= ERR_ALERT | ERR_FATAL;
3528 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003529 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003530#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003531 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003532 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01003533 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003536 }
3537 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003538 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003539 newsrv->state |= SRV_TPROXY_CLI;
3540 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003541 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003542 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02003543 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
3544 char *name, *end;
3545
3546 name = args[cur_arg+1] + 7;
3547 while (isspace(*name))
3548 name++;
3549
3550 end = name;
3551 while (*end && !isspace(*end) && *end != ',' && *end != ')')
3552 end++;
3553
3554 newsrv->state &= ~SRV_TPROXY_MASK;
3555 newsrv->state |= SRV_TPROXY_DYN;
3556 newsrv->bind_hdr_name = calloc(1, end - name + 1);
3557 newsrv->bind_hdr_len = end - name;
3558 memcpy(newsrv->bind_hdr_name, name, end - name);
3559 newsrv->bind_hdr_name[end-name] = '\0';
3560 newsrv->bind_hdr_occ = -1;
3561
3562 /* now look for an occurrence number */
3563 while (isspace(*end))
3564 end++;
3565 if (*end == ',') {
3566 end++;
3567 name = end;
3568 if (*end == '-')
3569 end++;
3570 while (isdigit(*end))
3571 end++;
3572 newsrv->bind_hdr_occ = strl2ic(name, end-name);
3573 }
3574
3575 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
3576 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
3577 " occurrences values smaller than %d.\n",
3578 file, linenum, MAX_HDR_HISTORY);
3579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
3581 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01003582 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003583 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3584 if (!sk) {
3585 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
3588 }
3589 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003590 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003591 }
3592 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003593#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003594 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003595#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003596 cur_arg += 2;
3597 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003598#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003599 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003600 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003603#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3604 } /* "usesrc" */
3605
3606 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3607#ifdef SO_BINDTODEVICE
3608 if (!*args[cur_arg + 1]) {
3609 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3610 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003611 err_code |= ERR_ALERT | ERR_FATAL;
3612 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003613 }
3614 if (newsrv->iface_name)
3615 free(newsrv->iface_name);
3616
3617 newsrv->iface_name = strdup(args[cur_arg + 1]);
3618 newsrv->iface_len = strlen(newsrv->iface_name);
3619 global.last_checks |= LSTCHK_NETADM;
3620#else
3621 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3622 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003623 err_code |= ERR_ALERT | ERR_FATAL;
3624 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003625#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003626 cur_arg += 2;
3627 continue;
3628 }
3629 /* this keyword in not an option of "source" */
3630 break;
3631 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003633 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003634 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3635 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003636 err_code |= ERR_ALERT | ERR_FATAL;
3637 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003638 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003639 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003640 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02003641 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', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003642 file, linenum, newsrv->id);
3643 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003644 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 +01003645 file, linenum);
3646
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 }
3650 }
3651
3652 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003653 if (newsrv->trackit) {
3654 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3655 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003658 }
3659
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003660 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3661 newsrv->check_port = newsrv->check_addr.sin_port;
3662
Willy Tarreaubaaee002006-06-26 02:48:02 +02003663 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3664 newsrv->check_port = realport; /* by default */
3665 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003666 /* not yet valid, because no port was set on
3667 * the server either. We'll check if we have
3668 * a known port on the first listener.
3669 */
3670 struct listener *l;
3671 l = curproxy->listen;
3672 if (l) {
3673 int port;
3674 port = (l->addr.ss_family == AF_INET6)
3675 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3676 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3677 newsrv->check_port = port;
3678 }
3679 }
3680 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003681 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3682 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003683 err_code |= ERR_ALERT | ERR_FATAL;
3684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003685 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003686
Cyril Bontéc9f825f2010-03-17 18:56:31 +01003687 /* Allocate buffer for partial check results... */
3688 if ((newsrv->check_data = calloc(BUFSIZE, sizeof(char))) == NULL) {
3689 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
3690 err_code |= ERR_ALERT | ERR_ABORT;
3691 goto out;
3692 }
3693
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003694 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003695 newsrv->state |= SRV_CHECKED;
3696 }
3697
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003698 if (!defsrv) {
3699 if (newsrv->state & SRV_BACKUP)
3700 curproxy->srv_bck++;
3701 else
3702 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003703
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003704 newsrv->prev_state = newsrv->state;
3705 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003706 }
3707 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003708 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003709 int facility;
3710
3711 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3712 curproxy->logfac1 = global.logfac1;
3713 curproxy->logsrv1 = global.logsrv1;
3714 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003715 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003716 curproxy->logfac2 = global.logfac2;
3717 curproxy->logsrv2 = global.logsrv2;
3718 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003719 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003720 }
3721 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003722 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723
3724 facility = get_log_facility(args[2]);
3725 if (facility < 0) {
3726 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3727 exit(1);
3728 }
3729
3730 level = 7; /* max syslog level = debug */
3731 if (*(args[3])) {
3732 level = get_log_level(args[3]);
3733 if (level < 0) {
3734 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3735 exit(1);
3736 }
3737 }
3738
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003739 minlvl = 0; /* limit syslog level to this level (emerg) */
3740 if (*(args[4])) {
3741 minlvl = get_log_level(args[4]);
3742 if (level < 0) {
3743 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3744 exit(1);
3745 }
3746 }
3747
Robert Tsai81ae1952007-12-05 10:47:29 +01003748 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003749 struct sockaddr_un *sk = str2sun(args[1]);
3750 if (!sk) {
3751 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
3752 args[1], (int)sizeof(sk->sun_path) - 1);
3753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
3755 }
3756 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003757 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01003758 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003759 struct sockaddr_in *sk = str2sa(args[1]);
3760 if (!sk) {
3761 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
3764 }
3765 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003766 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01003767 if (!logsrv.u.in.sin_port) {
3768 logsrv.u.in.sin_port =
3769 htons(SYSLOG_PORT);
3770 }
3771 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003772
3773 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003774 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003775 curproxy->logfac1 = facility;
3776 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003777 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 }
3779 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003780 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 curproxy->logfac2 = facility;
3782 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003783 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003784 }
3785 else {
3786 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 }
3790 }
3791 else {
3792 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3793 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_ALERT | ERR_FATAL;
3795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003796 }
3797 }
3798 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003799 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003800 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003801
Willy Tarreau977b8e42006-12-29 14:19:17 +01003802 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003804
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003806 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3807 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003811
3812 /* we must first clear any optional default setting */
3813 curproxy->options &= ~PR_O_TPXY_MASK;
3814 free(curproxy->iface_name);
3815 curproxy->iface_name = NULL;
3816 curproxy->iface_len = 0;
3817
Willy Tarreaud5191e72010-02-09 20:50:45 +01003818 sk = str2sa(args[1]);
3819 if (!sk) {
3820 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
3823 }
3824 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003826
3827 cur_arg = 2;
3828 while (*(args[cur_arg])) {
3829 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003830#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3831#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003832 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3833 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3834 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003837 }
3838#endif
3839 if (!*args[cur_arg + 1]) {
3840 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3841 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003842 err_code |= ERR_ALERT | ERR_FATAL;
3843 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003844 }
3845
3846 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003847 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003848 curproxy->options |= PR_O_TPXY_CLI;
3849 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02003850 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003851 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02003852 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
3853 char *name, *end;
3854
3855 name = args[cur_arg+1] + 7;
3856 while (isspace(*name))
3857 name++;
3858
3859 end = name;
3860 while (*end && !isspace(*end) && *end != ',' && *end != ')')
3861 end++;
3862
3863 curproxy->options &= ~PR_O_TPXY_MASK;
3864 curproxy->options |= PR_O_TPXY_DYN;
3865 curproxy->bind_hdr_name = calloc(1, end - name + 1);
3866 curproxy->bind_hdr_len = end - name;
3867 memcpy(curproxy->bind_hdr_name, name, end - name);
3868 curproxy->bind_hdr_name[end-name] = '\0';
3869 curproxy->bind_hdr_occ = -1;
3870
3871 /* now look for an occurrence number */
3872 while (isspace(*end))
3873 end++;
3874 if (*end == ',') {
3875 end++;
3876 name = end;
3877 if (*end == '-')
3878 end++;
3879 while (isdigit(*end))
3880 end++;
3881 curproxy->bind_hdr_occ = strl2ic(name, end-name);
3882 }
3883
3884 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
3885 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
3886 " occurrences values smaller than %d.\n",
3887 file, linenum, MAX_HDR_HISTORY);
3888 err_code |= ERR_ALERT | ERR_FATAL;
3889 goto out;
3890 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003891 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003892 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3893 if (!sk) {
3894 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3895 err_code |= ERR_ALERT | ERR_FATAL;
3896 goto out;
3897 }
3898 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003899 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003900 }
3901 global.last_checks |= LSTCHK_NETADM;
3902#if !defined(CONFIG_HAP_LINUX_TPROXY)
3903 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003904#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003905#else /* no TPROXY support */
3906 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003907 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003908 err_code |= ERR_ALERT | ERR_FATAL;
3909 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003910#endif
3911 cur_arg += 2;
3912 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003913 }
3914
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003915 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3916#ifdef SO_BINDTODEVICE
3917 if (!*args[cur_arg + 1]) {
3918 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3919 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003920 err_code |= ERR_ALERT | ERR_FATAL;
3921 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003922 }
3923 if (curproxy->iface_name)
3924 free(curproxy->iface_name);
3925
3926 curproxy->iface_name = strdup(args[cur_arg + 1]);
3927 curproxy->iface_len = strlen(curproxy->iface_name);
3928 global.last_checks |= LSTCHK_NETADM;
3929#else
3930 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3931 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003932 err_code |= ERR_ALERT | ERR_FATAL;
3933 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003934#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003935 cur_arg += 2;
3936 continue;
3937 }
3938 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3939 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003944 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3945 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3946 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003949 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003951 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003952 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3953 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003954 err_code |= ERR_ALERT | ERR_FATAL;
3955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003956 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003957
3958 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3959 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003960 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003961 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003963 }
3964 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003965 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3966 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003967 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003968 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003970 }
3971 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003972 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3973 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003974 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003975 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003977 }
3978 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003979 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3980 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003981 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003982 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003984 }
3985 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003986 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3987 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003988 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003989 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003991 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003992 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003993 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3994 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003995 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003996 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003997 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003998 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003999 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004000 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4001 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004002 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004003 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004004 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004005 }
4006 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004007 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4008 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004009 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004010 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004011 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004012 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004013 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004014 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4016 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004019 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004020
4021 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4022 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004023 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004024 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004026 }
4027 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004028 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4029 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004030 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004031 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004033 }
4034 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004035 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4036 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004037 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004038 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004040 }
4041 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004042 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4043 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004044 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004045 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004047 }
4048 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004049 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4050 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004051 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004052 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004054 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004055 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004056 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4057 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004058 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004059 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004060 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004062 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004063 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004064
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 if (curproxy == &defproxy) {
4066 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004070 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004071 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004072
Willy Tarreaubaaee002006-06-26 02:48:02 +02004073 if (*(args[1]) == 0) {
4074 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004075 err_code |= ERR_ALERT | ERR_FATAL;
4076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004077 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004078
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004079 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4080 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4081 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4082 file, linenum, args[0]);
4083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
4085 }
4086 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4087 }
4088 else if (*args[2]) {
4089 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4090 file, linenum, args[0], args[2]);
4091 err_code |= ERR_ALERT | ERR_FATAL;
4092 goto out;
4093 }
4094
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004095 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004096 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004097 wl->s = strdup(args[1]);
4098 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004099 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004100 }
4101 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004102 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004103 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4104 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004105 err_code |= ERR_ALERT | ERR_FATAL;
4106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004107 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004108
Willy Tarreauade5ec42010-01-28 19:33:49 +01004109 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4110 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004111 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004112 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004114 }
4115 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004116 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4117 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004118 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004119 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004121 }
4122 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004123 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4124 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004125 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004126 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004128 }
4129 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004130 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004131 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4132 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004135 }
4136
Willy Tarreauade5ec42010-01-28 19:33:49 +01004137 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4138 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004139 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004140 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004142 }
4143 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004144 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4145 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004146 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004147 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004149 }
4150 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004151 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4152 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004153 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004154 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 }
4157 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004158 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004159
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160 if (curproxy == &defproxy) {
4161 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004164 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004165 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004166 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004167
Willy Tarreaubaaee002006-06-26 02:48:02 +02004168 if (*(args[1]) == 0) {
4169 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004170 err_code |= ERR_ALERT | ERR_FATAL;
4171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004172 }
4173
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004174 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4175 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4176 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4177 file, linenum, args[0]);
4178 err_code |= ERR_ALERT | ERR_FATAL;
4179 goto out;
4180 }
4181 err_code |= warnif_cond_requires_req(cond, file, linenum);
4182 }
4183 else if (*args[2]) {
4184 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4185 file, linenum, args[0], args[2]);
4186 err_code |= ERR_ALERT | ERR_FATAL;
4187 goto out;
4188 }
4189
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004190 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004191 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004192 wl->s = strdup(args[1]);
4193 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004194 }
4195 else if (!strcmp(args[0], "errorloc") ||
4196 !strcmp(args[0], "errorloc302") ||
4197 !strcmp(args[0], "errorloc303")) { /* error location */
4198 int errnum, errlen;
4199 char *err;
4200
Willy Tarreau977b8e42006-12-29 14:19:17 +01004201 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004202 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004203
Willy Tarreaubaaee002006-06-26 02:48:02 +02004204 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004205 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004206 err_code |= ERR_ALERT | ERR_FATAL;
4207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004208 }
4209
4210 errnum = atol(args[1]);
4211 if (!strcmp(args[0], "errorloc303")) {
4212 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4213 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4214 } else {
4215 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4216 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4217 }
4218
Willy Tarreau0f772532006-12-23 20:51:41 +01004219 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4220 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004221 chunk_destroy(&curproxy->errmsg[rc]);
4222 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004223 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004225 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004226
4227 if (rc >= HTTP_ERR_SIZE) {
4228 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4229 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004230 free(err);
4231 }
4232 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004233 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4234 int errnum, errlen, fd;
4235 char *err;
4236 struct stat stat;
4237
4238 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004239 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004240
4241 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004242 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004243 err_code |= ERR_ALERT | ERR_FATAL;
4244 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004245 }
4246
4247 fd = open(args[2], O_RDONLY);
4248 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4249 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4250 file, linenum, args[2], args[1]);
4251 if (fd >= 0)
4252 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004253 err_code |= ERR_ALERT | ERR_FATAL;
4254 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004255 }
4256
Willy Tarreau27a674e2009-08-17 07:23:33 +02004257 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004258 errlen = stat.st_size;
4259 } else {
4260 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004261 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004262 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004263 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004264 }
4265
4266 err = malloc(errlen); /* malloc() must succeed during parsing */
4267 errnum = read(fd, err, errlen);
4268 if (errnum != errlen) {
4269 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4270 file, linenum, args[2], args[1]);
4271 close(fd);
4272 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004273 err_code |= ERR_ALERT | ERR_FATAL;
4274 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004275 }
4276 close(fd);
4277
4278 errnum = atol(args[1]);
4279 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4280 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004281 chunk_destroy(&curproxy->errmsg[rc]);
4282 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004283 break;
4284 }
4285 }
4286
4287 if (rc >= HTTP_ERR_SIZE) {
4288 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4289 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004290 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004291 free(err);
4292 }
4293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004294 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004295 struct cfg_kw_list *kwl;
4296 int index;
4297
4298 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4299 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4300 if (kwl->kw[index].section != CFG_LISTEN)
4301 continue;
4302 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4303 /* prepare error message just in case */
4304 snprintf(trash, sizeof(trash),
4305 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004306 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4307 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004308 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004309 err_code |= ERR_ALERT | ERR_FATAL;
4310 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004311 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004312 else if (rc > 0) {
4313 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004314 err_code |= ERR_WARN;
4315 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004316 }
Willy Tarreau93893792009-07-23 13:19:11 +02004317 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004318 }
4319 }
4320 }
4321
Willy Tarreau6daf3432008-01-22 16:44:08 +01004322 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004325 }
Willy Tarreau93893792009-07-23 13:19:11 +02004326 out:
4327 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004328}
4329
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004330int
4331cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4332{
4333
4334 int err_code = 0;
4335 const char *err;
4336
4337 if (!strcmp(args[0], "userlist")) { /* new userlist */
4338 struct userlist *newul;
4339
4340 if (!*args[1]) {
4341 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4342 file, linenum, args[0]);
4343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
4345 }
4346
4347 err = invalid_char(args[1]);
4348 if (err) {
4349 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4350 file, linenum, *err, args[0], args[1]);
4351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
4353 }
4354
4355 for (newul = userlist; newul; newul = newul->next)
4356 if (!strcmp(newul->name, args[1])) {
4357 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4358 file, linenum, args[1]);
4359 err_code |= ERR_WARN;
4360 goto out;
4361 }
4362
4363 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4364 if (!newul) {
4365 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4366 err_code |= ERR_ALERT | ERR_ABORT;
4367 goto out;
4368 }
4369
4370 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4371 newul->name = strdup(args[1]);
4372
4373 if (!newul->groupusers | !newul->name) {
4374 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4375 err_code |= ERR_ALERT | ERR_ABORT;
4376 goto out;
4377 }
4378
4379 newul->next = userlist;
4380 userlist = newul;
4381
4382 } else if (!strcmp(args[0], "group")) { /* new group */
4383 int cur_arg, i;
4384 const char *err;
4385
4386 if (!*args[1]) {
4387 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4388 file, linenum, args[0]);
4389 err_code |= ERR_ALERT | ERR_FATAL;
4390 goto out;
4391 }
4392
4393 err = invalid_char(args[1]);
4394 if (err) {
4395 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4396 file, linenum, *err, args[0], args[1]);
4397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
4399 }
4400
4401 for(i = 0; i < userlist->grpcnt; i++)
4402 if (!strcmp(userlist->groups[i], args[1])) {
4403 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4404 file, linenum, args[1], userlist->name);
4405 err_code |= ERR_ALERT;
4406 goto out;
4407 }
4408
4409 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4410 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4411 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4412 err_code |= ERR_ALERT | ERR_FATAL;
4413 goto out;
4414 }
4415
4416 cur_arg = 2;
4417
4418 while (*args[cur_arg]) {
4419 if (!strcmp(args[cur_arg], "users")) {
4420 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4421 cur_arg += 2;
4422 continue;
4423 } else {
4424 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4425 file, linenum, args[0]);
4426 err_code |= ERR_ALERT | ERR_FATAL;
4427 goto out;
4428 }
4429 }
4430
4431 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4432 } else if (!strcmp(args[0], "user")) { /* new user */
4433 struct auth_users *newuser;
4434 int cur_arg;
4435
4436 if (!*args[1]) {
4437 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4438 file, linenum, args[0]);
4439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
4441 }
4442
4443 for (newuser = userlist->users; newuser; newuser = newuser->next)
4444 if (!strcmp(newuser->user, args[1])) {
4445 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4446 file, linenum, args[1], userlist->name);
4447 err_code |= ERR_ALERT;
4448 goto out;
4449 }
4450
4451 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4452 if (!newuser) {
4453 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4454 err_code |= ERR_ALERT | ERR_ABORT;
4455 goto out;
4456 }
4457
4458 newuser->user = strdup(args[1]);
4459
4460 newuser->next = userlist->users;
4461 userlist->users = newuser;
4462
4463 cur_arg = 2;
4464
4465 while (*args[cur_arg]) {
4466 if (!strcmp(args[cur_arg], "password")) {
4467#ifndef CONFIG_HAP_CRYPT
4468 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4469 file, linenum);
4470 err_code |= ERR_ALERT;
4471#endif
4472 newuser->pass = strdup(args[cur_arg + 1]);
4473 cur_arg += 2;
4474 continue;
4475 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4476 newuser->pass = strdup(args[cur_arg + 1]);
4477 newuser->flags |= AU_O_INSECURE;
4478 cur_arg += 2;
4479 continue;
4480 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01004481 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004482 cur_arg += 2;
4483 continue;
4484 } else {
4485 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4486 file, linenum, args[0]);
4487 err_code |= ERR_ALERT | ERR_FATAL;
4488 goto out;
4489 }
4490 }
4491 } else {
4492 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4493 err_code |= ERR_ALERT | ERR_FATAL;
4494 }
4495
4496out:
4497 return err_code;
4498}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004499
4500/*
4501 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004502 * Returns the error code, 0 if OK, or any combination of :
4503 * - ERR_ABORT: must abort ASAP
4504 * - ERR_FATAL: we can continue parsing but not start the service
4505 * - ERR_WARN: a warning has been emitted
4506 * - ERR_ALERT: an alert has been emitted
4507 * Only the two first ones can stop processing, the two others are just
4508 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004510int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004511{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004512 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004513 FILE *f;
4514 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004515 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004516 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004517
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518 if ((f=fopen(file,"r")) == NULL)
4519 return -1;
4520
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004521 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004522 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004523 char *end;
4524 char *args[MAX_LINE_ARGS + 1];
4525 char *line = thisline;
4526
Willy Tarreaubaaee002006-06-26 02:48:02 +02004527 linenum++;
4528
4529 end = line + strlen(line);
4530
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004531 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4532 /* Check if we reached the limit and the last char is not \n.
4533 * Watch out for the last line without the terminating '\n'!
4534 */
4535 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004536 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004537 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004538 }
4539
Willy Tarreaubaaee002006-06-26 02:48:02 +02004540 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004541 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004542 line++;
4543
4544 arg = 0;
4545 args[arg] = line;
4546
4547 while (*line && arg < MAX_LINE_ARGS) {
4548 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4549 * C equivalent value. Other combinations left unchanged (eg: \1).
4550 */
4551 if (*line == '\\') {
4552 int skip = 0;
4553 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4554 *line = line[1];
4555 skip = 1;
4556 }
4557 else if (line[1] == 'r') {
4558 *line = '\r';
4559 skip = 1;
4560 }
4561 else if (line[1] == 'n') {
4562 *line = '\n';
4563 skip = 1;
4564 }
4565 else if (line[1] == 't') {
4566 *line = '\t';
4567 skip = 1;
4568 }
4569 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004570 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004571 unsigned char hex1, hex2;
4572 hex1 = toupper(line[2]) - '0';
4573 hex2 = toupper(line[3]) - '0';
4574 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4575 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4576 *line = (hex1<<4) + hex2;
4577 skip = 3;
4578 }
4579 else {
4580 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004581 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 }
4583 }
4584 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004585 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004586 end -= skip;
4587 }
4588 line++;
4589 }
4590 else if (*line == '#' || *line == '\n' || *line == '\r') {
4591 /* end of string, end of loop */
4592 *line = 0;
4593 break;
4594 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004595 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004597 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004598 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004599 line++;
4600 args[++arg] = line;
4601 }
4602 else {
4603 line++;
4604 }
4605 }
4606
4607 /* empty line */
4608 if (!**args)
4609 continue;
4610
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004611 if (*line) {
4612 /* we had to stop due to too many args.
4613 * Let's terminate the string, print the offending part then cut the
4614 * last arg.
4615 */
4616 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4617 line++;
4618 *line = '\0';
4619
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004620 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004621 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004622 err_code |= ERR_ALERT | ERR_FATAL;
4623 args[arg] = line;
4624 }
4625
Willy Tarreau540abe42007-05-02 20:50:16 +02004626 /* zero out remaining args and ensure that at least one entry
4627 * is zeroed out.
4628 */
4629 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004630 args[arg] = line;
4631 }
4632
Willy Tarreau3842f002009-06-14 11:39:52 +02004633 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004634 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004635 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004636 for (arg=0; *args[arg+1]; arg++)
4637 args[arg] = args[arg+1]; // shift args after inversion
4638 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004639 else if (!strcmp(args[0], "default")) {
4640 kwm = KWM_DEF;
4641 for (arg=0; *args[arg+1]; arg++)
4642 args[arg] = args[arg+1]; // shift args after inversion
4643 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004644
Willy Tarreau3842f002009-06-14 11:39:52 +02004645 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4646 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004647 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004648 }
4649
Willy Tarreau977b8e42006-12-29 14:19:17 +01004650 if (!strcmp(args[0], "listen") ||
4651 !strcmp(args[0], "frontend") ||
4652 !strcmp(args[0], "backend") ||
4653 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004654 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004655 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004656 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004657 cursection = strdup(args[0]);
4658 }
4659 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004660 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004661 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004662 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004663 } else if (!strcmp(args[0], "userlist")) {
4664 confsect = CFG_USERLIST;
4665 free(cursection);
4666 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004668 /* else it's a section keyword */
4669
4670 switch (confsect) {
4671 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004672 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004673 break;
4674 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004675 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004676 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004677 case CFG_USERLIST:
4678 err_code |= cfg_parse_users(file, linenum, args, kwm);
4679 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004680 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004681 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004682 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004683 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004684
4685 if (err_code & ERR_ABORT)
4686 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004688 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004689 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004690 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004691 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004692}
4693
Willy Tarreaubb925012009-07-23 13:36:36 +02004694/*
4695 * Returns the error code, 0 if OK, or any combination of :
4696 * - ERR_ABORT: must abort ASAP
4697 * - ERR_FATAL: we can continue parsing but not start the service
4698 * - ERR_WARN: a warning has been emitted
4699 * - ERR_ALERT: an alert has been emitted
4700 * Only the two first ones can stop processing, the two others are just
4701 * indicators.
4702 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004703int check_config_validity()
4704{
4705 int cfgerr = 0;
4706 struct proxy *curproxy = NULL;
4707 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004708 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004709 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004710 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004711
4712 /*
4713 * Now, check for the integrity of all that we have collected.
4714 */
4715
4716 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004717 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004718
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004719 /* first, we will invert the proxy list order */
4720 curproxy = NULL;
4721 while (proxy) {
4722 struct proxy *next;
4723
4724 next = proxy->next;
4725 proxy->next = curproxy;
4726 curproxy = proxy;
4727 if (!next)
4728 break;
4729 proxy = next;
4730 }
4731
Willy Tarreaubaaee002006-06-26 02:48:02 +02004732 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004733 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004734 err_code |= ERR_ALERT | ERR_FATAL;
4735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004736 }
4737
4738 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004739 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004740 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02004741 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004742 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004743 unsigned int next_id;
4744
4745 if (!curproxy->uuid) {
4746 /* proxy ID not set, use automatic numbering with first
4747 * spare entry starting with next_pxid.
4748 */
4749 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4750 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4751 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004752 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01004753 next_pxid++;
4754
Willy Tarreau55ea7572007-06-17 19:56:27 +02004755
Willy Tarreaubaaee002006-06-26 02:48:02 +02004756 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004757 /* ensure we don't keep listeners uselessly bound */
4758 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004759 curproxy = curproxy->next;
4760 continue;
4761 }
4762
Willy Tarreauff01a212009-03-15 13:46:16 +01004763 switch (curproxy->mode) {
4764 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004765 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004766 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004767 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4768 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004769 cfgerr++;
4770 }
4771
4772 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004773 Warning("config : servers will be ignored for %s '%s'.\n",
4774 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004775 break;
4776
4777 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004778 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004779 break;
4780
4781 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004782 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004783 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004784 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4785 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004786 cfgerr++;
4787 }
4788 break;
4789 }
4790
4791 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004792 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4793 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004794 cfgerr++;
4795 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004796
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004797 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004798 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004799 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004800 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4801 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004802 cfgerr++;
4803 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004804#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004805 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004806 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4807 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004808 cfgerr++;
4809 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004810#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004811 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004812 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4813 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004814 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004815 }
4816 }
4817 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4818 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4819 /* If no LB algo is set in a backend, and we're not in
4820 * transparent mode, dispatch mode nor proxy mode, we
4821 * want to use balance roundrobin by default.
4822 */
4823 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4824 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004825 }
4826 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004827
Willy Tarreau82936582007-11-30 15:20:09 +01004828 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4829 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004830 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4831 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004832 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004833 }
4834
Willy Tarreauef781042010-01-27 11:53:01 +01004835 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4836 curproxy->options &= ~PR_O2_CHK_SNDST;
4837 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4838 "send-state", proxy_type_str(curproxy), curproxy->id);
4839 err_code |= ERR_WARN;
4840 }
4841
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004842 /* if a default backend was specified, let's find it */
4843 if (curproxy->defbe.name) {
4844 struct proxy *target;
4845
Alex Williams96532db2009-11-01 21:27:13 -05004846 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004847 if (!target) {
4848 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4849 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004850 cfgerr++;
4851 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004852 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4853 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004854 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004855 } else {
4856 free(curproxy->defbe.name);
4857 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004858 /* we force the backend to be present on at least all of
4859 * the frontend's processes.
4860 */
4861 target->bind_proc = curproxy->bind_proc ?
4862 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863 }
4864 }
4865
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004866 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004867 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4868 /* map jump target for ACT_SETBE in req_rep chain */
4869 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004870 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004871 struct proxy *target;
4872
Willy Tarreaua496b602006-12-17 23:15:24 +01004873 if (exp->action != ACT_SETBE)
4874 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004875
Alex Williams96532db2009-11-01 21:27:13 -05004876 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004877 if (!target) {
4878 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4879 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004880 cfgerr++;
4881 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004882 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4883 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004884 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004885 } else {
4886 free((void *)exp->replace);
4887 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004888 /* we force the backend to be present on at least all of
4889 * the frontend's processes.
4890 */
4891 target->bind_proc = curproxy->bind_proc ?
4892 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004893 }
4894 }
4895 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004896
4897 /* find the target proxy for 'use_backend' rules */
4898 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004899 struct proxy *target;
4900
Alex Williams96532db2009-11-01 21:27:13 -05004901 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004902
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004903 if (!target) {
4904 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4905 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004906 cfgerr++;
4907 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004908 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4909 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004910 cfgerr++;
4911 } else {
4912 free((void *)rule->be.name);
4913 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004914 /* we force the backend to be present on at least all of
4915 * the frontend's processes.
4916 */
4917 target->bind_proc = curproxy->bind_proc ?
4918 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004919 }
4920 }
4921
Emeric Brunb982a3d2010-01-04 15:45:53 +01004922 /* find the target table for 'stick' rules */
4923 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4924 struct proxy *target;
4925
Emeric Brun1d33b292010-01-04 15:47:17 +01004926 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4927 if (mrule->flags & STK_IS_STORE)
4928 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4929
Emeric Brunb982a3d2010-01-04 15:45:53 +01004930 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02004931 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004932 else
4933 target = curproxy;
4934
4935 if (!target) {
4936 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4937 curproxy->id, mrule->table.name);
4938 cfgerr++;
4939 }
4940 else if (target->table.size == 0) {
4941 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4942 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4943 cfgerr++;
4944 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02004945 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004946 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4947 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4948 cfgerr++;
4949 }
4950 else {
4951 free((void *)mrule->table.name);
4952 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02004953 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004954 }
4955 }
4956
4957 /* find the target table for 'store response' rules */
4958 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4959 struct proxy *target;
4960
Emeric Brun1d33b292010-01-04 15:47:17 +01004961 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4962
Emeric Brunb982a3d2010-01-04 15:45:53 +01004963 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02004964 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004965 else
4966 target = curproxy;
4967
4968 if (!target) {
4969 Alert("Proxy '%s': unable to find store table '%s'.\n",
4970 curproxy->id, mrule->table.name);
4971 cfgerr++;
4972 }
4973 else if (target->table.size == 0) {
4974 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4975 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4976 cfgerr++;
4977 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02004978 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004979 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4980 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4981 cfgerr++;
4982 }
4983 else {
4984 free((void *)mrule->table.name);
4985 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02004986 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004987 }
4988 }
4989
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02004990 /* find the target table for 'tcp-request' layer 4 rules */
4991 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
4992 struct proxy *target;
4993
Willy Tarreau56123282010-08-06 19:06:56 +02004994 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02004995 continue;
4996
4997 if (trule->act_prm.trk_ctr.table.n)
4998 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
4999 else
5000 target = curproxy;
5001
5002 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005003 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5004 curproxy->id, trule->act_prm.trk_ctr.table.n,
5005 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005006 cfgerr++;
5007 }
5008 else if (target->table.size == 0) {
5009 Alert("Proxy '%s': table '%s' used but not configured.\n",
5010 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5011 cfgerr++;
5012 }
5013 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005014 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 +02005015 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5016 cfgerr++;
5017 }
5018 else {
5019 free(trule->act_prm.trk_ctr.table.n);
5020 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005021 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005022 * to pass a list of counters to track and allocate them right here using
5023 * stktable_alloc_data_type().
5024 */
5025 }
5026 }
5027
Willy Tarreaud1f96522010-08-03 19:34:32 +02005028 /* find the target table for 'tcp-request' layer 6 rules */
5029 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5030 struct proxy *target;
5031
Willy Tarreau56123282010-08-06 19:06:56 +02005032 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005033 continue;
5034
5035 if (trule->act_prm.trk_ctr.table.n)
5036 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5037 else
5038 target = curproxy;
5039
5040 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005041 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5042 curproxy->id, trule->act_prm.trk_ctr.table.n,
5043 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005044 cfgerr++;
5045 }
5046 else if (target->table.size == 0) {
5047 Alert("Proxy '%s': table '%s' used but not configured.\n",
5048 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5049 cfgerr++;
5050 }
5051 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005052 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 +02005053 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5054 cfgerr++;
5055 }
5056 else {
5057 free(trule->act_prm.trk_ctr.table.n);
5058 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005059 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005060 * to pass a list of counters to track and allocate them right here using
5061 * stktable_alloc_data_type().
5062 */
5063 }
5064 }
5065
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005066 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
5067 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005068 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5069 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5070 "proxy", curproxy->id);
5071 cfgerr++;
5072 goto out_uri_auth_compat;
5073 }
5074
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005075 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005076 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005077 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005078 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005079
Willy Tarreau95fa4692010-02-01 13:05:50 +01005080 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5081 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005082
5083 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005084 uri_auth_compat_req[i++] = "realm";
5085 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5086 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005087
Willy Tarreau95fa4692010-02-01 13:05:50 +01005088 uri_auth_compat_req[i++] = "unless";
5089 uri_auth_compat_req[i++] = "{";
5090 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5091 uri_auth_compat_req[i++] = "}";
5092 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005093
Willy Tarreau95fa4692010-02-01 13:05:50 +01005094 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5095 if (!req_acl) {
5096 cfgerr++;
5097 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005098 }
5099
Willy Tarreau95fa4692010-02-01 13:05:50 +01005100 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
5101
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005102 if (curproxy->uri_auth->auth_realm) {
5103 free(curproxy->uri_auth->auth_realm);
5104 curproxy->uri_auth->auth_realm = NULL;
5105 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005106
5107 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005108 }
5109out_uri_auth_compat:
5110
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005111 cfgerr += acl_find_targets(curproxy);
5112
Willy Tarreau2738a142006-07-08 17:28:09 +02005113 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005114 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005115 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005116 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005117 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005118 " | While not properly invalid, you will certainly encounter various problems\n"
5119 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005120 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005121 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005122 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005123 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005124
Willy Tarreau1fa31262007-12-03 00:36:16 +01005125 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5126 * We must still support older configurations, so let's find out whether those
5127 * parameters have been set or must be copied from contimeouts.
5128 */
5129 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005130 if (!curproxy->timeout.tarpit ||
5131 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005132 /* tarpit timeout not set. We search in the following order:
5133 * default.tarpit, curr.connect, default.connect.
5134 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005135 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005136 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005137 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005138 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005139 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005140 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005141 }
5142 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005143 (!curproxy->timeout.queue ||
5144 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005145 /* queue timeout not set. We search in the following order:
5146 * default.queue, curr.connect, default.connect.
5147 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005148 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005149 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005150 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005151 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005152 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005153 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005154 }
5155 }
5156
Willy Tarreau07a54902010-03-29 18:33:29 +02005157 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005158 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5159 curproxy->check_req = (char *)malloc(curproxy->check_len);
5160 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005161 }
5162
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005163 /* The small pools required for the capture lists */
5164 if (curproxy->nb_req_cap)
5165 curproxy->req_cap_pool = create_pool("ptrcap",
5166 curproxy->nb_req_cap * sizeof(char *),
5167 MEM_F_SHARED);
5168 if (curproxy->nb_rsp_cap)
5169 curproxy->rsp_cap_pool = create_pool("ptrcap",
5170 curproxy->nb_rsp_cap * sizeof(char *),
5171 MEM_F_SHARED);
5172
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005173 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5174 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5175 MEM_F_SHARED);
5176
Willy Tarreau86034312006-12-29 00:10:33 +01005177 /* for backwards compatibility with "listen" instances, if
5178 * fullconn is not set but maxconn is set, then maxconn
5179 * is used.
5180 */
5181 if (!curproxy->fullconn)
5182 curproxy->fullconn = curproxy->maxconn;
5183
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 /* first, we will invert the servers list order */
5185 newsrv = NULL;
5186 while (curproxy->srv) {
5187 struct server *next;
5188
5189 next = curproxy->srv->next;
5190 curproxy->srv->next = newsrv;
5191 newsrv = curproxy->srv;
5192 if (!next)
5193 break;
5194 curproxy->srv = next;
5195 }
5196
Willy Tarreaudd701652010-05-25 23:03:02 +02005197 /* assign automatic UIDs to servers which don't have one yet */
5198 next_id = 1;
5199 newsrv = curproxy->srv;
5200 while (newsrv != NULL) {
5201 if (!newsrv->puid) {
5202 /* server ID not set, use automatic numbering with first
5203 * spare entry starting with next_svid.
5204 */
5205 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5206 newsrv->conf.id.key = newsrv->puid = next_id;
5207 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
5208 }
5209 next_id++;
5210 newsrv = newsrv->next;
5211 }
5212
Willy Tarreau20697042007-11-15 23:26:18 +01005213 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01005214 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005215
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005216 /* We have to initialize the server lookup mechanism depending
5217 * on what LB algorithm was choosen.
5218 */
5219
5220 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
5221 switch (curproxy->lbprm.algo & BE_LB_KIND) {
5222 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02005223 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
5224 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5225 init_server_map(curproxy);
5226 } else {
5227 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
5228 fwrr_init_server_groups(curproxy);
5229 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005230 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005231
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005232 case BE_LB_KIND_LC:
5233 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01005234 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005235 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005236
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005237 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005238 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
5239 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
5240 chash_init_server_tree(curproxy);
5241 } else {
5242 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5243 init_server_map(curproxy);
5244 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005245 break;
5246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005247
5248 if (curproxy->options & PR_O_LOGASAP)
5249 curproxy->to_log &= ~LW_BYTES;
5250
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02005251 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
5252 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
5253 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
5254 proxy_type_str(curproxy), curproxy->id);
5255 err_code |= ERR_WARN;
5256 }
5257
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005258 if (curproxy->mode != PR_MODE_HTTP) {
5259 int optnum;
5260
5261 if (curproxy->options & PR_O_COOK_ANY) {
5262 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
5263 proxy_type_str(curproxy), curproxy->id);
5264 err_code |= ERR_WARN;
5265 }
5266
5267 if (curproxy->uri_auth) {
5268 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
5269 proxy_type_str(curproxy), curproxy->id);
5270 err_code |= ERR_WARN;
5271 curproxy->uri_auth = NULL;
5272 }
5273
5274 if (curproxy->options & PR_O_FWDFOR) {
5275 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5276 "forwardfor", proxy_type_str(curproxy), curproxy->id);
5277 err_code |= ERR_WARN;
5278 curproxy->options &= ~PR_O_FWDFOR;
5279 }
5280
5281 if (curproxy->options & PR_O_ORGTO) {
5282 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5283 "originalto", proxy_type_str(curproxy), curproxy->id);
5284 err_code |= ERR_WARN;
5285 curproxy->options &= ~PR_O_ORGTO;
5286 }
5287
5288 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
5289 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
5290 (curproxy->cap & cfg_opts[optnum].cap) &&
5291 (curproxy->options & cfg_opts[optnum].val)) {
5292 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5293 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
5294 err_code |= ERR_WARN;
5295 curproxy->options &= ~cfg_opts[optnum].val;
5296 }
5297 }
5298
5299 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
5300 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
5301 (curproxy->cap & cfg_opts2[optnum].cap) &&
5302 (curproxy->options2 & cfg_opts2[optnum].val)) {
5303 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5304 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
5305 err_code |= ERR_WARN;
5306 curproxy->options2 &= ~cfg_opts2[optnum].val;
5307 }
5308 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005309
Willy Tarreauefa5f512010-03-30 20:13:29 +02005310#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005311 if (curproxy->bind_hdr_occ) {
5312 curproxy->bind_hdr_occ = 0;
5313 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
5314 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
5315 err_code |= ERR_WARN;
5316 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005317#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005318 }
5319
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01005321 * ensure that we're not cross-dressing a TCP server into HTTP.
5322 */
5323 newsrv = curproxy->srv;
5324 while (newsrv != NULL) {
5325 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005326 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
5327 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005328 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005329 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005330
Willy Tarreauefa5f512010-03-30 20:13:29 +02005331#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005332 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
5333 newsrv->bind_hdr_occ = 0;
5334 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
5335 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
5336 err_code |= ERR_WARN;
5337 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005338#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01005339 newsrv = newsrv->next;
5340 }
5341
5342 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02005343 * If this server supports a maxconn parameter, it needs a dedicated
5344 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005345 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005346 */
5347 newsrv = curproxy->srv;
5348 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01005349 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005350 /* Only 'minconn' was specified, or it was higher than or equal
5351 * to 'maxconn'. Let's turn this into maxconn and clean it, as
5352 * this will avoid further useless expensive computations.
5353 */
5354 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01005355 } else if (newsrv->maxconn && !newsrv->minconn) {
5356 /* minconn was not specified, so we set it to maxconn */
5357 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005358 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005359 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
5360 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005361 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005362 }
5363
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005364 if (newsrv->trackit) {
5365 struct proxy *px;
5366 struct server *srv;
5367 char *pname, *sname;
5368
5369 pname = newsrv->trackit;
5370 sname = strrchr(pname, '/');
5371
5372 if (sname)
5373 *sname++ = '\0';
5374 else {
5375 sname = pname;
5376 pname = NULL;
5377 }
5378
5379 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005380 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005381 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005382 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5383 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005384 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005385 cfgerr++;
5386 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005387 }
5388 } else
5389 px = curproxy;
5390
5391 srv = findserver(px, sname);
5392 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005393 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5394 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005395 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005396 cfgerr++;
5397 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005398 }
5399
5400 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005401 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005402 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005403 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005404 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005405 cfgerr++;
5406 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005407 }
5408
5409 if (curproxy != px &&
5410 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005411 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005412 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005413 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005414 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005415 cfgerr++;
5416 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005417 }
5418
5419 newsrv->tracked = srv;
5420 newsrv->tracknext = srv->tracknext;
5421 srv->tracknext = newsrv;
5422
5423 free(newsrv->trackit);
5424 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005425 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005426 newsrv = newsrv->next;
5427 }
5428
Willy Tarreauc1a21672009-08-16 22:37:44 +02005429 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02005430 curproxy->accept = frontend_accept;
5431
Willy Tarreauc1a21672009-08-16 22:37:44 +02005432 if (curproxy->tcp_req.inspect_delay ||
5433 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02005434 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005435
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005436 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005437 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005438 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005439 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005440
5441 /* both TCP and HTTP must check switching rules */
5442 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5443 }
5444
5445 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02005446 if (curproxy->tcp_req.inspect_delay ||
5447 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5448 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
5449
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005450 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005451 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005452 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005453 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005454
5455 /* If the backend does requires RDP cookie persistence, we have to
5456 * enable the corresponding analyser.
5457 */
5458 if (curproxy->options2 & PR_O2_RDPC_PRST)
5459 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5460 }
5461
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005462 listener = NULL;
5463 while (curproxy->listen) {
5464 struct listener *next;
5465
5466 next = curproxy->listen->next;
5467 curproxy->listen->next = listener;
5468 listener = curproxy->listen;
5469
5470 if (!next)
5471 break;
5472
5473 curproxy->listen = next;
5474 }
5475
Willy Tarreaue6b98942007-10-29 01:09:36 +01005476 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005477 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005478 listener = curproxy->listen;
5479 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005480 if (!listener->luid) {
5481 /* listener ID not set, use automatic numbering with first
5482 * spare entry starting with next_luid.
5483 */
5484 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5485 listener->conf.id.key = listener->luid = next_id;
5486 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005487 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005488 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005489
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005490 /* enable separate counters */
5491 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5492 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5493 if (!listener->name) {
5494 sprintf(trash, "sock-%d", listener->luid);
5495 listener->name = strdup(trash);
5496 }
5497 }
5498
Willy Tarreaue6b98942007-10-29 01:09:36 +01005499 if (curproxy->options & PR_O_TCP_NOLING)
5500 listener->options |= LI_O_NOLINGER;
5501 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005502 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005503 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02005504 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02005505 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005506 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005507 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005508
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02005509 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
5510 listener->options |= LI_O_TCP_RULES;
5511
Willy Tarreaude3041d2010-05-31 10:56:17 +02005512 if (curproxy->mon_mask.s_addr)
5513 listener->options |= LI_O_CHK_MONNET;
5514
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005515 /* smart accept mode is automatic in HTTP mode */
5516 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5517 (curproxy->mode == PR_MODE_HTTP &&
5518 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5519 listener->options |= LI_O_NOQUICKACK;
5520
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005521 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005522 listener = listener->next;
5523 }
5524
Willy Tarreaubaaee002006-06-26 02:48:02 +02005525 curproxy = curproxy->next;
5526 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005527
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005528 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5529 struct auth_users *curuser;
5530 int g;
5531
5532 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5533 unsigned int group_mask = 0;
5534 char *group = NULL;
5535
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005536 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005537 continue;
5538
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005539 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005540
5541 for (g = 0; g < curuserlist->grpcnt; g++)
5542 if (!strcmp(curuserlist->groups[g], group))
5543 break;
5544
5545 if (g == curuserlist->grpcnt) {
5546 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5547 curuserlist->name, group, curuser->user);
5548 err_code |= ERR_ALERT | ERR_FATAL;
5549 goto out;
5550 }
5551
5552 group_mask |= (1 << g);
5553 }
5554
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005555 free(curuser->u.groups);
5556 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005557 }
5558
5559 for (g = 0; g < curuserlist->grpcnt; g++) {
5560 char *user = NULL;
5561
5562 if (!curuserlist->groupusers[g])
5563 continue;
5564
5565 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5566 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5567 if (!strcmp(curuser->user, user))
5568 break;
5569
5570 if (!curuser) {
5571 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5572 curuserlist->name, user, curuserlist->groups[g]);
5573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
5575 }
5576
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005577 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005578 }
5579
5580 free(curuserlist->groupusers[g]);
5581 }
5582
5583 free(curuserlist->groupusers);
5584
5585#ifdef DEBUG_AUTH
5586 for (g = 0; g < curuserlist->grpcnt; g++) {
5587 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5588
5589 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5590 if (curuser->group_mask & (1 << g))
5591 fprintf(stderr, " %s", curuser->user);
5592 }
5593
5594 fprintf(stderr, "\n");
5595 }
5596#endif
5597
5598 }
5599
Willy Tarreau056f5682010-06-06 15:51:11 +02005600 /* initialize stick-tables on backend capable proxies. This must not
5601 * be done earlier because the data size may be discovered while parsing
5602 * other proxies.
5603 */
5604 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005605 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02005606
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005607 /*
5608 * Recount currently required checks.
5609 */
5610
5611 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5612 int optnum;
5613
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005614 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5615 if (curproxy->options & cfg_opts[optnum].val)
5616 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005617
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005618 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5619 if (curproxy->options2 & cfg_opts2[optnum].val)
5620 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005621 }
5622
Willy Tarreaubb925012009-07-23 13:36:36 +02005623 if (cfgerr > 0)
5624 err_code |= ERR_ALERT | ERR_FATAL;
5625 out:
5626 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005627}
5628
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005629/*
5630 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5631 * parsing sessions.
5632 */
5633void cfg_register_keywords(struct cfg_kw_list *kwl)
5634{
5635 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5636}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005637
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005638/*
5639 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5640 */
5641void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5642{
5643 LIST_DEL(&kwl->list);
5644 LIST_INIT(&kwl->list);
5645}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005646
5647/*
5648 * Local variables:
5649 * c-indent-level: 8
5650 * c-basic-offset: 8
5651 * End:
5652 */