blob: 871310b66b2cda70fd1b5bd0fbe9b831638ab230 [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 Tarreaue6b98942007-10-29 01:09:36 +0100270 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271 } /* end for(port) */
272 } /* end while(next) */
273 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200274 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275 fail:
276 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200277 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200278}
279
Willy Tarreau977b8e42006-12-29 14:19:17 +0100280/*
281 * Sends a warning if proxy <proxy> does not have at least one of the
282 * capabilities in <cap>. An optionnal <hint> may be added at the end
283 * of the warning to help the user. Returns 1 if a warning was emitted
284 * or 0 if the condition is valid.
285 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100286int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100287{
288 char *msg;
289
290 switch (cap) {
291 case PR_CAP_BE: msg = "no backend"; break;
292 case PR_CAP_FE: msg = "no frontend"; break;
293 case PR_CAP_RS: msg = "no ruleset"; break;
294 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
295 default: msg = "not enough"; break;
296 }
297
298 if (!(proxy->cap & cap)) {
299 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100300 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100301 return 1;
302 }
303 return 0;
304}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200305
Willy Tarreau61d18892009-03-31 10:49:21 +0200306/* Report a warning if a rule is placed after a 'block' rule.
307 * Return 1 if the warning has been emitted, otherwise 0.
308 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100309int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200310{
311 if (!LIST_ISEMPTY(&proxy->block_cond)) {
312 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
313 file, line, arg);
314 return 1;
315 }
316 return 0;
317}
318
319/* Report a warning if a rule is placed after a reqrewrite rule.
320 * Return 1 if the warning has been emitted, otherwise 0.
321 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100322int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200323{
324 if (proxy->req_exp) {
325 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
326 file, line, arg);
327 return 1;
328 }
329 return 0;
330}
331
332/* Report a warning if a rule is placed after a reqadd rule.
333 * Return 1 if the warning has been emitted, otherwise 0.
334 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100335int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200336{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100337 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200338 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
339 file, line, arg);
340 return 1;
341 }
342 return 0;
343}
344
345/* Report a warning if a rule is placed after a redirect rule.
346 * Return 1 if the warning has been emitted, otherwise 0.
347 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100348int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200349{
350 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
351 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
352 file, line, arg);
353 return 1;
354 }
355 return 0;
356}
357
358/* Report a warning if a rule is placed after a 'use_backend' rule.
359 * Return 1 if the warning has been emitted, otherwise 0.
360 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100361int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200362{
363 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
364 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
365 file, line, arg);
366 return 1;
367 }
368 return 0;
369}
370
371/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100372int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200373{
374 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
375 warnif_rule_after_reqadd(proxy, file, line, arg) ||
376 warnif_rule_after_redirect(proxy, file, line, arg) ||
377 warnif_rule_after_use_backend(proxy, file, line, arg);
378}
379
380/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100381int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200382{
383 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
384 warnif_rule_after_redirect(proxy, file, line, arg) ||
385 warnif_rule_after_use_backend(proxy, file, line, arg);
386}
387
388/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100389int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200390{
391 return warnif_rule_after_redirect(proxy, file, line, arg) ||
392 warnif_rule_after_use_backend(proxy, file, line, arg);
393}
394
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100395/* Report it if a request ACL condition uses some response-only parameters. It
396 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
397 * Note that <cond> may be NULL and then will be ignored.
398 */
399static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
400{
401 struct acl *acl;
402
403 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
404 return 0;
405
406 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
407 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
408 file, line, acl ? acl->name : "(unknown)");
409 return ERR_WARN;
410}
411
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100412/* Report it if a request ACL condition uses some request-only volatile parameters.
413 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
414 * Note that <cond> may be NULL and then will be ignored.
415 */
416static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
417{
418 struct acl *acl;
419
420 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
421 return 0;
422
423 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
424 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
425 file, line, acl ? acl->name : "(unknown)");
426 return ERR_WARN;
427}
428
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100429
Willy Tarreaubaaee002006-06-26 02:48:02 +0200430/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200431 * parse a line in a <global> section. Returns the error code, 0 if OK, or
432 * any combination of :
433 * - ERR_ABORT: must abort ASAP
434 * - ERR_FATAL: we can continue parsing but not start the service
435 * - ERR_WARN: a warning has been emitted
436 * - ERR_ALERT: an alert has been emitted
437 * Only the two first ones can stop processing, the two others are just
438 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200439 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200440int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200441{
Willy Tarreau058e9072009-07-20 09:30:05 +0200442 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200443
444 if (!strcmp(args[0], "global")) { /* new section */
445 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200446 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200447 }
448 else if (!strcmp(args[0], "daemon")) {
449 global.mode |= MODE_DAEMON;
450 }
451 else if (!strcmp(args[0], "debug")) {
452 global.mode |= MODE_DEBUG;
453 }
454 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100455 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200456 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200457 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100458 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200459 }
460 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100461 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200462 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100464 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200465 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100466 else if (!strcmp(args[0], "nosplice")) {
467 global.tune.options &= ~GTUNE_USE_SPLICE;
468 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200469 else if (!strcmp(args[0], "quiet")) {
470 global.mode |= MODE_QUIET;
471 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200472 else if (!strcmp(args[0], "tune.maxpollevents")) {
473 if (global.tune.maxpollevents != 0) {
474 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200475 err_code |= ERR_ALERT;
476 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200477 }
478 if (*(args[1]) == 0) {
479 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200480 err_code |= ERR_ALERT | ERR_FATAL;
481 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200482 }
483 global.tune.maxpollevents = atol(args[1]);
484 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100485 else if (!strcmp(args[0], "tune.maxaccept")) {
486 if (global.tune.maxaccept != 0) {
487 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200488 err_code |= ERR_ALERT;
489 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100490 }
491 if (*(args[1]) == 0) {
492 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200493 err_code |= ERR_ALERT | ERR_FATAL;
494 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100495 }
496 global.tune.maxaccept = atol(args[1]);
497 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200498 else if (!strcmp(args[0], "tune.bufsize")) {
499 if (*(args[1]) == 0) {
500 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
501 err_code |= ERR_ALERT | ERR_FATAL;
502 goto out;
503 }
504 global.tune.bufsize = atol(args[1]);
505 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
506 global.tune.maxrewrite = global.tune.bufsize / 2;
507 }
508 else if (!strcmp(args[0], "tune.maxrewrite")) {
509 if (*(args[1]) == 0) {
510 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
511 err_code |= ERR_ALERT | ERR_FATAL;
512 goto out;
513 }
514 global.tune.maxrewrite = atol(args[1]);
515 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
516 global.tune.maxrewrite = global.tune.bufsize / 2;
517 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100518 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
519 if (global.tune.client_rcvbuf != 0) {
520 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT;
522 goto out;
523 }
524 if (*(args[1]) == 0) {
525 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
526 err_code |= ERR_ALERT | ERR_FATAL;
527 goto out;
528 }
529 global.tune.client_rcvbuf = atol(args[1]);
530 }
531 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
532 if (global.tune.server_rcvbuf != 0) {
533 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
534 err_code |= ERR_ALERT;
535 goto out;
536 }
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
539 err_code |= ERR_ALERT | ERR_FATAL;
540 goto out;
541 }
542 global.tune.server_rcvbuf = atol(args[1]);
543 }
544 else if (!strcmp(args[0], "tune.sndbuf.client")) {
545 if (global.tune.client_sndbuf != 0) {
546 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
547 err_code |= ERR_ALERT;
548 goto out;
549 }
550 if (*(args[1]) == 0) {
551 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
552 err_code |= ERR_ALERT | ERR_FATAL;
553 goto out;
554 }
555 global.tune.client_sndbuf = atol(args[1]);
556 }
557 else if (!strcmp(args[0], "tune.sndbuf.server")) {
558 if (global.tune.server_sndbuf != 0) {
559 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
560 err_code |= ERR_ALERT;
561 goto out;
562 }
563 if (*(args[1]) == 0) {
564 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
565 err_code |= ERR_ALERT | ERR_FATAL;
566 goto out;
567 }
568 global.tune.server_sndbuf = atol(args[1]);
569 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200570 else if (!strcmp(args[0], "uid")) {
571 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200572 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200573 err_code |= ERR_ALERT;
574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575 }
576 if (*(args[1]) == 0) {
577 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200578 err_code |= ERR_ALERT | ERR_FATAL;
579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 }
581 global.uid = atol(args[1]);
582 }
583 else if (!strcmp(args[0], "gid")) {
584 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200585 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200586 err_code |= ERR_ALERT;
587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200588 }
589 if (*(args[1]) == 0) {
590 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200591 err_code |= ERR_ALERT | ERR_FATAL;
592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200593 }
594 global.gid = atol(args[1]);
595 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200596 /* user/group name handling */
597 else if (!strcmp(args[0], "user")) {
598 struct passwd *ha_user;
599 if (global.uid != 0) {
600 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200601 err_code |= ERR_ALERT;
602 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200603 }
604 errno = 0;
605 ha_user = getpwnam(args[1]);
606 if (ha_user != NULL) {
607 global.uid = (int)ha_user->pw_uid;
608 }
609 else {
610 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 +0200611 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200612 }
613 }
614 else if (!strcmp(args[0], "group")) {
615 struct group *ha_group;
616 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200617 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200618 err_code |= ERR_ALERT;
619 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200620 }
621 errno = 0;
622 ha_group = getgrnam(args[1]);
623 if (ha_group != NULL) {
624 global.gid = (int)ha_group->gr_gid;
625 }
626 else {
627 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 +0200628 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200629 }
630 }
631 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632 else if (!strcmp(args[0], "nbproc")) {
633 if (global.nbproc != 0) {
634 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200635 err_code |= ERR_ALERT;
636 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200637 }
638 if (*(args[1]) == 0) {
639 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200640 err_code |= ERR_ALERT | ERR_FATAL;
641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 }
643 global.nbproc = atol(args[1]);
644 }
645 else if (!strcmp(args[0], "maxconn")) {
646 if (global.maxconn != 0) {
647 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200648 err_code |= ERR_ALERT;
649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200650 }
651 if (*(args[1]) == 0) {
652 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200653 err_code |= ERR_ALERT | ERR_FATAL;
654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200655 }
656 global.maxconn = atol(args[1]);
657#ifdef SYSTEM_MAXCONN
658 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
659 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);
660 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200661 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 }
663#endif /* SYSTEM_MAXCONN */
664 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100665 else if (!strcmp(args[0], "maxpipes")) {
666 if (global.maxpipes != 0) {
667 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200668 err_code |= ERR_ALERT;
669 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100670 }
671 if (*(args[1]) == 0) {
672 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT | ERR_FATAL;
674 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100675 }
676 global.maxpipes = atol(args[1]);
677 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200678 else if (!strcmp(args[0], "ulimit-n")) {
679 if (global.rlimit_nofile != 0) {
680 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200681 err_code |= ERR_ALERT;
682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200683 }
684 if (*(args[1]) == 0) {
685 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 }
689 global.rlimit_nofile = atol(args[1]);
690 }
691 else if (!strcmp(args[0], "chroot")) {
692 if (global.chroot != NULL) {
693 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200694 err_code |= ERR_ALERT;
695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696 }
697 if (*(args[1]) == 0) {
698 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 err_code |= ERR_ALERT | ERR_FATAL;
700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 }
702 global.chroot = strdup(args[1]);
703 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200704 else if (!strcmp(args[0], "description")) {
705 int i, len=0;
706 char *d;
707
708 if (!*args[1]) {
709 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
710 file, linenum, args[0]);
711 err_code |= ERR_ALERT | ERR_FATAL;
712 goto out;
713 }
714
715 for(i=1; *args[i]; i++)
716 len += strlen(args[i])+1;
717
718 if (global.desc)
719 free(global.desc);
720
721 global.desc = d = (char *)calloc(1, len);
722
723 d += sprintf(d, "%s", args[1]);
724 for(i=2; *args[i]; i++)
725 d += sprintf(d, " %s", args[i]);
726 }
727 else if (!strcmp(args[0], "node")) {
728 int i;
729 char c;
730
731 for (i=0; args[1][i]; i++) {
732 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100733 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
734 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200735 break;
736 }
737
738 if (!i || args[1][i]) {
739 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
740 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
741 file, linenum, args[0]);
742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
744 }
745
746 if (global.node)
747 free(global.node);
748
749 global.node = strdup(args[1]);
750 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751 else if (!strcmp(args[0], "pidfile")) {
752 if (global.pidfile != NULL) {
753 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200754 err_code |= ERR_ALERT;
755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200756 }
757 if (*(args[1]) == 0) {
758 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200759 err_code |= ERR_ALERT | ERR_FATAL;
760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200761 }
762 global.pidfile = strdup(args[1]);
763 }
764 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100765 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200766 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200767
768 if (*(args[1]) == 0 || *(args[2]) == 0) {
769 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200772 }
773
774 facility = get_log_facility(args[2]);
775 if (facility < 0) {
776 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200777 err_code |= ERR_ALERT | ERR_FATAL;
778 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200779 }
780
781 level = 7; /* max syslog level = debug */
782 if (*(args[3])) {
783 level = get_log_level(args[3]);
784 if (level < 0) {
785 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200786 err_code |= ERR_ALERT | ERR_FATAL;
787 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200788 }
789 }
790
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200791 minlvl = 0; /* limit syslog level to this level (emerg) */
792 if (*(args[4])) {
793 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200794 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200795 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200796 err_code |= ERR_ALERT | ERR_FATAL;
797 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200798 }
799 }
800
Robert Tsai81ae1952007-12-05 10:47:29 +0100801 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100802 struct sockaddr_un *sk = str2sun(args[1]);
803 if (!sk) {
804 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
805 args[1], (int)sizeof(sk->sun_path) - 1);
806 err_code |= ERR_ALERT | ERR_FATAL;
807 goto out;
808 }
809 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100810 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100811 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100812 struct sockaddr_in *sk = str2sa(args[1]);
813 if (!sk) {
814 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
815 err_code |= ERR_ALERT | ERR_FATAL;
816 goto out;
817 }
818 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100819 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100820 if (!logsrv.u.in.sin_port)
821 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
822 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823
824 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100825 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200826 global.logfac1 = facility;
827 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200828 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200829 }
830 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100831 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 global.logfac2 = facility;
833 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200834 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200835 }
836 else {
837 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200838 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200840 }
841 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
842 if (global.spread_checks != 0) {
843 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200844 err_code |= ERR_ALERT;
845 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200846 }
847 if (*(args[1]) == 0) {
848 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200849 err_code |= ERR_ALERT | ERR_FATAL;
850 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200851 }
852 global.spread_checks = atol(args[1]);
853 if (global.spread_checks < 0 || global.spread_checks > 50) {
854 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200855 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200856 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200857 }
858 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200859 struct cfg_kw_list *kwl;
860 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200861 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200862
863 list_for_each_entry(kwl, &cfg_keywords.list, list) {
864 for (index = 0; kwl->kw[index].kw != NULL; index++) {
865 if (kwl->kw[index].section != CFG_GLOBAL)
866 continue;
867 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
868 /* prepare error message just in case */
869 snprintf(trash, sizeof(trash),
870 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200871 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
872 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200873 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200874 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200875 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200876 else if (rc > 0) {
877 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200878 err_code |= ERR_WARN;
879 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200880 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200881 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200882 }
883 }
884 }
885
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200887 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200889
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 out:
891 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892}
893
Willy Tarreau97cb7802010-01-03 20:23:58 +0100894/* Perform the most basic initialization of a proxy :
895 * memset(), list_init(*), reset_timeouts(*).
896 */
897static void init_new_proxy(struct proxy *p)
898{
899 memset(p, 0, sizeof(struct proxy));
900 LIST_INIT(&p->pendconns);
901 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +0100902 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100903 LIST_INIT(&p->block_cond);
904 LIST_INIT(&p->redirect_rules);
905 LIST_INIT(&p->mon_fail_cond);
906 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +0200907 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100908 LIST_INIT(&p->sticking_rules);
909 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100910 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +0200911 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100912 LIST_INIT(&p->req_add);
913 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100914
915 /* Timeouts are defined as -1 */
916 proxy_reset_timeouts(p);
917}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200919void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100921 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 defproxy.mode = PR_MODE_TCP;
923 defproxy.state = PR_STNEW;
924 defproxy.maxconn = cfg_maxpconn;
925 defproxy.conn_retries = CONN_RETRIES;
926 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100927
928 defproxy.defsrv.inter = DEF_CHKINTR;
929 defproxy.defsrv.fastinter = 0;
930 defproxy.defsrv.downinter = 0;
931 defproxy.defsrv.rise = DEF_RISETIME;
932 defproxy.defsrv.fall = DEF_FALLTIME;
933 defproxy.defsrv.check_port = 0;
934 defproxy.defsrv.maxqueue = 0;
935 defproxy.defsrv.minconn = 0;
936 defproxy.defsrv.maxconn = 0;
937 defproxy.defsrv.slowstart = 0;
938 defproxy.defsrv.onerror = DEF_HANA_ONERR;
939 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
940 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200941}
942
Willy Tarreauade5ec42010-01-28 19:33:49 +0100943
944static int create_cond_regex_rule(const char *file, int line,
945 struct proxy *px, int dir, int action, int flags,
946 const char *cmd, const char *reg, const char *repl,
947 const char **cond_start)
948{
949 regex_t *preg = NULL;
950 const char *err;
951 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +0100952 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +0100953
954 if (px == &defproxy) {
955 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto err;
958 }
959
960 if (*reg == 0) {
961 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto err;
964 }
965
966 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
967 err_code |= ERR_WARN;
968
Willy Tarreau5321c422010-01-28 20:35:13 +0100969 if (cond_start &&
970 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
971 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
972 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
973 file, line, cmd);
974 err_code |= ERR_ALERT | ERR_FATAL;
975 goto err;
976 }
977 }
978 else if (cond_start && **cond_start) {
979 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
980 file, line, cmd, *cond_start);
981 err_code |= ERR_ALERT | ERR_FATAL;
982 goto err;
983 }
984
985 if (dir == ACL_DIR_REQ)
986 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100987 else
988 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +0100989
Willy Tarreauade5ec42010-01-28 19:33:49 +0100990 preg = calloc(1, sizeof(regex_t));
991 if (!preg) {
992 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
993 err_code = ERR_ALERT | ERR_FATAL;
994 goto err;
995 }
996
997 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
998 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
999 err_code = ERR_ALERT | ERR_FATAL;
1000 goto err;
1001 }
1002
1003 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001004 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001005 if (repl && err) {
1006 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1007 file, line, cmd, *err);
1008 err_code |= ERR_ALERT | ERR_FATAL;
1009 goto err;
1010 }
1011
1012 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1013 err_code |= ERR_WARN;
1014
1015 return err_code;
1016 err:
1017 free(preg);
1018 return err_code;
1019}
1020
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001022 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001023 * Returns the error code, 0 if OK, or any combination of :
1024 * - ERR_ABORT: must abort ASAP
1025 * - ERR_FATAL: we can continue parsing but not start the service
1026 * - ERR_WARN: a warning has been emitted
1027 * - ERR_ALERT: an alert has been emitted
1028 * Only the two first ones can stop processing, the two others are just
1029 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001030 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001031int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001032{
1033 static struct proxy *curproxy = NULL;
1034 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001035 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001036 int rc;
1037 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001038 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001039 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001040
Willy Tarreau977b8e42006-12-29 14:19:17 +01001041 if (!strcmp(args[0], "listen"))
1042 rc = PR_CAP_LISTEN;
1043 else if (!strcmp(args[0], "frontend"))
1044 rc = PR_CAP_FE | PR_CAP_RS;
1045 else if (!strcmp(args[0], "backend"))
1046 rc = PR_CAP_BE | PR_CAP_RS;
1047 else if (!strcmp(args[0], "ruleset"))
1048 rc = PR_CAP_RS;
1049 else
1050 rc = PR_CAP_NONE;
1051
1052 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 if (!*args[1]) {
1054 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1055 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1056 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001057 err_code |= ERR_ALERT | ERR_ABORT;
1058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001060
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001061 err = invalid_char(args[1]);
1062 if (err) {
1063 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1064 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001065 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001066 }
1067
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001068 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1069 /*
1070 * If there are two proxies with the same name only following
1071 * combinations are allowed:
1072 *
1073 * listen backend frontend ruleset
1074 * listen - - - -
1075 * backend - - OK -
1076 * frontend - OK - -
1077 * ruleset - - - -
1078 */
1079
1080 if (!strcmp(curproxy->id, args[1]) &&
1081 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1082 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001083 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1084 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1085 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001086 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001087 }
1088 }
1089
Willy Tarreaubaaee002006-06-26 02:48:02 +02001090 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1091 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001092 err_code |= ERR_ALERT | ERR_ABORT;
1093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001095
Willy Tarreau97cb7802010-01-03 20:23:58 +01001096 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 curproxy->next = proxy;
1098 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001099 curproxy->conf.file = file;
1100 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001101 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001103 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104
1105 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001106 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001107 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001108 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001109 err_code |= ERR_FATAL;
1110 goto out;
1111 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001112 new = curproxy->listen;
1113 while (new != last) {
1114 new->conf.file = file;
1115 new->conf.line = linenum;
1116 new = new->next;
1117 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001118 global.maxsock++;
1119 }
1120
1121 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001122 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001123 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001124
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001126 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001127 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001128 curproxy->no_options = defproxy.no_options;
1129 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001130 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001131 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001132 curproxy->except_net = defproxy.except_net;
1133 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001134 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001135 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001136
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001137 if (defproxy.fwdfor_hdr_len) {
1138 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1139 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1140 }
1141
Willy Tarreaub86db342009-11-30 11:50:16 +01001142 if (defproxy.orgto_hdr_len) {
1143 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1144 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1145 }
1146
Willy Tarreau977b8e42006-12-29 14:19:17 +01001147 if (curproxy->cap & PR_CAP_FE) {
1148 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001149 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001150 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001151
1152 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001153 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1154 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001155
1156 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1157 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158
Willy Tarreau977b8e42006-12-29 14:19:17 +01001159 if (curproxy->cap & PR_CAP_BE) {
1160 curproxy->fullconn = defproxy.fullconn;
1161 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001162
Willy Tarreau977b8e42006-12-29 14:19:17 +01001163 if (defproxy.check_req)
1164 curproxy->check_req = strdup(defproxy.check_req);
1165 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001166
Willy Tarreau977b8e42006-12-29 14:19:17 +01001167 if (defproxy.cookie_name)
1168 curproxy->cookie_name = strdup(defproxy.cookie_name);
1169 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001170 if (defproxy.cookie_domain)
1171 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001172
Emeric Brun647caf12009-06-30 17:57:00 +02001173 if (defproxy.rdp_cookie_name)
1174 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1175 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1176
Willy Tarreau01732802007-11-01 22:48:15 +01001177 if (defproxy.url_param_name)
1178 curproxy->url_param_name = strdup(defproxy.url_param_name);
1179 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001180
Benoitaffb4812009-03-25 13:02:10 +01001181 if (defproxy.hh_name)
1182 curproxy->hh_name = strdup(defproxy.hh_name);
1183 curproxy->hh_len = defproxy.hh_len;
1184 curproxy->hh_match_domain = defproxy.hh_match_domain;
1185
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001186 if (defproxy.iface_name)
1187 curproxy->iface_name = strdup(defproxy.iface_name);
1188 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001190
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001191 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001192 if (defproxy.capture_name)
1193 curproxy->capture_name = strdup(defproxy.capture_name);
1194 curproxy->capture_namelen = defproxy.capture_namelen;
1195 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197
Willy Tarreau977b8e42006-12-29 14:19:17 +01001198 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001199 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001200 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001201 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001202 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001203 curproxy->uri_auth = defproxy.uri_auth;
1204 curproxy->mon_net = defproxy.mon_net;
1205 curproxy->mon_mask = defproxy.mon_mask;
1206 if (defproxy.monitor_uri)
1207 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1208 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001209 if (defproxy.defbe.name)
1210 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001211 }
1212
1213 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001214 curproxy->timeout.connect = defproxy.timeout.connect;
1215 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001216 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001217 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001218 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001219 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001220 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001221 curproxy->source_addr = defproxy.source_addr;
1222 }
1223
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224 curproxy->mode = defproxy.mode;
1225 curproxy->logfac1 = defproxy.logfac1;
1226 curproxy->logsrv1 = defproxy.logsrv1;
1227 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001228 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001229 curproxy->logfac2 = defproxy.logfac2;
1230 curproxy->logsrv2 = defproxy.logsrv2;
1231 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001232 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001233 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001234 curproxy->conf.used_listener_id = EB_ROOT;
1235 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001236
Willy Tarreau93893792009-07-23 13:19:11 +02001237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001238 }
1239 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1240 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001241 /* FIXME-20070101: we should do this too at the end of the
1242 * config parsing to free all default values.
1243 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001244 free(defproxy.check_req);
1245 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001246 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001247 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001248 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001249 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001250 free(defproxy.capture_name);
1251 free(defproxy.monitor_uri);
1252 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001253 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001254 free(defproxy.fwdfor_hdr_name);
1255 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001256 free(defproxy.orgto_hdr_name);
1257 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001258
Willy Tarreaua534fea2008-08-03 12:19:50 +02001259 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001260 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001261
Willy Tarreaubaaee002006-06-26 02:48:02 +02001262 /* we cannot free uri_auth because it might already be used */
1263 init_default_instance();
1264 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001265 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001267 }
1268 else if (curproxy == NULL) {
1269 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001270 err_code |= ERR_ALERT | ERR_FATAL;
1271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001272 }
1273
Willy Tarreau977b8e42006-12-29 14:19:17 +01001274
1275 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001276 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001277 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001278 int cur_arg;
1279
Willy Tarreaubaaee002006-06-26 02:48:02 +02001280 if (curproxy == &defproxy) {
1281 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001282 err_code |= ERR_ALERT | ERR_FATAL;
1283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001285 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001286 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001287
1288 if (strchr(args[1], ':') == NULL) {
1289 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1290 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001291 err_code |= ERR_ALERT | ERR_FATAL;
1292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001293 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001294
1295 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001296 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001297 err_code |= ERR_ALERT | ERR_FATAL;
1298 goto out;
1299 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001300
Willy Tarreau90a570f2009-10-04 20:54:54 +02001301 new_listen = curproxy->listen;
1302 while (new_listen != last_listen) {
1303 new_listen->conf.file = file;
1304 new_listen->conf.line = linenum;
1305 new_listen = new_listen->next;
1306 }
1307
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001308 cur_arg = 2;
1309 while (*(args[cur_arg])) {
1310 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1311#ifdef SO_BINDTODEVICE
1312 struct listener *l;
1313
1314 if (!*args[cur_arg + 1]) {
1315 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1316 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001317 err_code |= ERR_ALERT | ERR_FATAL;
1318 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001319 }
1320
1321 for (l = curproxy->listen; l != last_listen; l = l->next)
1322 l->interface = strdup(args[cur_arg + 1]);
1323
1324 global.last_checks |= LSTCHK_NETADM;
1325
1326 cur_arg += 2;
1327 continue;
1328#else
1329 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1330 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001331 err_code |= ERR_ALERT | ERR_FATAL;
1332 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001333#endif
1334 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001335 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1336#ifdef TCP_MAXSEG
1337 struct listener *l;
1338 int mss;
1339
1340 if (!*args[cur_arg + 1]) {
1341 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1342 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001343 err_code |= ERR_ALERT | ERR_FATAL;
1344 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001345 }
1346
1347 mss = str2uic(args[cur_arg + 1]);
1348 if (mss < 1 || mss > 65535) {
1349 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1350 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001351 err_code |= ERR_ALERT | ERR_FATAL;
1352 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001353 }
1354
1355 for (l = curproxy->listen; l != last_listen; l = l->next)
1356 l->maxseg = mss;
1357
1358 cur_arg += 2;
1359 continue;
1360#else
1361 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1362 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001363 err_code |= ERR_ALERT | ERR_FATAL;
1364 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001365#endif
1366 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001367
1368 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1369#ifdef TCP_DEFER_ACCEPT
1370 struct listener *l;
1371
1372 for (l = curproxy->listen; l != last_listen; l = l->next)
1373 l->options |= LI_O_DEF_ACCEPT;
1374
1375 cur_arg ++;
1376 continue;
1377#else
1378 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1379 file, linenum, args[0], args[cur_arg]);
1380 err_code |= ERR_ALERT | ERR_FATAL;
1381 goto out;
1382#endif
1383 }
1384
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001385 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001386#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001387 struct listener *l;
1388
1389 for (l = curproxy->listen; l != last_listen; l = l->next)
1390 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001391
1392 cur_arg ++;
1393 continue;
1394#else
1395 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1396 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001397 err_code |= ERR_ALERT | ERR_FATAL;
1398 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001399#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001400 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001401
1402 if (!strcmp(args[cur_arg], "name")) {
1403 struct listener *l;
1404
1405 for (l = curproxy->listen; l != last_listen; l = l->next)
1406 l->name = strdup(args[cur_arg + 1]);
1407
1408 cur_arg += 2;
1409 continue;
1410 }
1411
1412 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001413 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001414 struct listener *l;
1415
1416 if (curproxy->listen->next != last_listen) {
1417 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1418 file, linenum, args[cur_arg]);
1419 err_code |= ERR_ALERT | ERR_FATAL;
1420 goto out;
1421 }
1422
1423 if (!*args[cur_arg + 1]) {
1424 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1425 file, linenum, args[cur_arg]);
1426 err_code |= ERR_ALERT | ERR_FATAL;
1427 goto out;
1428 }
1429
1430 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001431 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001432
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001433 if (curproxy->listen->luid <= 0) {
1434 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001435 file, linenum);
1436 err_code |= ERR_ALERT | ERR_FATAL;
1437 goto out;
1438 }
1439
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001440 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1441 if (node) {
1442 l = container_of(node, struct listener, conf.id);
1443 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1444 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1445 err_code |= ERR_ALERT | ERR_FATAL;
1446 goto out;
1447 }
1448 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1449
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001450 cur_arg += 2;
1451 continue;
1452 }
1453
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001454 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 +01001455 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001456 err_code |= ERR_ALERT | ERR_FATAL;
1457 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001458 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001461 }
1462 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1463 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1464 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1465 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001466 err_code |= ERR_ALERT | ERR_FATAL;
1467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001469 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001470 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001471
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472 /* flush useless bits */
1473 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001475 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001476 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001477 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001478 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001479
Willy Tarreau1c47f852006-07-09 08:22:27 +02001480 if (!*args[1]) {
1481 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1482 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001483 err_code |= ERR_ALERT | ERR_FATAL;
1484 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001485 }
1486
Willy Tarreaua534fea2008-08-03 12:19:50 +02001487 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001488 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001489 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001490 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001491 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1492
Willy Tarreau93893792009-07-23 13:19:11 +02001493 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001495 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1496 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1497 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1498 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1499 else {
1500 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001501 err_code |= ERR_ALERT | ERR_FATAL;
1502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001503 }
1504 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001505 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001506 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001507
1508 if (curproxy == &defproxy) {
1509 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1510 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001513 }
1514
1515 if (!*args[1]) {
1516 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1517 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001518 err_code |= ERR_ALERT | ERR_FATAL;
1519 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001520 }
1521
1522 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001523 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001524
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001525 if (curproxy->uuid <= 0) {
1526 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001527 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001528 err_code |= ERR_ALERT | ERR_FATAL;
1529 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001530 }
1531
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001532 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1533 if (node) {
1534 struct proxy *target = container_of(node, struct proxy, conf.id);
1535 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1536 file, linenum, proxy_type_str(curproxy), curproxy->id,
1537 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1538 err_code |= ERR_ALERT | ERR_FATAL;
1539 goto out;
1540 }
1541 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001542 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001543 else if (!strcmp(args[0], "description")) {
1544 int i, len=0;
1545 char *d;
1546
Cyril Bonté99ed3272010-01-24 23:29:44 +01001547 if (curproxy == &defproxy) {
1548 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1549 file, linenum, args[0]);
1550 err_code |= ERR_ALERT | ERR_FATAL;
1551 goto out;
1552 }
1553
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001554 if (!*args[1]) {
1555 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1556 file, linenum, args[0]);
1557 return -1;
1558 }
1559
1560 for(i=1; *args[i]; i++)
1561 len += strlen(args[i])+1;
1562
1563 d = (char *)calloc(1, len);
1564 curproxy->desc = d;
1565
1566 d += sprintf(d, "%s", args[1]);
1567 for(i=2; *args[i]; i++)
1568 d += sprintf(d, " %s", args[i]);
1569
1570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1572 curproxy->state = PR_STSTOPPED;
1573 }
1574 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1575 curproxy->state = PR_STNEW;
1576 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001577 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1578 int cur_arg = 1;
1579 unsigned int set = 0;
1580
1581 while (*args[cur_arg]) {
1582 int u;
1583 if (strcmp(args[cur_arg], "all") == 0) {
1584 set = 0;
1585 break;
1586 }
1587 else if (strcmp(args[cur_arg], "odd") == 0) {
1588 set |= 0x55555555;
1589 }
1590 else if (strcmp(args[cur_arg], "even") == 0) {
1591 set |= 0xAAAAAAAA;
1592 }
1593 else {
1594 u = str2uic(args[cur_arg]);
1595 if (u < 1 || u > 32) {
1596 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1597 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001598 err_code |= ERR_ALERT | ERR_FATAL;
1599 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001600 }
1601 if (u > global.nbproc) {
1602 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1603 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001604 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001605 }
1606 set |= 1 << (u - 1);
1607 }
1608 cur_arg++;
1609 }
1610 curproxy->bind_proc = set;
1611 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001612 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001613 if (curproxy == &defproxy) {
1614 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001615 err_code |= ERR_ALERT | ERR_FATAL;
1616 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001617 }
1618
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001619 err = invalid_char(args[1]);
1620 if (err) {
1621 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1622 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001623 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001624 }
1625
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001626 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1627 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1628 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001629 err_code |= ERR_ALERT | ERR_FATAL;
1630 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001631 }
1632 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1634 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635
Willy Tarreau977b8e42006-12-29 14:19:17 +01001636 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001637 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001638
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 if (*(args[1]) == 0) {
1640 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1641 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001642 err_code |= ERR_ALERT | ERR_FATAL;
1643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001645
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001646 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001647 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001648 curproxy->cookie_name = strdup(args[1]);
1649 curproxy->cookie_len = strlen(curproxy->cookie_name);
1650
1651 cur_arg = 2;
1652 while (*(args[cur_arg])) {
1653 if (!strcmp(args[cur_arg], "rewrite")) {
1654 curproxy->options |= PR_O_COOK_RW;
1655 }
1656 else if (!strcmp(args[cur_arg], "indirect")) {
1657 curproxy->options |= PR_O_COOK_IND;
1658 }
1659 else if (!strcmp(args[cur_arg], "insert")) {
1660 curproxy->options |= PR_O_COOK_INS;
1661 }
1662 else if (!strcmp(args[cur_arg], "nocache")) {
1663 curproxy->options |= PR_O_COOK_NOC;
1664 }
1665 else if (!strcmp(args[cur_arg], "postonly")) {
1666 curproxy->options |= PR_O_COOK_POST;
1667 }
1668 else if (!strcmp(args[cur_arg], "prefix")) {
1669 curproxy->options |= PR_O_COOK_PFX;
1670 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001671 else if (!strcmp(args[cur_arg], "domain")) {
1672 if (!*args[cur_arg + 1]) {
1673 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1674 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001675 err_code |= ERR_ALERT | ERR_FATAL;
1676 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001677 }
1678
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001679 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001680 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001681 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1682 " dots nor does not start with a dot."
1683 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001684 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001685 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001686 }
1687
1688 err = invalid_domainchar(args[cur_arg + 1]);
1689 if (err) {
1690 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1691 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001692 err_code |= ERR_ALERT | ERR_FATAL;
1693 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001694 }
1695
Willy Tarreau68a897b2009-12-03 23:28:34 +01001696 if (!curproxy->cookie_domain) {
1697 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1698 } else {
1699 /* one domain was already specified, add another one by
1700 * building the string which will be returned along with
1701 * the cookie.
1702 */
1703 char *new_ptr;
1704 int new_len = strlen(curproxy->cookie_domain) +
1705 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1706 new_ptr = malloc(new_len);
1707 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1708 free(curproxy->cookie_domain);
1709 curproxy->cookie_domain = new_ptr;
1710 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001711 cur_arg++;
1712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001714 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001715 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001716 err_code |= ERR_ALERT | ERR_FATAL;
1717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001718 }
1719 cur_arg++;
1720 }
1721 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1722 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1723 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001724 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001725 }
1726
1727 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1728 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1729 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001730 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001731 }
1732 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001733 else if (!strcmp(args[0], "persist")) { /* persist */
1734 if (*(args[1]) == 0) {
1735 Alert("parsing [%s:%d] : missing persist method.\n",
1736 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001737 err_code |= ERR_ALERT | ERR_FATAL;
1738 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001739 }
1740
1741 if (!strncmp(args[1], "rdp-cookie", 10)) {
1742 curproxy->options2 |= PR_O2_RDPC_PRST;
1743
Emeric Brunb982a3d2010-01-04 15:45:53 +01001744 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001745 const char *beg, *end;
1746
1747 beg = args[1] + 11;
1748 end = strchr(beg, ')');
1749
1750 if (!end || end == beg) {
1751 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1752 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001753 err_code |= ERR_ALERT | ERR_FATAL;
1754 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001755 }
1756
1757 free(curproxy->rdp_cookie_name);
1758 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1759 curproxy->rdp_cookie_len = end-beg;
1760 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001761 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001762 free(curproxy->rdp_cookie_name);
1763 curproxy->rdp_cookie_name = strdup("msts");
1764 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1765 }
1766 else { /* syntax */
1767 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1768 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001771 }
1772 }
1773 else {
1774 Alert("parsing [%s:%d] : unknown persist method.\n",
1775 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001776 err_code |= ERR_ALERT | ERR_FATAL;
1777 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001778 }
1779 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001781 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001782
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001783 if (curproxy == &defproxy) {
1784 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1785 err_code |= ERR_ALERT | ERR_FATAL;
1786 goto out;
1787 }
1788
Willy Tarreau977b8e42006-12-29 14:19:17 +01001789 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001790 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001791
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001793 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001795 err_code |= ERR_ALERT | ERR_FATAL;
1796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797 }
1798 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001799 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800 curproxy->appsession_name = strdup(args[1]);
1801 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1802 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001803 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1804 if (err) {
1805 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1806 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001807 err_code |= ERR_ALERT | ERR_FATAL;
1808 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001809 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001810 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001811
Willy Tarreau51041c72007-09-09 21:56:53 +02001812 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1813 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001814 err_code |= ERR_ALERT | ERR_ABORT;
1815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001816 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001817
1818 cur_arg = 6;
1819 curproxy->options2 &= ~PR_O2_AS_REQL