blob: 6fdbe177f33b583b59907cafe8c8fd1d6836de14 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau7c669d72008-06-20 15:04:11 +02004 * Copyright 2000-2008 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 Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
27#include <common/config.h>
28#include <common/memory.h>
29#include <common/standard.h>
30#include <common/time.h>
31#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020032
33#include <types/capture.h>
34#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreaueb0c6142007-05-07 00:53:22 +020036#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010038#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020040#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010041#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010043#include <proto/protocols.h>
44#include <proto/proto_tcp.h>
45#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010046#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010048#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <proto/task.h>
50
51
Willy Tarreauf3c69202006-07-09 16:42:34 +020052/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
53 * ssl-hello-chk option to ensure that the remote server speaks SSL.
54 *
55 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
56 */
57const char sslv3_client_hello_pkt[] = {
58 "\x16" /* ContentType : 0x16 = Hanshake */
59 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
60 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
61 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
62 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
63 "\x03\x00" /* Hello Version : 0x0300 = v3 */
64 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
65 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
66 "\x00" /* Session ID length : empty (no session ID) */
67 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
68 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
69 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
70 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
71 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
72 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
73 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
74 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
75 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
76 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
77 "\x00\x38" "\x00\x39" "\x00\x3A"
78 "\x01" /* Compression Length : 0x01 = 1 byte for types */
79 "\x00" /* Compression Type : 0x00 = NULL compression */
80};
81
Willy Tarreau13943ab2006-12-31 00:24:10 +010082/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010083struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010084 const char *name;
85 unsigned int val;
86 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010087 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +010088};
89
90/* proxy->options */
91static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +010092{
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010094 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010095 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010096 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010097 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
98 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
99 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
100 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
101 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
102 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
103 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
104 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100106 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
107 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100108#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100109 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
110#endif
111#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100112 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100113#endif
114
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116};
117
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100118/* proxy->options2 */
119static const struct cfg_opt cfg_opts2[] =
120{
121#ifdef CONFIG_HAP_LINUX_SPLICE
122 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
123 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
124 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
125#endif
126 { NULL, 0, 0, 0 }
127};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200128
Willy Tarreau6daf3432008-01-22 16:44:08 +0100129static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200130static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
131int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100132int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
133unsigned int acl_seen = 0; /* CFG_ACL_* */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200134
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200135/* List head of all known configuration keywords */
136static struct cfg_kw_list cfg_keywords = {
137 .list = LIST_HEAD_INIT(cfg_keywords.list)
138};
139
Willy Tarreaubaaee002006-06-26 02:48:02 +0200140/*
141 * converts <str> to a list of listeners which are dynamically allocated.
142 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
143 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
144 * - <port> is a numerical port from 1 to 65535 ;
145 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
146 * This can be repeated as many times as necessary, separated by a coma.
147 * The <tail> argument is a pointer to a current list which should be appended
148 * to the tail of the new list. The pointer to the new list is returned.
149 */
150static struct listener *str2listener(char *str, struct listener *tail)
151{
152 struct listener *l;
153 char *c, *next, *range, *dupstr;
154 int port, end;
155
156 next = dupstr = strdup(str);
157
158 while (next && *next) {
159 struct sockaddr_storage ss;
160
161 str = next;
162 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100163 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200164 *next++ = 0;
165 }
166
167 /* 2) look for the addr/port delimiter, it's the last colon. */
168 if ((range = strrchr(str, ':')) == NULL) {
169 Alert("Missing port number: '%s'\n", str);
170 goto fail;
171 }
172
173 *range++ = 0;
174
175 if (strrchr(str, ':') != NULL) {
176 /* IPv6 address contains ':' */
177 memset(&ss, 0, sizeof(ss));
178 ss.ss_family = AF_INET6;
179
180 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
181 Alert("Invalid server address: '%s'\n", str);
182 goto fail;
183 }
184 }
185 else {
186 memset(&ss, 0, sizeof(ss));
187 ss.ss_family = AF_INET;
188
189 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
190 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
191 }
192 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
193 struct hostent *he;
194
195 if ((he = gethostbyname(str)) == NULL) {
196 Alert("Invalid server name: '%s'\n", str);
197 goto fail;
198 }
199 else
200 ((struct sockaddr_in *)&ss)->sin_addr =
201 *(struct in_addr *) *(he->h_addr_list);
202 }
203 }
204
205 /* 3) look for the port-end delimiter */
206 if ((c = strchr(range, '-')) != NULL) {
207 *c++ = 0;
208 end = atol(c);
209 }
210 else {
211 end = atol(range);
212 }
213
214 port = atol(range);
215
216 if (port < 1 || port > 65535) {
217 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
218 goto fail;
219 }
220
221 if (end < 1 || end > 65535) {
222 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
223 goto fail;
224 }
225
226 for (; port <= end; port++) {
227 l = (struct listener *)calloc(1, sizeof(struct listener));
228 l->next = tail;
229 tail = l;
230
231 l->fd = -1;
232 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100233 l->state = LI_INIT;
234
235 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100237 tcpv6_add_listener(l);
238 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100240 tcpv4_add_listener(l);
241 }
242 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 } /* end for(port) */
244 } /* end while(next) */
245 free(dupstr);
246 return tail;
247 fail:
248 free(dupstr);
249 return NULL;
250}
251
Willy Tarreau977b8e42006-12-29 14:19:17 +0100252/*
253 * Sends a warning if proxy <proxy> does not have at least one of the
254 * capabilities in <cap>. An optionnal <hint> may be added at the end
255 * of the warning to help the user. Returns 1 if a warning was emitted
256 * or 0 if the condition is valid.
257 */
258int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
259{
260 char *msg;
261
262 switch (cap) {
263 case PR_CAP_BE: msg = "no backend"; break;
264 case PR_CAP_FE: msg = "no frontend"; break;
265 case PR_CAP_RS: msg = "no ruleset"; break;
266 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
267 default: msg = "not enough"; break;
268 }
269
270 if (!(proxy->cap & cap)) {
271 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100272 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100273 return 1;
274 }
275 return 0;
276}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200277
278/*
279 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
280 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100281int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200282{
283
284 if (!strcmp(args[0], "global")) { /* new section */
285 /* no option, nothing special to do */
286 return 0;
287 }
288 else if (!strcmp(args[0], "daemon")) {
289 global.mode |= MODE_DAEMON;
290 }
291 else if (!strcmp(args[0], "debug")) {
292 global.mode |= MODE_DEBUG;
293 }
294 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100295 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200297 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100298 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200299 }
300 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100301 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200302 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200303 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100304 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200305 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100306 else if (!strcmp(args[0], "nosplice")) {
307 global.tune.options &= ~GTUNE_USE_SPLICE;
308 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200309 else if (!strcmp(args[0], "quiet")) {
310 global.mode |= MODE_QUIET;
311 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200312 else if (!strcmp(args[0], "tune.maxpollevents")) {
313 if (global.tune.maxpollevents != 0) {
314 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
315 return 0;
316 }
317 if (*(args[1]) == 0) {
318 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
319 return -1;
320 }
321 global.tune.maxpollevents = atol(args[1]);
322 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100323 else if (!strcmp(args[0], "tune.maxaccept")) {
324 if (global.tune.maxaccept != 0) {
325 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
326 return 0;
327 }
328 if (*(args[1]) == 0) {
329 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
330 return -1;
331 }
332 global.tune.maxaccept = atol(args[1]);
333 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200334 else if (!strcmp(args[0], "uid")) {
335 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200336 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200337 return 0;
338 }
339 if (*(args[1]) == 0) {
340 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
341 return -1;
342 }
343 global.uid = atol(args[1]);
344 }
345 else if (!strcmp(args[0], "gid")) {
346 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200347 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200348 return 0;
349 }
350 if (*(args[1]) == 0) {
351 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
352 return -1;
353 }
354 global.gid = atol(args[1]);
355 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200356 /* user/group name handling */
357 else if (!strcmp(args[0], "user")) {
358 struct passwd *ha_user;
359 if (global.uid != 0) {
360 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
361 return 0;
362 }
363 errno = 0;
364 ha_user = getpwnam(args[1]);
365 if (ha_user != NULL) {
366 global.uid = (int)ha_user->pw_uid;
367 }
368 else {
369 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
370 exit(1);
371 }
372 }
373 else if (!strcmp(args[0], "group")) {
374 struct group *ha_group;
375 if (global.gid != 0) {
376 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
377 return 0;
378 }
379 errno = 0;
380 ha_group = getgrnam(args[1]);
381 if (ha_group != NULL) {
382 global.gid = (int)ha_group->gr_gid;
383 }
384 else {
385 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
386 exit(1);
387 }
388 }
389 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200390 else if (!strcmp(args[0], "nbproc")) {
391 if (global.nbproc != 0) {
392 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
393 return 0;
394 }
395 if (*(args[1]) == 0) {
396 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
397 return -1;
398 }
399 global.nbproc = atol(args[1]);
400 }
401 else if (!strcmp(args[0], "maxconn")) {
402 if (global.maxconn != 0) {
403 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
404 return 0;
405 }
406 if (*(args[1]) == 0) {
407 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
408 return -1;
409 }
410 global.maxconn = atol(args[1]);
411#ifdef SYSTEM_MAXCONN
412 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
413 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);
414 global.maxconn = DEFAULT_MAXCONN;
415 }
416#endif /* SYSTEM_MAXCONN */
417 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100418 else if (!strcmp(args[0], "maxpipes")) {
419 if (global.maxpipes != 0) {
420 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
421 return 0;
422 }
423 if (*(args[1]) == 0) {
424 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
425 return -1;
426 }
427 global.maxpipes = atol(args[1]);
428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200429 else if (!strcmp(args[0], "ulimit-n")) {
430 if (global.rlimit_nofile != 0) {
431 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
432 return 0;
433 }
434 if (*(args[1]) == 0) {
435 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
436 return -1;
437 }
438 global.rlimit_nofile = atol(args[1]);
439 }
440 else if (!strcmp(args[0], "chroot")) {
441 if (global.chroot != NULL) {
442 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
443 return 0;
444 }
445 if (*(args[1]) == 0) {
446 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
447 return -1;
448 }
449 global.chroot = strdup(args[1]);
450 }
451 else if (!strcmp(args[0], "pidfile")) {
452 if (global.pidfile != NULL) {
453 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
454 return 0;
455 }
456 if (*(args[1]) == 0) {
457 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
458 return -1;
459 }
460 global.pidfile = strdup(args[1]);
461 }
462 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100463 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200464 int facility, level;
465
466 if (*(args[1]) == 0 || *(args[2]) == 0) {
467 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
468 return -1;
469 }
470
471 facility = get_log_facility(args[2]);
472 if (facility < 0) {
473 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
474 exit(1);
475 }
476
477 level = 7; /* max syslog level = debug */
478 if (*(args[3])) {
479 level = get_log_level(args[3]);
480 if (level < 0) {
481 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
482 exit(1);
483 }
484 }
485
Robert Tsai81ae1952007-12-05 10:47:29 +0100486 if (args[1][0] == '/') {
487 logsrv.u.addr.sa_family = AF_UNIX;
488 logsrv.u.un = *str2sun(args[1]);
489 } else {
490 logsrv.u.addr.sa_family = AF_INET;
491 logsrv.u.in = *str2sa(args[1]);
492 if (!logsrv.u.in.sin_port)
493 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200495
496 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100497 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200498 global.logfac1 = facility;
499 global.loglev1 = level;
500 }
501 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100502 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200503 global.logfac2 = facility;
504 global.loglev2 = level;
505 }
506 else {
507 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
508 return -1;
509 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200510 }
511 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
512 if (global.spread_checks != 0) {
513 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
514 return 0;
515 }
516 if (*(args[1]) == 0) {
517 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
518 return -1;
519 }
520 global.spread_checks = atol(args[1]);
521 if (global.spread_checks < 0 || global.spread_checks > 50) {
522 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
523 return -1;
524 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200525 }
526 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200527 struct cfg_kw_list *kwl;
528 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200529 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200530
531 list_for_each_entry(kwl, &cfg_keywords.list, list) {
532 for (index = 0; kwl->kw[index].kw != NULL; index++) {
533 if (kwl->kw[index].section != CFG_GLOBAL)
534 continue;
535 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
536 /* prepare error message just in case */
537 snprintf(trash, sizeof(trash),
538 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200539 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
540 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200541 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
542 return -1;
543 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200544 else if (rc > 0) {
545 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
546 return 0;
547 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200548 return 0;
549 }
550 }
551 }
552
Willy Tarreaubaaee002006-06-26 02:48:02 +0200553 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
554 return -1;
555 }
556 return 0;
557}
558
559
560static void init_default_instance()
561{
562 memset(&defproxy, 0, sizeof(defproxy));
563 defproxy.mode = PR_MODE_TCP;
564 defproxy.state = PR_STNEW;
565 defproxy.maxconn = cfg_maxpconn;
566 defproxy.conn_retries = CONN_RETRIES;
567 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200568
569 LIST_INIT(&defproxy.pendconns);
570 LIST_INIT(&defproxy.acl);
571 LIST_INIT(&defproxy.block_cond);
572 LIST_INIT(&defproxy.mon_fail_cond);
573 LIST_INIT(&defproxy.switching_rules);
574
Willy Tarreau3a70f942008-02-15 11:15:34 +0100575 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200576}
577
578/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100579 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
580 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100582int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200583{
584 static struct proxy *curproxy = NULL;
585 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200586 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100587 int rc;
588 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589
Willy Tarreau977b8e42006-12-29 14:19:17 +0100590 if (!strcmp(args[0], "listen"))
591 rc = PR_CAP_LISTEN;
592 else if (!strcmp(args[0], "frontend"))
593 rc = PR_CAP_FE | PR_CAP_RS;
594 else if (!strcmp(args[0], "backend"))
595 rc = PR_CAP_BE | PR_CAP_RS;
596 else if (!strcmp(args[0], "ruleset"))
597 rc = PR_CAP_RS;
598 else
599 rc = PR_CAP_NONE;
600
601 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 if (!*args[1]) {
603 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
604 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
605 file, linenum, args[0]);
606 return -1;
607 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200608
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100609 err = invalid_char(args[1]);
610 if (err) {
611 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
612 file, linenum, *err, args[0], args[1]);
613 return -1;
614 }
615
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200616 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
617 /*
618 * If there are two proxies with the same name only following
619 * combinations are allowed:
620 *
621 * listen backend frontend ruleset
622 * listen - - - -
623 * backend - - OK -
624 * frontend - OK - -
625 * ruleset - - - -
626 */
627
628 if (!strcmp(curproxy->id, args[1]) &&
629 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
630 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100631 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
632 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200633 }
634 }
635
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
637 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
638 return -1;
639 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100640
641 acl_seen = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 curproxy->next = proxy;
643 proxy = curproxy;
644 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200645 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200646 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200647 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100648 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200649 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200650 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200651
Willy Tarreauee991362007-05-14 14:37:50 +0200652 /* Timeouts are defined as -1, so we cannot use the zeroed area
653 * as a default value.
654 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100655 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200656
657 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100659 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200660
661 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100662 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200663 curproxy->listen = str2listener(args[2], curproxy->listen);
664 if (!curproxy->listen)
665 return -1;
666 global.maxsock++;
667 }
668
669 /* set default values */
670 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100672 curproxy->options2 = defproxy.options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100673 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100674 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200675 curproxy->except_net = defproxy.except_net;
676 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200678 if (defproxy.fwdfor_hdr_len) {
679 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
680 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
681 }
682
Willy Tarreau977b8e42006-12-29 14:19:17 +0100683 if (curproxy->cap & PR_CAP_FE) {
684 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100685 curproxy->backlog = defproxy.backlog;
Willy Tarreau39af0f62009-03-07 11:53:44 +0100686 curproxy->fe_maxsps = defproxy.fe_maxsps;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100687
688 /* initialize error relocations */
689 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
690 if (defproxy.errmsg[rc].str)
691 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
692 }
693
694 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
695 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696
Willy Tarreau977b8e42006-12-29 14:19:17 +0100697 if (curproxy->cap & PR_CAP_BE) {
698 curproxy->fullconn = defproxy.fullconn;
699 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700
Willy Tarreau977b8e42006-12-29 14:19:17 +0100701 if (defproxy.check_req)
702 curproxy->check_req = strdup(defproxy.check_req);
703 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200704
Willy Tarreau977b8e42006-12-29 14:19:17 +0100705 if (defproxy.cookie_name)
706 curproxy->cookie_name = strdup(defproxy.cookie_name);
707 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100708
709 if (defproxy.url_param_name)
710 curproxy->url_param_name = strdup(defproxy.url_param_name);
711 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100712
713 if (defproxy.iface_name)
714 curproxy->iface_name = strdup(defproxy.iface_name);
715 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100716 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200717
Willy Tarreau977b8e42006-12-29 14:19:17 +0100718 if (curproxy->cap & PR_CAP_RS) {
719 if (defproxy.capture_name)
720 curproxy->capture_name = strdup(defproxy.capture_name);
721 curproxy->capture_namelen = defproxy.capture_namelen;
722 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200724
Willy Tarreau977b8e42006-12-29 14:19:17 +0100725 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100726 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100727 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100728 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100729 curproxy->uri_auth = defproxy.uri_auth;
730 curproxy->mon_net = defproxy.mon_net;
731 curproxy->mon_mask = defproxy.mon_mask;
732 if (defproxy.monitor_uri)
733 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
734 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100735 if (defproxy.defbe.name)
736 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100737 }
738
739 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100740 curproxy->timeout.connect = defproxy.timeout.connect;
741 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100742 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100743 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100744 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100745 curproxy->source_addr = defproxy.source_addr;
746 }
747
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748 curproxy->mode = defproxy.mode;
749 curproxy->logfac1 = defproxy.logfac1;
750 curproxy->logsrv1 = defproxy.logsrv1;
751 curproxy->loglev1 = defproxy.loglev1;
752 curproxy->logfac2 = defproxy.logfac2;
753 curproxy->logsrv2 = defproxy.logsrv2;
754 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200755 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100756 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
757 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200758
Willy Tarreaubaaee002006-06-26 02:48:02 +0200759 return 0;
760 }
761 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
762 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100763 /* FIXME-20070101: we should do this too at the end of the
764 * config parsing to free all default values.
765 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200766 free(defproxy.check_req);
767 free(defproxy.cookie_name);
768 free(defproxy.url_param_name);
769 free(defproxy.capture_name);
770 free(defproxy.monitor_uri);
771 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100772 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200773 free(defproxy.fwdfor_hdr_name);
774 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100775
Willy Tarreaua534fea2008-08-03 12:19:50 +0200776 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
777 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100778
Willy Tarreaubaaee002006-06-26 02:48:02 +0200779 /* we cannot free uri_auth because it might already be used */
780 init_default_instance();
781 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100782 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200783 return 0;
784 }
785 else if (curproxy == NULL) {
786 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
787 return -1;
788 }
789
Willy Tarreau977b8e42006-12-29 14:19:17 +0100790
791 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200792 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100793 struct listener *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100794 int cur_arg;
795
Willy Tarreaubaaee002006-06-26 02:48:02 +0200796 if (curproxy == &defproxy) {
797 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
798 return -1;
799 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100800 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
801 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200802
803 if (strchr(args[1], ':') == NULL) {
804 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
805 file, linenum, args[0]);
806 return -1;
807 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100808
809 last_listen = curproxy->listen;
810 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200811 if (!curproxy->listen)
812 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100813
814 cur_arg = 2;
815 while (*(args[cur_arg])) {
816 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
817#ifdef SO_BINDTODEVICE
818 struct listener *l;
819
820 if (!*args[cur_arg + 1]) {
821 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
822 file, linenum, args[0]);
823 return -1;
824 }
825
826 for (l = curproxy->listen; l != last_listen; l = l->next)
827 l->interface = strdup(args[cur_arg + 1]);
828
829 global.last_checks |= LSTCHK_NETADM;
830
831 cur_arg += 2;
832 continue;
833#else
834 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
835 file, linenum, args[0], args[cur_arg]);
836 return -1;
837#endif
838 }
839 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100840#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100841 struct listener *l;
842
843 for (l = curproxy->listen; l != last_listen; l = l->next)
844 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100845
846 cur_arg ++;
847 continue;
848#else
849 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
850 file, linenum, args[0], args[cur_arg]);
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100851 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100852#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100853 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100854 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100855 file, linenum, args[0]);
856 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100857 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200858 global.maxsock++;
859 return 0;
860 }
861 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
862 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
863 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
864 file, linenum, args[0]);
865 return -1;
866 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100867 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
868 return 0;
869
Willy Tarreaubaaee002006-06-26 02:48:02 +0200870 /* flush useless bits */
871 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
872 return 0;
873 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200874 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100875 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
876 return 0;
877
Willy Tarreau1c47f852006-07-09 08:22:27 +0200878 if (!*args[1]) {
879 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
880 file, linenum, args[0]);
881 return -1;
882 }
883
Willy Tarreaua534fea2008-08-03 12:19:50 +0200884 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100885 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200886 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100887 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200888 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
889
890 return 0;
891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
893 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
894 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
895 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
896 else {
897 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
898 return -1;
899 }
900 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100901 else if (!strcmp(args[0], "id")) {
902 struct proxy *target;
903
904 if (curproxy == &defproxy) {
905 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
906 file, linenum, args[0]);
907 return -1;
908 }
909
910 if (!*args[1]) {
911 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
912 file, linenum, args[0]);
913 return -1;
914 }
915
916 curproxy->uuid = atol(args[1]);
917
918 if (curproxy->uuid < 1001) {
919 Alert("parsing [%s:%d]: custom id has to be > 1000",
920 file, linenum);
921 return -1;
922 }
923
924 for (target = proxy; target; target = target->next)
925 if (curproxy != target && curproxy->uuid == target->uuid) {
926 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
927 file, linenum, curproxy->id, target->id);
928 return -1;
929 }
930 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
932 curproxy->state = PR_STSTOPPED;
933 }
934 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
935 curproxy->state = PR_STNEW;
936 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100937 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
938 int cur_arg = 1;
939 unsigned int set = 0;
940
941 while (*args[cur_arg]) {
942 int u;
943 if (strcmp(args[cur_arg], "all") == 0) {
944 set = 0;
945 break;
946 }
947 else if (strcmp(args[cur_arg], "odd") == 0) {
948 set |= 0x55555555;
949 }
950 else if (strcmp(args[cur_arg], "even") == 0) {
951 set |= 0xAAAAAAAA;
952 }
953 else {
954 u = str2uic(args[cur_arg]);
955 if (u < 1 || u > 32) {
956 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
957 file, linenum, args[0]);
958 return -1;
959 }
960 if (u > global.nbproc) {
961 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
962 file, linenum, args[0]);
963 }
964 set |= 1 << (u - 1);
965 }
966 cur_arg++;
967 }
968 curproxy->bind_proc = set;
969 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200970 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200971 if (curproxy == &defproxy) {
972 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
973 return -1;
974 }
975
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100976 err = invalid_char(args[1]);
977 if (err) {
978 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
979 file, linenum, *err, args[1]);
980 return -1;
981 }
982
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200983 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
984 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
985 file, linenum, args[1]);
986 return -1;
987 }
988 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200989 else if (!strcmp(args[0], "cookie")) { /* cookie name */
990 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200991
Willy Tarreau977b8e42006-12-29 14:19:17 +0100992 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
993 return 0;
994
Willy Tarreaubaaee002006-06-26 02:48:02 +0200995 if (*(args[1]) == 0) {
996 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
997 file, linenum, args[0]);
998 return -1;
999 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001000
1001 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 curproxy->cookie_name = strdup(args[1]);
1003 curproxy->cookie_len = strlen(curproxy->cookie_name);
1004
1005 cur_arg = 2;
1006 while (*(args[cur_arg])) {
1007 if (!strcmp(args[cur_arg], "rewrite")) {
1008 curproxy->options |= PR_O_COOK_RW;
1009 }
1010 else if (!strcmp(args[cur_arg], "indirect")) {
1011 curproxy->options |= PR_O_COOK_IND;
1012 }
1013 else if (!strcmp(args[cur_arg], "insert")) {
1014 curproxy->options |= PR_O_COOK_INS;
1015 }
1016 else if (!strcmp(args[cur_arg], "nocache")) {
1017 curproxy->options |= PR_O_COOK_NOC;
1018 }
1019 else if (!strcmp(args[cur_arg], "postonly")) {
1020 curproxy->options |= PR_O_COOK_POST;
1021 }
1022 else if (!strcmp(args[cur_arg], "prefix")) {
1023 curproxy->options |= PR_O_COOK_PFX;
1024 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001025 else if (!strcmp(args[cur_arg], "domain")) {
1026 if (!*args[cur_arg + 1]) {
1027 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1028 file, linenum, args[cur_arg]);
1029 return -1;
1030 }
1031
1032 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1033 /* rfc2109, 4.3.2 Rejecting Cookies */
1034 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1035 " dots or does not start with a dot.\n",
1036 file, linenum, args[cur_arg + 1]);
1037 return -1;
1038 }
1039
1040 err = invalid_domainchar(args[cur_arg + 1]);
1041 if (err) {
1042 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1043 file, linenum, *err, args[cur_arg + 1]);
1044 return -1;
1045 }
1046
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001047 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001048 cur_arg++;
1049 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001051 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 file, linenum, args[0]);
1053 return -1;
1054 }
1055 cur_arg++;
1056 }
1057 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1058 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1059 file, linenum);
1060 return -1;
1061 }
1062
1063 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1064 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1065 file, linenum);
1066 return -1;
1067 }
1068 }/* end else if (!strcmp(args[0], "cookie")) */
1069 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001070
Willy Tarreau977b8e42006-12-29 14:19:17 +01001071 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1072 return 0;
1073
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074 if (*(args[5]) == 0) {
1075 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1076 file, linenum, args[0]);
1077 return -1;
1078 }
1079 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001080 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081 curproxy->appsession_name = strdup(args[1]);
1082 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1083 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001084 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1085 if (err) {
1086 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1087 file, linenum, *err, args[0]);
1088 return -1;
1089 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001090 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001091
Willy Tarreau51041c72007-09-09 21:56:53 +02001092 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1093 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 return -1;
1095 }
1096 } /* Url App Session */
1097 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001098 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1099 return 0;
1100
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 if (*(args[4]) == 0) {
1103 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1104 file, linenum, args[0]);
1105 return -1;
1106 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001107 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001108 curproxy->capture_name = strdup(args[2]);
1109 curproxy->capture_namelen = strlen(curproxy->capture_name);
1110 curproxy->capture_len = atol(args[4]);
1111 if (curproxy->capture_len >= CAPTURE_LEN) {
1112 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1113 file, linenum, CAPTURE_LEN - 1);
1114 curproxy->capture_len = CAPTURE_LEN - 1;
1115 }
1116 curproxy->to_log |= LW_COOKIE;
1117 }
1118 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1119 struct cap_hdr *hdr;
1120
1121 if (curproxy == &defproxy) {
1122 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1123 return -1;
1124 }
1125
1126 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1127 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1128 file, linenum, args[0], args[1]);
1129 return -1;
1130 }
1131
1132 hdr = calloc(sizeof(struct cap_hdr), 1);
1133 hdr->next = curproxy->req_cap;
1134 hdr->name = strdup(args[3]);
1135 hdr->namelen = strlen(args[3]);
1136 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001137 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001138 hdr->index = curproxy->nb_req_cap++;
1139 curproxy->req_cap = hdr;
1140 curproxy->to_log |= LW_REQHDR;
1141 }
1142 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1143 struct cap_hdr *hdr;
1144
1145 if (curproxy == &defproxy) {
1146 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1147 return -1;
1148 }
1149
1150 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1151 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1152 file, linenum, args[0], args[1]);
1153 return -1;
1154 }
1155 hdr = calloc(sizeof(struct cap_hdr), 1);
1156 hdr->next = curproxy->rsp_cap;
1157 hdr->name = strdup(args[3]);
1158 hdr->namelen = strlen(args[3]);
1159 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001160 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001161 hdr->index = curproxy->nb_rsp_cap++;
1162 curproxy->rsp_cap = hdr;
1163 curproxy->to_log |= LW_RSPHDR;
1164 }
1165 else {
1166 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1167 file, linenum, args[0]);
1168 return -1;
1169 }
1170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001171 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001172 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1173 return 0;
1174
Willy Tarreaubaaee002006-06-26 02:48:02 +02001175 if (*(args[1]) == 0) {
1176 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1177 file, linenum, args[0]);
1178 return -1;
1179 }
1180 curproxy->conn_retries = atol(args[1]);
1181 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001182 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1183 int pol = ACL_COND_NONE;
1184 struct acl_cond *cond;
1185
Willy Tarreaub099aca2008-10-12 17:26:37 +02001186 if (curproxy == &defproxy) {
1187 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1188 return -1;
1189 }
1190
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001191 if (!strcmp(args[1], "if"))
1192 pol = ACL_COND_IF;
1193 else if (!strcmp(args[1], "unless"))
1194 pol = ACL_COND_UNLESS;
1195
1196 if (pol == ACL_COND_NONE) {
1197 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1198 file, linenum, args[0]);
1199 return -1;
1200 }
1201
1202 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1203 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1204 file, linenum);
1205 return -1;
1206 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001207 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001208 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001209
1210 if (!(acl_seen & CFG_ACL_BLOCK)) {
1211 if (acl_seen & CFG_ACL_REDIR)
1212 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
1213 file, linenum, args[0]);
1214 if (acl_seen & CFG_ACL_BACKEND)
1215 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
1216 file, linenum, args[0]);
1217 acl_seen |= CFG_ACL_BLOCK;
1218 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001219 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001220 else if (!strcmp(args[0], "redirect")) {
1221 int pol = ACL_COND_NONE;
1222 struct acl_cond *cond;
1223 struct redirect_rule *rule;
1224 int cur_arg;
1225 int type = REDIRECT_TYPE_NONE;
1226 int code = 302;
1227 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001228 char *cookie = NULL;
1229 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001230 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001231
1232 cur_arg = 1;
1233 while (*(args[cur_arg])) {
1234 if (!strcmp(args[cur_arg], "location")) {
1235 if (!*args[cur_arg + 1]) {
1236 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1237 file, linenum, args[0], args[cur_arg]);
1238 return -1;
1239 }
1240
1241 type = REDIRECT_TYPE_LOCATION;
1242 cur_arg++;
1243 destination = args[cur_arg];
1244 }
1245 else if (!strcmp(args[cur_arg], "prefix")) {
1246 if (!*args[cur_arg + 1]) {
1247 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1248 file, linenum, args[0], args[cur_arg]);
1249 return -1;
1250 }
1251
1252 type = REDIRECT_TYPE_PREFIX;
1253 cur_arg++;
1254 destination = args[cur_arg];
1255 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001256 else if (!strcmp(args[cur_arg], "set-cookie")) {
1257 if (!*args[cur_arg + 1]) {
1258 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1259 file, linenum, args[0], args[cur_arg]);
1260 return -1;
1261 }
1262
1263 cur_arg++;
1264 cookie = args[cur_arg];
1265 cookie_set = 1;
1266 }
1267 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1268 if (!*args[cur_arg + 1]) {
1269 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1270 file, linenum, args[0], args[cur_arg]);
1271 return -1;
1272 }
1273
1274 cur_arg++;
1275 cookie = args[cur_arg];
1276 cookie_set = 0;
1277 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001278 else if (!strcmp(args[cur_arg],"code")) {
1279 if (!*args[cur_arg + 1]) {
1280 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1281 file, linenum, args[0]);
1282 return -1;
1283 }
1284 cur_arg++;
1285 code = atol(args[cur_arg]);
1286 if (code < 301 || code > 303) {
1287 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1288 file, linenum, args[0], code);
1289 return -1;
1290 }
1291 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001292 else if (!strcmp(args[cur_arg],"drop-query")) {
1293 flags |= REDIRECT_FLAG_DROP_QS;
1294 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001295 else if (!strcmp(args[cur_arg], "if")) {
1296 pol = ACL_COND_IF;
1297 cur_arg++;
1298 break;
1299 }
1300 else if (!strcmp(args[cur_arg], "unless")) {
1301 pol = ACL_COND_UNLESS;
1302 cur_arg++;
1303 break;
1304 }
1305 else {
1306 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1307 file, linenum, args[0], args[cur_arg]);
1308 return -1;
1309 }
1310 cur_arg++;
1311 }
1312
1313 if (type == REDIRECT_TYPE_NONE) {
1314 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1315 file, linenum, args[0]);
1316 return -1;
1317 }
1318
1319 if (pol == ACL_COND_NONE) {
1320 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1321 file, linenum, args[0]);
1322 return -1;
1323 }
1324
1325 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1326 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1327 file, linenum, args[0]);
1328 return -1;
1329 }
1330
Willy Tarreaua9802632008-07-25 19:13:19 +02001331 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001332 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1333 rule->cond = cond;
1334 rule->rdr_str = strdup(destination);
1335 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001336 if (cookie) {
1337 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1338 * a clear consists in appending "; Max-Age=0" at the end.
1339 */
1340 rule->cookie_len = strlen(cookie);
1341 if (cookie_set)
1342 rule->cookie_str = strdup(cookie);
1343 else {
1344 rule->cookie_str = malloc(rule->cookie_len + 12);
1345 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1346 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1347 rule->cookie_len += 11;
1348 }
1349 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001350 rule->type = type;
1351 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001352 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001353 LIST_INIT(&rule->list);
1354 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001355
1356 if (!(acl_seen & CFG_ACL_REDIR)) {
1357 if (acl_seen & CFG_ACL_BACKEND)
1358 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
1359 file, linenum, args[0]);
1360 acl_seen |= CFG_ACL_REDIR;
1361 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001362 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001363 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001364 int pol = ACL_COND_NONE;
1365 struct acl_cond *cond;
1366 struct switching_rule *rule;
1367
Willy Tarreaub099aca2008-10-12 17:26:37 +02001368 if (curproxy == &defproxy) {
1369 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1370 return -1;
1371 }
1372
Willy Tarreau55ea7572007-06-17 19:56:27 +02001373 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1374 return 0;
1375
1376 if (*(args[1]) == 0) {
1377 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1378 return -1;
1379 }
1380
1381 if (!strcmp(args[2], "if"))
1382 pol = ACL_COND_IF;
1383 else if (!strcmp(args[2], "unless"))
1384 pol = ACL_COND_UNLESS;
1385
1386 if (pol == ACL_COND_NONE) {
1387 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1388 file, linenum, args[0]);
1389 return -1;
1390 }
1391
1392 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001393 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001394 file, linenum);
1395 return -1;
1396 }
1397
Willy Tarreaua9802632008-07-25 19:13:19 +02001398 cond->line = linenum;
1399 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001400 struct acl *acl;
1401 const char *name;
1402
1403 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1404 name = acl ? acl->name : "(unknown)";
1405 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1406 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001407 }
1408
Willy Tarreau55ea7572007-06-17 19:56:27 +02001409 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1410 rule->cond = cond;
1411 rule->be.name = strdup(args[1]);
1412 LIST_INIT(&rule->list);
1413 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001414 acl_seen |= CFG_ACL_BACKEND;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001415 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001416 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001417 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1418 return 0;
1419
Willy Tarreaubaaee002006-06-26 02:48:02 +02001420 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1421 curproxy->uri_auth = NULL; /* we must detach from the default config */
1422
1423 if (*(args[1]) == 0) {
1424 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1425 return -1;
1426 } else if (!strcmp(args[1], "uri")) {
1427 if (*(args[2]) == 0) {
1428 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1429 return -1;
1430 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1431 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1432 return -1;
1433 }
1434 } else if (!strcmp(args[1], "realm")) {
1435 if (*(args[2]) == 0) {
1436 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1437 return -1;
1438 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1439 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1440 return -1;
1441 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001442 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001443 unsigned interval;
1444
1445 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1446 if (err) {
1447 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1448 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001449 return -1;
1450 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1451 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1452 return -1;
1453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 } else if (!strcmp(args[1], "auth")) {
1455 if (*(args[2]) == 0) {
1456 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1457 return -1;
1458 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1459 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1460 return -1;
1461 }
1462 } else if (!strcmp(args[1], "scope")) {
1463 if (*(args[2]) == 0) {
1464 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1465 return -1;
1466 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1467 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1468 return -1;
1469 }
1470 } else if (!strcmp(args[1], "enable")) {
1471 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1472 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1473 return -1;
1474 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001475 } else if (!strcmp(args[1], "hide-version")) {
1476 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1477 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1478 return -1;
1479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001480 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001481 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001482 file, linenum, args[0]);
1483 return -1;
1484 }
1485 }
1486 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001487 int optnum;
1488
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001489 if (*(args[1]) == '\0') {
1490 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1491 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492 return -1;
1493 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001494
1495 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1496 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1497 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1498 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001499
1500 if (!inv)
1501 curproxy->options |= cfg_opts[optnum].val;
1502 else
1503 curproxy->options &= ~cfg_opts[optnum].val;
1504
Willy Tarreau13943ab2006-12-31 00:24:10 +01001505 return 0;
1506 }
1507 }
1508
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001509 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1510 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
1511 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
1512 return 0;
1513
1514 if (!inv)
1515 curproxy->options2 |= cfg_opts2[optnum].val;
1516 else
1517 curproxy->options2 &= ~cfg_opts2[optnum].val;
1518
1519 return 0;
1520 }
1521 }
1522
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001523 if (inv) {
1524 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1525 file, linenum, args[1]);
1526 return -1;
1527 }
1528
Willy Tarreau13943ab2006-12-31 00:24:10 +01001529 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530 /* generate a complete HTTP log */
1531 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1532 else if (!strcmp(args[1], "tcplog"))
1533 /* generate a detailed TCP log */
1534 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535 else if (!strcmp(args[1], "tcpka")) {
1536 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001537 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1538 return 0;
1539
1540 if (curproxy->cap & PR_CAP_FE)
1541 curproxy->options |= PR_O_TCP_CLI_KA;
1542 if (curproxy->cap & PR_CAP_BE)
1543 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001544 }
1545 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001546 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1547 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001548 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001549 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001550 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001551 curproxy->options &= ~PR_O_SMTP_CHK;
1552 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001553 if (!*args[2]) { /* no argument */
1554 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1555 curproxy->check_len = strlen(DEF_CHECK_REQ);
1556 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001557 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558 curproxy->check_req = (char *)malloc(reqlen);
1559 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1560 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1561 } else { /* more arguments : METHOD URI [HTTP_VER] */
1562 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1563 if (*args[4])
1564 reqlen += strlen(args[4]);
1565 else
1566 reqlen += strlen("HTTP/1.0");
1567
1568 curproxy->check_req = (char *)malloc(reqlen);
1569 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1570 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1571 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001572 }
1573 else if (!strcmp(args[1], "ssl-hello-chk")) {
1574 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001575 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1576 return 0;
1577
Willy Tarreaua534fea2008-08-03 12:19:50 +02001578 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001579 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001580 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001581 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001582 }
Willy Tarreau23677902007-05-08 23:50:35 +02001583 else if (!strcmp(args[1], "smtpchk")) {
1584 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001585 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001586 curproxy->options &= ~PR_O_HTTP_CHK;
1587 curproxy->options &= ~PR_O_SSL3_CHK;
1588 curproxy->options |= PR_O_SMTP_CHK;
1589
1590 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1591 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1592 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1593 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1594 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1595 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1596 curproxy->check_req = (char *)malloc(reqlen);
1597 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1598 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1599 } else {
1600 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1601 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1602 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1603 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1604 }
1605 }
1606 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001607 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001608 int cur_arg;
1609
1610 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1611 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001612 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001613
1614 curproxy->options |= PR_O_FWDFOR;
1615
1616 free(curproxy->fwdfor_hdr_name);
1617 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1618 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1619
1620 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1621 cur_arg = 2;
1622 while (*(args[cur_arg])) {
1623 if (!strcmp(args[cur_arg], "except")) {
1624 /* suboption except - needs additional argument for it */
1625 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1626 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1627 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001628 return -1;
1629 }
1630 /* flush useless bits */
1631 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001632 cur_arg += 2;
1633 } else if (!strcmp(args[cur_arg], "header")) {
1634 /* suboption header - needs additional argument for it */
1635 if (*(args[cur_arg+1]) == 0) {
1636 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1637 file, linenum, args[0], args[1], args[cur_arg]);
1638 return -1;
1639 }
1640 free(curproxy->fwdfor_hdr_name);
1641 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1642 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1643 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001644 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001645 /* unknown suboption - catchall */
1646 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1647 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001648 return -1;
1649 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001650 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001652 else {
1653 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1654 return -1;
1655 }
1656 return 0;
1657 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001658 else if (!strcmp(args[0], "default_backend")) {
1659 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1660 return 0;
1661
1662 if (*(args[1]) == 0) {
1663 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1664 return -1;
1665 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001666 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001667 curproxy->defbe.name = strdup(args[1]);
1668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001669 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001670 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1671 return 0;
1672
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001673 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1674 file, linenum, args[0]);
1675
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 /* enable reconnections to dispatch */
1677 curproxy->options |= PR_O_REDISP;
1678 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001679 else if (!strcmp(args[0], "http-check")) {
1680 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1681 return 0;
1682
1683 if (strcmp(args[1], "disable-on-404") == 0) {
1684 /* enable a graceful server shutdown on an HTTP 404 response */
1685 curproxy->options |= PR_O_DISABLE404;
1686 }
1687 else {
1688 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1689 return -1;
1690 }
1691 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001692 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001693 if (curproxy == &defproxy) {
1694 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1695 return -1;
1696 }
1697
Willy Tarreaub80c2302007-11-30 20:51:32 +01001698 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1699 return 0;
1700
1701 if (strcmp(args[1], "fail") == 0) {
1702 /* add a condition to fail monitor requests */
1703 int pol = ACL_COND_NONE;
1704 struct acl_cond *cond;
1705
1706 if (!strcmp(args[2], "if"))
1707 pol = ACL_COND_IF;
1708 else if (!strcmp(args[2], "unless"))
1709 pol = ACL_COND_UNLESS;
1710
1711 if (pol == ACL_COND_NONE) {
1712 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1713 file, linenum, args[0], args[1]);
1714 return -1;
1715 }
1716
1717 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1718 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1719 file, linenum, args[0], args[1]);
1720 return -1;
1721 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001722 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001723 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1724 }
1725 else {
1726 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1727 return -1;
1728 }
1729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001730#ifdef TPROXY
1731 else if (!strcmp(args[0], "transparent")) {
1732 /* enable transparent proxy connections */
1733 curproxy->options |= PR_O_TRANSP;
1734 }
1735#endif
1736 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001737 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1738 return 0;
1739
Willy Tarreaubaaee002006-06-26 02:48:02 +02001740 if (*(args[1]) == 0) {
1741 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1742 return -1;
1743 }
1744 curproxy->maxconn = atol(args[1]);
1745 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001746 else if (!strcmp(args[0], "backlog")) { /* backlog */
1747 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1748 return 0;
1749
1750 if (*(args[1]) == 0) {
1751 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1752 return -1;
1753 }
1754 curproxy->backlog = atol(args[1]);
1755 }
Willy Tarreau86034312006-12-29 00:10:33 +01001756 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001757 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1758 return 0;
1759
Willy Tarreau86034312006-12-29 00:10:33 +01001760 if (*(args[1]) == 0) {
1761 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1762 return -1;
1763 }
1764 curproxy->fullconn = atol(args[1]);
1765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1767 if (*(args[1]) == 0) {
1768 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1769 return -1;
1770 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001771 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1772 if (err) {
1773 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1774 file, linenum, *err);
1775 return -1;
1776 }
1777 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 }
1779 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1780 if (curproxy == &defproxy) {
1781 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1782 return -1;
1783 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001784 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1785 return 0;
1786
Willy Tarreaubaaee002006-06-26 02:48:02 +02001787 if (strchr(args[1], ':') == NULL) {
1788 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1789 return -1;
1790 }
1791 curproxy->dispatch_addr = *str2sa(args[1]);
1792 }
1793 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001794 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1795 return 0;
1796
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02001797 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001798 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1799 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1800 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001801 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802 }
1803 else if (!strcmp(args[0], "server")) { /* server address */
1804 int cur_arg;
1805 char *rport;
1806 char *raddr;
1807 short realport;
1808 int do_check;
1809
1810 if (curproxy == &defproxy) {
1811 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1812 return -1;
1813 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001814 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1815 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001816
1817 if (!*args[2]) {
1818 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1819 file, linenum, args[0]);
1820 return -1;
1821 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001822
1823 err = invalid_char(args[1]);
1824 if (err) {
1825 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1826 file, linenum, *err, args[1]);
1827 return -1;
1828 }
1829
Willy Tarreaubaaee002006-06-26 02:48:02 +02001830 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1831 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1832 return -1;
1833 }
1834
1835 /* the servers are linked backwards first */
1836 newsrv->next = curproxy->srv;
1837 curproxy->srv = newsrv;
1838 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001839 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001840
1841 LIST_INIT(&newsrv->pendconns);
1842 do_check = 0;
1843 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001844 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001845 newsrv->id = strdup(args[1]);
1846
1847 /* several ways to check the port component :
1848 * - IP => port=+0, relative
1849 * - IP: => port=+0, relative
1850 * - IP:N => port=N, absolute
1851 * - IP:+N => port=+N, relative
1852 * - IP:-N => port=-N, relative
1853 */
1854 raddr = strdup(args[2]);
1855 rport = strchr(raddr, ':');
1856 if (rport) {
1857 *rport++ = 0;
1858 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001859 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001860 newsrv->state |= SRV_MAPPORTS;
1861 } else {
1862 realport = 0;
1863 newsrv->state |= SRV_MAPPORTS;
1864 }
1865
1866 newsrv->addr = *str2sa(raddr);
1867 newsrv->addr.sin_port = htons(realport);
1868 free(raddr);
1869
1870 newsrv->curfd = -1; /* no health-check in progress */
1871 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001872 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1873 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001874 newsrv->rise = DEF_RISETIME;
1875 newsrv->fall = DEF_FALLTIME;
1876 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001877 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001878 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001879 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001880
Willy Tarreaubaaee002006-06-26 02:48:02 +02001881 cur_arg = 3;
1882 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001883 if (!strcmp(args[cur_arg], "id")) {
1884 struct server *target;
1885
1886 if (!*args[cur_arg + 1]) {
1887 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1888 file, linenum, args[cur_arg]);
1889 return -1;
1890 }
1891
1892 newsrv->puid = atol(args[cur_arg + 1]);
1893
1894 if (newsrv->puid< 1001) {
1895 Alert("parsing [%s:%d]: custom id has to be > 1000",
1896 file, linenum);
1897 return -1;
1898 }
1899
1900 for (target = proxy->srv; target; target = target->next)
1901 if (newsrv != target && newsrv->puid == target->puid) {
1902 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1903 file, linenum, newsrv->id, target->id);
1904 return -1;
1905 }
1906 cur_arg += 2;
1907 }
1908 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909 newsrv->cookie = strdup(args[cur_arg + 1]);
1910 newsrv->cklen = strlen(args[cur_arg + 1]);
1911 cur_arg += 2;
1912 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001913 else if (!strcmp(args[cur_arg], "redir")) {
1914 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1915 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1916 cur_arg += 2;
1917 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 else if (!strcmp(args[cur_arg], "rise")) {
1919 newsrv->rise = atol(args[cur_arg + 1]);
1920 newsrv->health = newsrv->rise;
1921 cur_arg += 2;
1922 }
1923 else if (!strcmp(args[cur_arg], "fall")) {
1924 newsrv->fall = atol(args[cur_arg + 1]);
1925 cur_arg += 2;
1926 }
1927 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001928 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1929 if (err) {
1930 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1931 file, linenum, *err, newsrv->id);
1932 return -1;
1933 }
Willy Tarreaue3838802009-03-21 18:58:32 +01001934 if (val <= 0) {
1935 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
1936 file, linenum, val, args[cur_arg], newsrv->id);
1937 return -1;
1938 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001939 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 cur_arg += 2;
1941 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001942 else if (!strcmp(args[cur_arg], "fastinter")) {
1943 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1944 if (err) {
1945 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1946 file, linenum, *err, newsrv->id);
1947 return -1;
1948 }
Willy Tarreaue3838802009-03-21 18:58:32 +01001949 if (val <= 0) {
1950 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
1951 file, linenum, val, args[cur_arg], newsrv->id);
1952 return -1;
1953 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001954 newsrv->fastinter = val;
1955 cur_arg += 2;
1956 }
1957 else if (!strcmp(args[cur_arg], "downinter")) {
1958 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1959 if (err) {
1960 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1961 file, linenum, *err, newsrv->id);
1962 return -1;
1963 }
Willy Tarreaue3838802009-03-21 18:58:32 +01001964 if (val <= 0) {
1965 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
1966 file, linenum, val, args[cur_arg], newsrv->id);
1967 return -1;
1968 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001969 newsrv->downinter = val;
1970 cur_arg += 2;
1971 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001972 else if (!strcmp(args[cur_arg], "addr")) {
1973 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001974 cur_arg += 2;
1975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976 else if (!strcmp(args[cur_arg], "port")) {
1977 newsrv->check_port = atol(args[cur_arg + 1]);
1978 cur_arg += 2;
1979 }
1980 else if (!strcmp(args[cur_arg], "backup")) {
1981 newsrv->state |= SRV_BACKUP;
1982 cur_arg ++;
1983 }
1984 else if (!strcmp(args[cur_arg], "weight")) {
1985 int w;
1986 w = atol(args[cur_arg + 1]);
1987 if (w < 1 || w > 256) {
1988 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1989 file, linenum, newsrv->id, w);
1990 return -1;
1991 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001992 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001993 cur_arg += 2;
1994 }
1995 else if (!strcmp(args[cur_arg], "minconn")) {
1996 newsrv->minconn = atol(args[cur_arg + 1]);
1997 cur_arg += 2;
1998 }
1999 else if (!strcmp(args[cur_arg], "maxconn")) {
2000 newsrv->maxconn = atol(args[cur_arg + 1]);
2001 cur_arg += 2;
2002 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002003 else if (!strcmp(args[cur_arg], "maxqueue")) {
2004 newsrv->maxqueue = atol(args[cur_arg + 1]);
2005 cur_arg += 2;
2006 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002007 else if (!strcmp(args[cur_arg], "slowstart")) {
2008 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002009 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002010 if (err) {
2011 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2012 file, linenum, *err, newsrv->id);
2013 return -1;
2014 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002015 if (val <= 0) {
2016 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2017 file, linenum, val, args[cur_arg], newsrv->id);
2018 return -1;
2019 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002020 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002021 cur_arg += 2;
2022 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002023 else if (!strcmp(args[cur_arg], "track")) {
2024
2025 if (!*args[cur_arg + 1]) {
2026 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2027 file, linenum);
2028 return -1;
2029 }
2030
2031 newsrv->trackit = strdup(args[cur_arg + 1]);
2032
2033 cur_arg += 2;
2034 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002035 else if (!strcmp(args[cur_arg], "check")) {
2036 global.maxsock++;
2037 do_check = 1;
2038 cur_arg += 1;
2039 }
2040 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
2041 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002042#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002043 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2044 file, linenum, "source", "usesrc");
2045#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002046 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2047 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002048#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049 return -1;
2050 }
2051 newsrv->state |= SRV_BIND_SRC;
2052 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
2053 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002054 while (*(args[cur_arg])) {
2055 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002056#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2057#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002058 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2059 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2060 file, linenum, "usesrc", "source");
2061 return -1;
2062 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002063#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002064 if (!*args[cur_arg + 1]) {
2065 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2066 file, linenum, "usesrc");
2067 return -1;
2068 }
2069 if (!strcmp(args[cur_arg + 1], "client")) {
2070 newsrv->state |= SRV_TPROXY_CLI;
2071 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2072 newsrv->state |= SRV_TPROXY_CIP;
2073 } else {
2074 newsrv->state |= SRV_TPROXY_ADDR;
2075 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2076 }
2077 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002078#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002079 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002080#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002081 cur_arg += 2;
2082 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002083#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002084 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002085 file, linenum, "usesrc");
2086 return -1;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002087#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2088 } /* "usesrc" */
2089
2090 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2091#ifdef SO_BINDTODEVICE
2092 if (!*args[cur_arg + 1]) {
2093 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2094 file, linenum, args[0]);
2095 return -1;
2096 }
2097 if (newsrv->iface_name)
2098 free(newsrv->iface_name);
2099
2100 newsrv->iface_name = strdup(args[cur_arg + 1]);
2101 newsrv->iface_len = strlen(newsrv->iface_name);
2102 global.last_checks |= LSTCHK_NETADM;
2103#else
2104 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2105 file, linenum, args[0], args[cur_arg]);
2106 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002107#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002108 cur_arg += 2;
2109 continue;
2110 }
2111 /* this keyword in not an option of "source" */
2112 break;
2113 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002115 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2116 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2117 file, linenum, "usesrc", "source");
2118 return -1;
2119 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002120 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002121 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'check', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002122 file, linenum, newsrv->id);
2123 return -1;
2124 }
2125 }
2126
2127 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002128 if (newsrv->trackit) {
2129 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2130 file, linenum);
2131 return -1;
2132 }
2133
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002134 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2135 newsrv->check_port = newsrv->check_addr.sin_port;
2136
Willy Tarreaubaaee002006-06-26 02:48:02 +02002137 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2138 newsrv->check_port = realport; /* by default */
2139 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002140 /* not yet valid, because no port was set on
2141 * the server either. We'll check if we have
2142 * a known port on the first listener.
2143 */
2144 struct listener *l;
2145 l = curproxy->listen;
2146 if (l) {
2147 int port;
2148 port = (l->addr.ss_family == AF_INET6)
2149 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2150 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2151 newsrv->check_port = port;
2152 }
2153 }
2154 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2156 file, linenum, newsrv->id);
2157 return -1;
2158 }
2159 newsrv->state |= SRV_CHECKED;
2160 }
2161
2162 if (newsrv->state & SRV_BACKUP)
2163 curproxy->srv_bck++;
2164 else
2165 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002166
2167 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002168 }
2169 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002170 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171 int facility;
2172
2173 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2174 curproxy->logfac1 = global.logfac1;
2175 curproxy->logsrv1 = global.logsrv1;
2176 curproxy->loglev1 = global.loglev1;
2177 curproxy->logfac2 = global.logfac2;
2178 curproxy->logsrv2 = global.logsrv2;
2179 curproxy->loglev2 = global.loglev2;
2180 }
2181 else if (*(args[1]) && *(args[2])) {
2182 int level;
2183
2184 facility = get_log_facility(args[2]);
2185 if (facility < 0) {
2186 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2187 exit(1);
2188 }
2189
2190 level = 7; /* max syslog level = debug */
2191 if (*(args[3])) {
2192 level = get_log_level(args[3]);
2193 if (level < 0) {
2194 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2195 exit(1);
2196 }
2197 }
2198
Robert Tsai81ae1952007-12-05 10:47:29 +01002199 if (args[1][0] == '/') {
2200 logsrv.u.addr.sa_family = AF_UNIX;
2201 logsrv.u.un = *str2sun(args[1]);
2202 } else {
2203 logsrv.u.addr.sa_family = AF_INET;
2204 logsrv.u.in = *str2sa(args[1]);
2205 if (!logsrv.u.in.sin_port) {
2206 logsrv.u.in.sin_port =
2207 htons(SYSLOG_PORT);
2208 }
2209 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002210
2211 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002212 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213 curproxy->logfac1 = facility;
2214 curproxy->loglev1 = level;
2215 }
2216 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002217 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 curproxy->logfac2 = facility;
2219 curproxy->loglev2 = level;
2220 }
2221 else {
2222 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2223 return -1;
2224 }
2225 }
2226 else {
2227 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2228 file, linenum);
2229 return -1;
2230 }
2231 }
2232 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002233 int cur_arg;
2234
Willy Tarreau977b8e42006-12-29 14:19:17 +01002235 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2236 return 0;
2237
Willy Tarreaubaaee002006-06-26 02:48:02 +02002238 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002239 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2240 file, linenum, "source", "usesrc", "interface");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241 return -1;
2242 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002243
2244 /* we must first clear any optional default setting */
2245 curproxy->options &= ~PR_O_TPXY_MASK;
2246 free(curproxy->iface_name);
2247 curproxy->iface_name = NULL;
2248 curproxy->iface_len = 0;
2249
Willy Tarreaubaaee002006-06-26 02:48:02 +02002250 curproxy->source_addr = *str2sa(args[1]);
2251 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002252
2253 cur_arg = 2;
2254 while (*(args[cur_arg])) {
2255 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002256#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2257#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002258 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2259 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2260 file, linenum, "usesrc");
2261 return -1;
2262 }
2263#endif
2264 if (!*args[cur_arg + 1]) {
2265 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2266 file, linenum, "usesrc");
2267 return -1;
2268 }
2269
2270 if (!strcmp(args[cur_arg + 1], "client")) {
2271 curproxy->options |= PR_O_TPXY_CLI;
2272 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2273 curproxy->options |= PR_O_TPXY_CIP;
2274 } else {
2275 curproxy->options |= PR_O_TPXY_ADDR;
2276 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2277 }
2278 global.last_checks |= LSTCHK_NETADM;
2279#if !defined(CONFIG_HAP_LINUX_TPROXY)
2280 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002281#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002282#else /* no TPROXY support */
2283 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002284 file, linenum, "usesrc");
2285 return -1;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002286#endif
2287 cur_arg += 2;
2288 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002289 }
2290
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002291 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2292#ifdef SO_BINDTODEVICE
2293 if (!*args[cur_arg + 1]) {
2294 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2295 file, linenum, args[0]);
2296 return -1;
2297 }
2298 if (curproxy->iface_name)
2299 free(curproxy->iface_name);
2300
2301 curproxy->iface_name = strdup(args[cur_arg + 1]);
2302 curproxy->iface_len = strlen(curproxy->iface_name);
2303 global.last_checks |= LSTCHK_NETADM;
2304#else
2305 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2306 file, linenum, args[0], args[cur_arg]);
2307 return -1;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002308#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002309 cur_arg += 2;
2310 continue;
2311 }
2312 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2313 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002314 return -1;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002316 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002317 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2318 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2319 file, linenum, "usesrc", "source");
2320 return -1;
2321 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2323 regex_t *preg;
2324 if (curproxy == &defproxy) {
2325 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2326 return -1;
2327 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002328 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2329 return 0;
2330
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 if (*(args[1]) == 0 || *(args[2]) == 0) {
2332 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2333 file, linenum, args[0]);
2334 return -1;
2335 }
2336
2337 preg = calloc(1, sizeof(regex_t));
2338 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2339 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2340 return -1;
2341 }
2342
2343 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2344 if (err) {
2345 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2346 file, linenum, *err);
2347 return -1;
2348 }
2349 }
2350 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2351 regex_t *preg;
2352 if (curproxy == &defproxy) {
2353 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2354 return -1;
2355 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002356 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2357 return 0;
2358
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 if (*(args[1]) == 0) {
2360 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2361 return -1;
2362 }
2363
2364 preg = calloc(1, sizeof(regex_t));
2365 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2366 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2367 return -1;
2368 }
2369
2370 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2371 }
2372 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2373 regex_t *preg;
2374 if (curproxy == &defproxy) {
2375 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2376 return -1;
2377 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002378 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2379 return 0;
2380
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 if (*(args[1]) == 0) {
2382 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2383 return -1;
2384 }
2385
2386 preg = calloc(1, sizeof(regex_t));
2387 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2388 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2389 return -1;
2390 }
2391
2392 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2393 }
2394 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2395 regex_t *preg;
2396 if (curproxy == &defproxy) {
2397 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2398 return -1;
2399 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002400 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2401 return 0;
2402
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 if (*(args[1]) == 0) {
2404 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2405 return -1;
2406 }
2407
2408 preg = calloc(1, sizeof(regex_t));
2409 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2410 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2411 return -1;
2412 }
2413
2414 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2415 }
2416 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2417 regex_t *preg;
2418 if (curproxy == &defproxy) {
2419 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2420 return -1;
2421 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002422 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2423 return 0;
2424
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 if (*(args[1]) == 0) {
2426 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2427 return -1;
2428 }
2429
2430 preg = calloc(1, sizeof(regex_t));
2431 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2432 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2433 return -1;
2434 }
2435
2436 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2437 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002438 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2439 regex_t *preg;
2440 if (curproxy == &defproxy) {
2441 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2442 return -1;
2443 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002444 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2445 return 0;
2446
Willy Tarreaub8750a82006-09-03 09:56:00 +02002447 if (*(args[1]) == 0) {
2448 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2449 return -1;
2450 }
2451
2452 preg = calloc(1, sizeof(regex_t));
2453 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2454 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2455 return -1;
2456 }
2457
2458 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2459 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002460 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2461 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002462 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002463 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2464 return -1;
2465 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002466 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2467 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002468
Willy Tarreau977b8e42006-12-29 14:19:17 +01002469 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002470 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2471 file, linenum, args[0]);
2472 return -1;
2473 }
2474
2475 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002476 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002477 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2478 }
2479
2480 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2481 }
2482 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2483 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002484 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002485 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2486 return -1;
2487 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002488 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2489 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002490
Willy Tarreau977b8e42006-12-29 14:19:17 +01002491 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002492 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2493 file, linenum, args[0]);
2494 return -1;
2495 }
2496
2497 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002498 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002499 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2500 }
2501
2502 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2503 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2505 regex_t *preg;
2506 if (curproxy == &defproxy) {
2507 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2508 return -1;
2509 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002510 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2511 return 0;
2512
Willy Tarreaubaaee002006-06-26 02:48:02 +02002513 if (*(args[1]) == 0 || *(args[2]) == 0) {
2514 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2515 file, linenum, args[0]);
2516 return -1;
2517 }
2518
2519 preg = calloc(1, sizeof(regex_t));
2520 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2521 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2522 return -1;
2523 }
2524
2525 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2526 if (err) {
2527 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2528 file, linenum, *err);
2529 return -1;
2530 }
2531 }
2532 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2533 regex_t *preg;
2534 if (curproxy == &defproxy) {
2535 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2536 return -1;
2537 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002538 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2539 return 0;
2540
Willy Tarreaubaaee002006-06-26 02:48:02 +02002541 if (*(args[1]) == 0) {
2542 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2543 return -1;
2544 }
2545
2546 preg = calloc(1, sizeof(regex_t));
2547 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2548 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2549 return -1;
2550 }
2551
2552 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2553 }
2554 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2555 regex_t *preg;
2556 if (curproxy == &defproxy) {
2557 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2558 return -1;
2559 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002560 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2561 return 0;
2562
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 if (*(args[1]) == 0) {
2564 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2565 return -1;
2566 }
2567
2568 preg = calloc(1, sizeof(regex_t));
2569 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2570 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2571 return -1;
2572 }
2573
2574 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2575 }
2576 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2577 regex_t *preg;
2578 if (curproxy == &defproxy) {
2579 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2580 return -1;
2581 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002582 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2583 return 0;
2584
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 if (*(args[1]) == 0) {
2586 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2587 return -1;
2588 }
2589
2590 preg = calloc(1, sizeof(regex_t));
2591 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2592 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2593 return -1;
2594 }
2595
2596 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2597 }
2598 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2599 regex_t *preg;
2600 if (curproxy == &defproxy) {
2601 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2602 return -1;
2603 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002604 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2605 return 0;
2606
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 if (*(args[1]) == 0) {
2608 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2609 return -1;
2610 }
2611
2612 preg = calloc(1, sizeof(regex_t));
2613 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2614 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2615 return -1;
2616 }
2617
2618 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2619 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002620 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2621 regex_t *preg;
2622 if (curproxy == &defproxy) {
2623 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2624 return -1;
2625 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002626 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2627 return 0;
2628
Willy Tarreaub8750a82006-09-03 09:56:00 +02002629 if (*(args[1]) == 0) {
2630 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2631 return -1;
2632 }
2633
2634 preg = calloc(1, sizeof(regex_t));
2635 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2636 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2637 return -1;
2638 }
2639
2640 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2643 if (curproxy == &defproxy) {
2644 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2645 return -1;
2646 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002647 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2648 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649
2650 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2651 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2652 return 0;
2653 }
2654
2655 if (*(args[1]) == 0) {
2656 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2657 return -1;
2658 }
2659
2660 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2661 }
2662 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2663 regex_t *preg;
2664
2665 if (*(args[1]) == 0 || *(args[2]) == 0) {
2666 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2667 file, linenum, args[0]);
2668 return -1;
2669 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002670 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2671 return 0;
2672
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673 preg = calloc(1, sizeof(regex_t));
2674 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2675 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2676 return -1;
2677 }
2678
2679 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2680 if (err) {
2681 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2682 file, linenum, *err);
2683 return -1;
2684 }
2685 }
2686 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2687 regex_t *preg;
2688 if (curproxy == &defproxy) {
2689 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2690 return -1;
2691 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002692 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2693 return 0;
2694
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695 if (*(args[1]) == 0) {
2696 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2697 return -1;
2698 }
2699
2700 preg = calloc(1, sizeof(regex_t));
2701 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2702 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2703 return -1;
2704 }
2705
2706 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2707 if (err) {
2708 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2709 file, linenum, *err);
2710 return -1;
2711 }
2712 }
2713 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2714 regex_t *preg;
2715 if (curproxy == &defproxy) {
2716 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2717 return -1;
2718 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002719 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2720 return 0;
2721
Willy Tarreaubaaee002006-06-26 02:48:02 +02002722 if (*(args[1]) == 0) {
2723 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2724 return -1;
2725 }
2726
2727 preg = calloc(1, sizeof(regex_t));
2728 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2729 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2730 return -1;
2731 }
2732
2733 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2734 if (err) {
2735 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2736 file, linenum, *err);
2737 return -1;
2738 }
2739 }
2740 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2741 regex_t *preg;
2742 if (curproxy == &defproxy) {
2743 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2744 return -1;
2745 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002746 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2747 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748
2749 if (*(args[1]) == 0 || *(args[2]) == 0) {
2750 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2751 file, linenum, args[0]);
2752 return -1;
2753 }
2754
2755 preg = calloc(1, sizeof(regex_t));
2756 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2757 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2758 return -1;
2759 }
2760
2761 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2762 if (err) {
2763 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2764 file, linenum, *err);
2765 return -1;
2766 }
2767 }
2768 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2769 regex_t *preg;
2770 if (curproxy == &defproxy) {
2771 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2772 return -1;
2773 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002774 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2775 return 0;
2776
Willy Tarreaubaaee002006-06-26 02:48:02 +02002777 if (*(args[1]) == 0) {
2778 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2779 return -1;
2780 }
2781
2782 preg = calloc(1, sizeof(regex_t));
2783 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2784 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2785 return -1;
2786 }
2787
2788 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2789 if (err) {
2790 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2791 file, linenum, *err);
2792 return -1;
2793 }
2794 }
2795 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2796 regex_t *preg;
2797 if (curproxy == &defproxy) {
2798 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2799 return -1;
2800 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002801 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2802 return 0;
2803
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804 if (*(args[1]) == 0) {
2805 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2806 return -1;
2807 }
2808
2809 preg = calloc(1, sizeof(regex_t));
2810 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2811 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2812 return -1;
2813 }
2814
2815 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2816 if (err) {
2817 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2818 file, linenum, *err);
2819 return -1;
2820 }
2821 }
2822 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2823 if (curproxy == &defproxy) {
2824 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2825 return -1;
2826 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002827 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2828 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002829
2830 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2831 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2832 return 0;
2833 }
2834
2835 if (*(args[1]) == 0) {
2836 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2837 return -1;
2838 }
2839
2840 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2841 }
2842 else if (!strcmp(args[0], "errorloc") ||
2843 !strcmp(args[0], "errorloc302") ||
2844 !strcmp(args[0], "errorloc303")) { /* error location */
2845 int errnum, errlen;
2846 char *err;
2847
Willy Tarreau977b8e42006-12-29 14:19:17 +01002848 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2849 return 0;
2850
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002852 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002853 return -1;
2854 }
2855
2856 errnum = atol(args[1]);
2857 if (!strcmp(args[0], "errorloc303")) {
2858 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2859 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2860 } else {
2861 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2862 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2863 }
2864
Willy Tarreau0f772532006-12-23 20:51:41 +01002865 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2866 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002867 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002868 curproxy->errmsg[rc].str = err;
2869 curproxy->errmsg[rc].len = errlen;
2870 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002873
2874 if (rc >= HTTP_ERR_SIZE) {
2875 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2876 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 free(err);
2878 }
2879 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002880 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2881 int errnum, errlen, fd;
2882 char *err;
2883 struct stat stat;
2884
2885 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2886 return 0;
2887
2888 if (*(args[2]) == 0) {
2889 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2890 return -1;
2891 }
2892
2893 fd = open(args[2], O_RDONLY);
2894 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2895 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2896 file, linenum, args[2], args[1]);
2897 if (fd >= 0)
2898 close(fd);
2899 return -1;
2900 }
2901
2902 if (stat.st_size <= BUFSIZE) {
2903 errlen = stat.st_size;
2904 } else {
2905 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2906 file, linenum, args[2], BUFSIZE);
2907 errlen = BUFSIZE;
2908 }
2909
2910 err = malloc(errlen); /* malloc() must succeed during parsing */
2911 errnum = read(fd, err, errlen);
2912 if (errnum != errlen) {
2913 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2914 file, linenum, args[2], args[1]);
2915 close(fd);
2916 free(err);
2917 return -1;
2918 }
2919 close(fd);
2920
2921 errnum = atol(args[1]);
2922 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2923 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002924 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002925 curproxy->errmsg[rc].str = err;
2926 curproxy->errmsg[rc].len = errlen;
2927 break;
2928 }
2929 }
2930
2931 if (rc >= HTTP_ERR_SIZE) {
2932 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2933 file, linenum, errnum);
2934 free(err);
2935 }
2936 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002937 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002938 struct cfg_kw_list *kwl;
2939 int index;
2940
2941 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2942 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2943 if (kwl->kw[index].section != CFG_LISTEN)
2944 continue;
2945 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2946 /* prepare error message just in case */
2947 snprintf(trash, sizeof(trash),
2948 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002949 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2950 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002951 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2952 return -1;
2953 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002954 else if (rc > 0) {
2955 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2956 return 0;
2957 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002958 return 0;
2959 }
2960 }
2961 }
2962
Willy Tarreau6daf3432008-01-22 16:44:08 +01002963 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002964 return -1;
2965 }
2966 return 0;
2967}
2968
2969
2970/*
2971 * This function reads and parses the configuration file given in the argument.
2972 * returns 0 if OK, -1 if error.
2973 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002974int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002975{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002976 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002977 FILE *f;
2978 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002979 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 int confsect = CFG_NONE;
2981
2982 struct proxy *curproxy = NULL;
2983 struct server *newsrv = NULL;
2984
2985 if ((f=fopen(file,"r")) == NULL)
2986 return -1;
2987
2988 init_default_instance();
2989
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002990 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002991 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002992 char *end;
2993 char *args[MAX_LINE_ARGS + 1];
2994 char *line = thisline;
2995
Willy Tarreaubaaee002006-06-26 02:48:02 +02002996 linenum++;
2997
2998 end = line + strlen(line);
2999
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003000 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3001 /* Check if we reached the limit and the last char is not \n.
3002 * Watch out for the last line without the terminating '\n'!
3003 */
3004 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
3005 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003006 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003007 }
3008
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003010 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003011 line++;
3012
3013 arg = 0;
3014 args[arg] = line;
3015
3016 while (*line && arg < MAX_LINE_ARGS) {
3017 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3018 * C equivalent value. Other combinations left unchanged (eg: \1).
3019 */
3020 if (*line == '\\') {
3021 int skip = 0;
3022 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3023 *line = line[1];
3024 skip = 1;
3025 }
3026 else if (line[1] == 'r') {
3027 *line = '\r';
3028 skip = 1;
3029 }
3030 else if (line[1] == 'n') {
3031 *line = '\n';
3032 skip = 1;
3033 }
3034 else if (line[1] == 't') {
3035 *line = '\t';
3036 skip = 1;
3037 }
3038 else if (line[1] == 'x') {
3039 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3040 unsigned char hex1, hex2;
3041 hex1 = toupper(line[2]) - '0';
3042 hex2 = toupper(line[3]) - '0';
3043 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3044 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3045 *line = (hex1<<4) + hex2;
3046 skip = 3;
3047 }
3048 else {
3049 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003050 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 }
3052 }
3053 if (skip) {
3054 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3055 end -= skip;
3056 }
3057 line++;
3058 }
3059 else if (*line == '#' || *line == '\n' || *line == '\r') {
3060 /* end of string, end of loop */
3061 *line = 0;
3062 break;
3063 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003064 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003065 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003066 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003067 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003068 line++;
3069 args[++arg] = line;
3070 }
3071 else {
3072 line++;
3073 }
3074 }
3075
3076 /* empty line */
3077 if (!**args)
3078 continue;
3079
Willy Tarreau540abe42007-05-02 20:50:16 +02003080 /* zero out remaining args and ensure that at least one entry
3081 * is zeroed out.
3082 */
3083 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003084 args[arg] = line;
3085 }
3086
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003087 if (!strcmp(args[0], "no")) {
3088 inv = 1;
3089 for (arg=0; *args[arg+1]; arg++)
3090 args[arg] = args[arg+1]; // shift args after inversion
3091 }
3092
3093 if (inv && strcmp(args[0], "option")) {
3094 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003095 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003096 }
3097
Willy Tarreau977b8e42006-12-29 14:19:17 +01003098 if (!strcmp(args[0], "listen") ||
3099 !strcmp(args[0], "frontend") ||
3100 !strcmp(args[0], "backend") ||
3101 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003102 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003104 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003105 cursection = strdup(args[0]);
3106 }
3107 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003109 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003110 cursection = strdup(args[0]);
3111 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 /* else it's a section keyword */
3113
3114 switch (confsect) {
3115 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003116 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003117 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 break;
3119 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003120 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003121 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 break;
3123 default:
3124 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003125 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003128 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003129 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 fclose(f);
3131
3132 /*
3133 * Now, check for the integrity of all that we have collected.
3134 */
3135
3136 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003137 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138
Willy Tarreau55bc0f82009-03-15 14:51:53 +01003139 /* first, we will invert the proxy list order */
3140 curproxy = NULL;
3141 while (proxy) {
3142 struct proxy *next;
3143
3144 next = proxy->next;
3145 proxy->next = curproxy;
3146 curproxy = proxy;
3147 if (!next)
3148 break;
3149 proxy = next;
3150 }
3151
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 if ((curproxy = proxy) == NULL) {
3153 Alert("parsing %s : no <listen> line. Nothing to do !\n",
3154 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003155 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003156 }
3157
3158 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003159 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003160 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003161
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003163 /* ensure we don't keep listeners uselessly bound */
3164 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003165 curproxy = curproxy->next;
3166 continue;
3167 }
3168
Willy Tarreauff01a212009-03-15 13:46:16 +01003169 switch (curproxy->mode) {
3170 case PR_MODE_HEALTH:
3171 cfgerr += proxy_cfg_ensure_no_http(curproxy, file);
3172 if (!(curproxy->cap & PR_CAP_FE)) {
3173 Alert("parsing %s : %s '%s' cannot be in health mode as it has no frontend capability.\n",
3174 file, proxy_type_str(curproxy), curproxy->id);
3175 cfgerr++;
3176 }
3177
3178 if (curproxy->srv != NULL)
3179 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
3180 file, proxy_type_str(curproxy), curproxy->id);
3181 break;
3182
3183 case PR_MODE_TCP:
3184 cfgerr += proxy_cfg_ensure_no_http(curproxy, file);
3185 break;
3186
3187 case PR_MODE_HTTP:
3188 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
3189 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
3190 file, curproxy->id);
3191 cfgerr++;
3192 }
3193 break;
3194 }
3195
3196 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003197 Alert("parsing %s : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003198 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 cfgerr++;
3200 }
Willy Tarreauff01a212009-03-15 13:46:16 +01003201
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003202 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
3203 if (curproxy->lbprm.algo & BE_LB_ALGO) {
3204 if (curproxy->options & PR_O_TRANSP) {
3205 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
3206 file, proxy_type_str(curproxy), curproxy->id);
3207 cfgerr++;
3208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003210 else if (curproxy->srv == NULL) {
3211 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
3212 file, proxy_type_str(curproxy), curproxy->id);
3213 cfgerr++;
3214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003216 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
3217 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
3218 file, proxy_type_str(curproxy), curproxy->id);
3219 }
3220 }
3221 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
3222 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
3223 /* If no LB algo is set in a backend, and we're not in
3224 * transparent mode, dispatch mode nor proxy mode, we
3225 * want to use balance roundrobin by default.
3226 */
3227 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3228 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 }
3230 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003231
Willy Tarreau82936582007-11-30 15:20:09 +01003232 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3233 curproxy->options &= ~PR_O_DISABLE404;
3234 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3235 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
3236 }
3237
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003238 /* if a default backend was specified, let's find it */
3239 if (curproxy->defbe.name) {
3240 struct proxy *target;
3241
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003242 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3243 if (!target) {
3244 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3245 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003246 cfgerr++;
3247 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003248 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3249 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003250 } else {
3251 free(curproxy->defbe.name);
3252 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003253 /* we force the backend to be present on at least all of
3254 * the frontend's processes.
3255 */
3256 target->bind_proc = curproxy->bind_proc ?
3257 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003258 }
3259 }
3260
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003261 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003262 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3263 /* map jump target for ACT_SETBE in req_rep chain */
3264 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003265 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003266 struct proxy *target;
3267
Willy Tarreaua496b602006-12-17 23:15:24 +01003268 if (exp->action != ACT_SETBE)
3269 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003270
3271 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3272 if (!target) {
3273 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3274 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003275 cfgerr++;
3276 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003277 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3278 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003279 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003280 } else {
3281 free((void *)exp->replace);
3282 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003283 /* we force the backend to be present on at least all of
3284 * the frontend's processes.
3285 */
3286 target->bind_proc = curproxy->bind_proc ?
3287 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01003288 }
3289 }
3290 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003291
3292 /* find the target proxy for 'use_backend' rules */
3293 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003294 struct proxy *target;
3295
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003296 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003297
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003298 if (!target) {
3299 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3300 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003301 cfgerr++;
3302 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003303 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3304 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003305 cfgerr++;
3306 } else {
3307 free((void *)rule->be.name);
3308 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003309 /* we force the backend to be present on at least all of
3310 * the frontend's processes.
3311 */
3312 target->bind_proc = curproxy->bind_proc ?
3313 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003314 }
3315 }
3316
Willy Tarreau2738a142006-07-08 17:28:09 +02003317 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003318 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003319 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003320 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003321 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003322 " | While not properly invalid, you will certainly encounter various problems\n"
3323 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003324 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003325 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003326 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003327
Willy Tarreau1fa31262007-12-03 00:36:16 +01003328 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3329 * We must still support older configurations, so let's find out whether those
3330 * parameters have been set or must be copied from contimeouts.
3331 */
3332 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003333 if (!curproxy->timeout.tarpit ||
3334 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003335 /* tarpit timeout not set. We search in the following order:
3336 * default.tarpit, curr.connect, default.connect.
3337 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003338 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003339 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003340 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003341 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003342 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003343 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003344 }
3345 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003346 (!curproxy->timeout.queue ||
3347 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003348 /* queue timeout not set. We search in the following order:
3349 * default.queue, curr.connect, default.connect.
3350 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003351 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003352 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003353 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003354 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003355 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003356 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003357 }
3358 }
3359
Willy Tarreauf3c69202006-07-09 16:42:34 +02003360 if (curproxy->options & PR_O_SSL3_CHK) {
3361 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3362 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3363 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3364 }
3365
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003366 /* The small pools required for the capture lists */
3367 if (curproxy->nb_req_cap)
3368 curproxy->req_cap_pool = create_pool("ptrcap",
3369 curproxy->nb_req_cap * sizeof(char *),
3370 MEM_F_SHARED);
3371 if (curproxy->nb_rsp_cap)
3372 curproxy->rsp_cap_pool = create_pool("ptrcap",
3373 curproxy->nb_rsp_cap * sizeof(char *),
3374 MEM_F_SHARED);
3375
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003376 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3377 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3378 MEM_F_SHARED);
3379
Willy Tarreau86034312006-12-29 00:10:33 +01003380 /* for backwards compatibility with "listen" instances, if
3381 * fullconn is not set but maxconn is set, then maxconn
3382 * is used.
3383 */
3384 if (!curproxy->fullconn)
3385 curproxy->fullconn = curproxy->maxconn;
3386
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 /* first, we will invert the servers list order */
3388 newsrv = NULL;
3389 while (curproxy->srv) {
3390 struct server *next;
3391
3392 next = curproxy->srv->next;
3393 curproxy->srv->next = newsrv;
3394 newsrv = curproxy->srv;
3395 if (!next)
3396 break;
3397 curproxy->srv = next;
3398 }
3399
Willy Tarreau20697042007-11-15 23:26:18 +01003400 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003401 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402
Willy Tarreaub625a082007-11-26 01:15:43 +01003403 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003404 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003405 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003406 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3407 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003408 else
3409 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410
3411 if (curproxy->options & PR_O_LOGASAP)
3412 curproxy->to_log &= ~LW_BYTES;
3413
Willy Tarreaubaaee002006-06-26 02:48:02 +02003414 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003415 * ensure that we're not cross-dressing a TCP server into HTTP.
3416 */
3417 newsrv = curproxy->srv;
3418 while (newsrv != NULL) {
3419 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3420 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3421 file, proxy_type_str(curproxy), curproxy->id, linenum);
3422 goto err;
3423 }
3424 newsrv = newsrv->next;
3425 }
3426
3427 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003428 * If this server supports a maxconn parameter, it needs a dedicated
3429 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003430 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 */
3432 newsrv = curproxy->srv;
3433 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003434 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003435 /* Only 'minconn' was specified, or it was higher than or equal
3436 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3437 * this will avoid further useless expensive computations.
3438 */
3439 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003440 } else if (newsrv->maxconn && !newsrv->minconn) {
3441 /* minconn was not specified, so we set it to maxconn */
3442 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003443 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3444 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003445 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003446 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447 }
3448
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003449 if (newsrv->trackit) {
3450 struct proxy *px;
3451 struct server *srv;
3452 char *pname, *sname;
3453
3454 pname = newsrv->trackit;
3455 sname = strrchr(pname, '/');
3456
3457 if (sname)
3458 *sname++ = '\0';
3459 else {
3460 sname = pname;
3461 pname = NULL;
3462 }
3463
3464 if (pname) {
3465 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3466 if (!px) {
3467 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3468 file, proxy_type_str(curproxy), curproxy->id,
3469 newsrv->id, pname);
3470 return -1;
3471 }
3472 } else
3473 px = curproxy;
3474
3475 srv = findserver(px, sname);
3476 if (!srv) {
3477 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3478 file, proxy_type_str(curproxy), curproxy->id,
3479 newsrv->id, sname);
3480 return -1;
3481 }
3482
3483 if (!(srv->state & SRV_CHECKED)) {
3484 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3485 "tracing as it does not have checks enabled.\n",
3486 file, proxy_type_str(curproxy), curproxy->id,
3487 newsrv->id, px->id, srv->id);
3488 return -1;
3489 }
3490
3491 if (curproxy != px &&
3492 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3493 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3494 "tracing: disable-on-404 option inconsistency.\n",
3495 file, proxy_type_str(curproxy), curproxy->id,
3496 newsrv->id, px->id, srv->id);
3497 return -1;
3498 }
3499
3500 newsrv->tracked = srv;
3501 newsrv->tracknext = srv->tracknext;
3502 srv->tracknext = newsrv;
3503
3504 free(newsrv->trackit);
3505 }
3506
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 newsrv = newsrv->next;
3508 }
3509
Willy Tarreaue6b98942007-10-29 01:09:36 +01003510 /* adjust this proxy's listeners */
3511 listener = curproxy->listen;
3512 while (listener) {
3513 if (curproxy->options & PR_O_TCP_NOLING)
3514 listener->options |= LI_O_NOLINGER;
3515 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003516 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003517 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003518 listener->accept = event_accept;
3519 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003520 listener->handler = process_session;
3521
3522 if (curproxy->mode == PR_MODE_HTTP)
3523 listener->analysers |= AN_REQ_HTTP_HDR;
3524
Willy Tarreaud869b242009-03-15 14:43:58 +01003525 if (curproxy->tcp_req.inspect_delay ||
3526 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreau3bc13772008-12-07 11:50:35 +01003527 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003528
3529 listener = listener->next;
3530 }
3531
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532 curproxy = curproxy->next;
3533 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003534
Willy Tarreaubaaee002006-06-26 02:48:02 +02003535 if (cfgerr > 0) {
3536 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003537 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003539
3540 /*
3541 * Recount currently required checks.
3542 */
3543
3544 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3545 int optnum;
3546
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003547 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3548 if (curproxy->options & cfg_opts[optnum].val)
3549 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003550
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003551 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3552 if (curproxy->options2 & cfg_opts2[optnum].val)
3553 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003554 }
3555
Willy Tarreaua534fea2008-08-03 12:19:50 +02003556 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003557 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003558 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003559
3560 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003561 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003562 cursection = NULL;
3563 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003564}
3565
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003566/*
3567 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3568 * parsing sessions.
3569 */
3570void cfg_register_keywords(struct cfg_kw_list *kwl)
3571{
3572 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3573}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003574
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003575/*
3576 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3577 */
3578void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3579{
3580 LIST_DEL(&kwl->list);
3581 LIST_INIT(&kwl->list);
3582}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003583
3584/*
3585 * Local variables:
3586 * c-indent-level: 8
3587 * c-basic-offset: 8
3588 * End:
3589 */