blob: 09f63a40c7126761e8f9570bf08efeac3ce4ac7a [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>
35#include <types/polling.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036
Willy Tarreaueb0c6142007-05-07 00:53:22 +020037#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010039#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020041#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010044#include <proto/protocols.h>
45#include <proto/proto_tcp.h>
46#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010047#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <proto/server.h>
49#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 */
83static const struct {
84 const char *name;
85 unsigned int val;
86 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010087 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010088} cfg_opts[] =
89{
Willy Tarreau4fee4e92007-01-06 21:09:17 +010090 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010091 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010092 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010094 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
95 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
96 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
97 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
98 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
99 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
100 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
101 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100102 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100103 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
104 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100105#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100106 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
107#endif
108#ifdef TPROXY
109 { "transparent", PR_O_TRANSP, PR_CAP_FE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100110#endif
111
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100112 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113};
114
Willy Tarreaubaaee002006-06-26 02:48:02 +0200115
Willy Tarreau6daf3432008-01-22 16:44:08 +0100116static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200117static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
118int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
119int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
120
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200121/* List head of all known configuration keywords */
122static struct cfg_kw_list cfg_keywords = {
123 .list = LIST_HEAD_INIT(cfg_keywords.list)
124};
125
Willy Tarreaubaaee002006-06-26 02:48:02 +0200126/*
127 * converts <str> to a list of listeners which are dynamically allocated.
128 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
129 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
130 * - <port> is a numerical port from 1 to 65535 ;
131 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
132 * This can be repeated as many times as necessary, separated by a coma.
133 * The <tail> argument is a pointer to a current list which should be appended
134 * to the tail of the new list. The pointer to the new list is returned.
135 */
136static struct listener *str2listener(char *str, struct listener *tail)
137{
138 struct listener *l;
139 char *c, *next, *range, *dupstr;
140 int port, end;
141
142 next = dupstr = strdup(str);
143
144 while (next && *next) {
145 struct sockaddr_storage ss;
146
147 str = next;
148 /* 1) look for the end of the first address */
149 if ((next = strrchr(str, ',')) != NULL) {
150 *next++ = 0;
151 }
152
153 /* 2) look for the addr/port delimiter, it's the last colon. */
154 if ((range = strrchr(str, ':')) == NULL) {
155 Alert("Missing port number: '%s'\n", str);
156 goto fail;
157 }
158
159 *range++ = 0;
160
161 if (strrchr(str, ':') != NULL) {
162 /* IPv6 address contains ':' */
163 memset(&ss, 0, sizeof(ss));
164 ss.ss_family = AF_INET6;
165
166 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
167 Alert("Invalid server address: '%s'\n", str);
168 goto fail;
169 }
170 }
171 else {
172 memset(&ss, 0, sizeof(ss));
173 ss.ss_family = AF_INET;
174
175 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
176 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
177 }
178 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
179 struct hostent *he;
180
181 if ((he = gethostbyname(str)) == NULL) {
182 Alert("Invalid server name: '%s'\n", str);
183 goto fail;
184 }
185 else
186 ((struct sockaddr_in *)&ss)->sin_addr =
187 *(struct in_addr *) *(he->h_addr_list);
188 }
189 }
190
191 /* 3) look for the port-end delimiter */
192 if ((c = strchr(range, '-')) != NULL) {
193 *c++ = 0;
194 end = atol(c);
195 }
196 else {
197 end = atol(range);
198 }
199
200 port = atol(range);
201
202 if (port < 1 || port > 65535) {
203 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
204 goto fail;
205 }
206
207 if (end < 1 || end > 65535) {
208 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
209 goto fail;
210 }
211
212 for (; port <= end; port++) {
213 l = (struct listener *)calloc(1, sizeof(struct listener));
214 l->next = tail;
215 tail = l;
216
217 l->fd = -1;
218 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100219 l->state = LI_INIT;
220
221 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100223 tcpv6_add_listener(l);
224 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100226 tcpv4_add_listener(l);
227 }
228 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229 } /* end for(port) */
230 } /* end while(next) */
231 free(dupstr);
232 return tail;
233 fail:
234 free(dupstr);
235 return NULL;
236}
237
Willy Tarreau977b8e42006-12-29 14:19:17 +0100238/*
239 * Sends a warning if proxy <proxy> does not have at least one of the
240 * capabilities in <cap>. An optionnal <hint> may be added at the end
241 * of the warning to help the user. Returns 1 if a warning was emitted
242 * or 0 if the condition is valid.
243 */
244int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
245{
246 char *msg;
247
248 switch (cap) {
249 case PR_CAP_BE: msg = "no backend"; break;
250 case PR_CAP_FE: msg = "no frontend"; break;
251 case PR_CAP_RS: msg = "no ruleset"; break;
252 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
253 default: msg = "not enough"; break;
254 }
255
256 if (!(proxy->cap & cap)) {
257 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100258 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100259 return 1;
260 }
261 return 0;
262}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
264/*
265 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
266 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100267int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268{
269
270 if (!strcmp(args[0], "global")) { /* new section */
271 /* no option, nothing special to do */
272 return 0;
273 }
274 else if (!strcmp(args[0], "daemon")) {
275 global.mode |= MODE_DAEMON;
276 }
277 else if (!strcmp(args[0], "debug")) {
278 global.mode |= MODE_DEBUG;
279 }
280 else if (!strcmp(args[0], "noepoll")) {
281 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
282 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200283 else if (!strcmp(args[0], "nosepoll")) {
284 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
285 }
286 else if (!strcmp(args[0], "nokqueue")) {
287 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 else if (!strcmp(args[0], "nopoll")) {
290 cfg_polling_mechanism &= ~POLL_USE_POLL;
291 }
292 else if (!strcmp(args[0], "quiet")) {
293 global.mode |= MODE_QUIET;
294 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200295 else if (!strcmp(args[0], "tune.maxpollevents")) {
296 if (global.tune.maxpollevents != 0) {
297 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
298 return 0;
299 }
300 if (*(args[1]) == 0) {
301 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
302 return -1;
303 }
304 global.tune.maxpollevents = atol(args[1]);
305 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100306 else if (!strcmp(args[0], "tune.maxaccept")) {
307 if (global.tune.maxaccept != 0) {
308 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
309 return 0;
310 }
311 if (*(args[1]) == 0) {
312 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
313 return -1;
314 }
315 global.tune.maxaccept = atol(args[1]);
316 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317 else if (!strcmp(args[0], "uid")) {
318 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200319 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200320 return 0;
321 }
322 if (*(args[1]) == 0) {
323 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
324 return -1;
325 }
326 global.uid = atol(args[1]);
327 }
328 else if (!strcmp(args[0], "gid")) {
329 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200330 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200331 return 0;
332 }
333 if (*(args[1]) == 0) {
334 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
335 return -1;
336 }
337 global.gid = atol(args[1]);
338 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200339 /* user/group name handling */
340 else if (!strcmp(args[0], "user")) {
341 struct passwd *ha_user;
342 if (global.uid != 0) {
343 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
344 return 0;
345 }
346 errno = 0;
347 ha_user = getpwnam(args[1]);
348 if (ha_user != NULL) {
349 global.uid = (int)ha_user->pw_uid;
350 }
351 else {
352 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
353 exit(1);
354 }
355 }
356 else if (!strcmp(args[0], "group")) {
357 struct group *ha_group;
358 if (global.gid != 0) {
359 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
360 return 0;
361 }
362 errno = 0;
363 ha_group = getgrnam(args[1]);
364 if (ha_group != NULL) {
365 global.gid = (int)ha_group->gr_gid;
366 }
367 else {
368 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
369 exit(1);
370 }
371 }
372 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200373 else if (!strcmp(args[0], "nbproc")) {
374 if (global.nbproc != 0) {
375 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
376 return 0;
377 }
378 if (*(args[1]) == 0) {
379 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
380 return -1;
381 }
382 global.nbproc = atol(args[1]);
383 }
384 else if (!strcmp(args[0], "maxconn")) {
385 if (global.maxconn != 0) {
386 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
387 return 0;
388 }
389 if (*(args[1]) == 0) {
390 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
391 return -1;
392 }
393 global.maxconn = atol(args[1]);
394#ifdef SYSTEM_MAXCONN
395 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
396 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);
397 global.maxconn = DEFAULT_MAXCONN;
398 }
399#endif /* SYSTEM_MAXCONN */
400 }
401 else if (!strcmp(args[0], "ulimit-n")) {
402 if (global.rlimit_nofile != 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.rlimit_nofile = atol(args[1]);
411 }
412 else if (!strcmp(args[0], "chroot")) {
413 if (global.chroot != NULL) {
414 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
415 return 0;
416 }
417 if (*(args[1]) == 0) {
418 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
419 return -1;
420 }
421 global.chroot = strdup(args[1]);
422 }
423 else if (!strcmp(args[0], "pidfile")) {
424 if (global.pidfile != NULL) {
425 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
426 return 0;
427 }
428 if (*(args[1]) == 0) {
429 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
430 return -1;
431 }
432 global.pidfile = strdup(args[1]);
433 }
434 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100435 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200436 int facility, level;
437
438 if (*(args[1]) == 0 || *(args[2]) == 0) {
439 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
440 return -1;
441 }
442
443 facility = get_log_facility(args[2]);
444 if (facility < 0) {
445 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
446 exit(1);
447 }
448
449 level = 7; /* max syslog level = debug */
450 if (*(args[3])) {
451 level = get_log_level(args[3]);
452 if (level < 0) {
453 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
454 exit(1);
455 }
456 }
457
Robert Tsai81ae1952007-12-05 10:47:29 +0100458 if (args[1][0] == '/') {
459 logsrv.u.addr.sa_family = AF_UNIX;
460 logsrv.u.un = *str2sun(args[1]);
461 } else {
462 logsrv.u.addr.sa_family = AF_INET;
463 logsrv.u.in = *str2sa(args[1]);
464 if (!logsrv.u.in.sin_port)
465 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
466 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467
468 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100469 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 global.logfac1 = facility;
471 global.loglev1 = level;
472 }
473 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100474 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 global.logfac2 = facility;
476 global.loglev2 = level;
477 }
478 else {
479 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
480 return -1;
481 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200482 }
483 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
484 if (global.spread_checks != 0) {
485 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
486 return 0;
487 }
488 if (*(args[1]) == 0) {
489 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
490 return -1;
491 }
492 global.spread_checks = atol(args[1]);
493 if (global.spread_checks < 0 || global.spread_checks > 50) {
494 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
495 return -1;
496 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200497 }
498 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200499 struct cfg_kw_list *kwl;
500 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200501 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200502
503 list_for_each_entry(kwl, &cfg_keywords.list, list) {
504 for (index = 0; kwl->kw[index].kw != NULL; index++) {
505 if (kwl->kw[index].section != CFG_GLOBAL)
506 continue;
507 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
508 /* prepare error message just in case */
509 snprintf(trash, sizeof(trash),
510 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200511 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
512 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200513 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
514 return -1;
515 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200516 else if (rc > 0) {
517 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
518 return 0;
519 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200520 return 0;
521 }
522 }
523 }
524
Willy Tarreaubaaee002006-06-26 02:48:02 +0200525 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
526 return -1;
527 }
528 return 0;
529}
530
531
532static void init_default_instance()
533{
534 memset(&defproxy, 0, sizeof(defproxy));
535 defproxy.mode = PR_MODE_TCP;
536 defproxy.state = PR_STNEW;
537 defproxy.maxconn = cfg_maxpconn;
538 defproxy.conn_retries = CONN_RETRIES;
539 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100540 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541}
542
543/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100544 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
545 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100547int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548{
549 static struct proxy *curproxy = NULL;
550 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200551 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100552 int rc;
553 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200554
Willy Tarreau977b8e42006-12-29 14:19:17 +0100555 if (!strcmp(args[0], "listen"))
556 rc = PR_CAP_LISTEN;
557 else if (!strcmp(args[0], "frontend"))
558 rc = PR_CAP_FE | PR_CAP_RS;
559 else if (!strcmp(args[0], "backend"))
560 rc = PR_CAP_BE | PR_CAP_RS;
561 else if (!strcmp(args[0], "ruleset"))
562 rc = PR_CAP_RS;
563 else
564 rc = PR_CAP_NONE;
565
566 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 if (!*args[1]) {
568 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
569 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
570 file, linenum, args[0]);
571 return -1;
572 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200573
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100574 err = invalid_char(args[1]);
575 if (err) {
576 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
577 file, linenum, *err, args[0], args[1]);
578 return -1;
579 }
580
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200581 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
582 /*
583 * If there are two proxies with the same name only following
584 * combinations are allowed:
585 *
586 * listen backend frontend ruleset
587 * listen - - - -
588 * backend - - OK -
589 * frontend - OK - -
590 * ruleset - - - -
591 */
592
593 if (!strcmp(curproxy->id, args[1]) &&
594 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
595 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100596 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
597 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200598 }
599 }
600
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
602 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
603 return -1;
604 }
605
606 curproxy->next = proxy;
607 proxy = curproxy;
608 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200609 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200610 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200611 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100612 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200613 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200614 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615
Willy Tarreauee991362007-05-14 14:37:50 +0200616 /* Timeouts are defined as -1, so we cannot use the zeroed area
617 * as a default value.
618 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100619 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200620
621 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100623 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200624
625 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100626 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200627 curproxy->listen = str2listener(args[2], curproxy->listen);
628 if (!curproxy->listen)
629 return -1;
630 global.maxsock++;
631 }
632
633 /* set default values */
634 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100636 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200637 curproxy->except_net = defproxy.except_net;
638 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639
Willy Tarreau977b8e42006-12-29 14:19:17 +0100640 if (curproxy->cap & PR_CAP_FE) {
641 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100642 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100643
644 /* initialize error relocations */
645 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
646 if (defproxy.errmsg[rc].str)
647 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
648 }
649
650 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652
Willy Tarreau977b8e42006-12-29 14:19:17 +0100653 if (curproxy->cap & PR_CAP_BE) {
654 curproxy->fullconn = defproxy.fullconn;
655 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656
Willy Tarreau977b8e42006-12-29 14:19:17 +0100657 if (defproxy.check_req)
658 curproxy->check_req = strdup(defproxy.check_req);
659 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200660
Willy Tarreau977b8e42006-12-29 14:19:17 +0100661 if (defproxy.cookie_name)
662 curproxy->cookie_name = strdup(defproxy.cookie_name);
663 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100664
665 if (defproxy.url_param_name)
666 curproxy->url_param_name = strdup(defproxy.url_param_name);
667 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669
Willy Tarreau977b8e42006-12-29 14:19:17 +0100670 if (curproxy->cap & PR_CAP_RS) {
671 if (defproxy.capture_name)
672 curproxy->capture_name = strdup(defproxy.capture_name);
673 curproxy->capture_namelen = defproxy.capture_namelen;
674 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676
Willy Tarreau977b8e42006-12-29 14:19:17 +0100677 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100678 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100679 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100680 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100681 curproxy->uri_auth = defproxy.uri_auth;
682 curproxy->mon_net = defproxy.mon_net;
683 curproxy->mon_mask = defproxy.mon_mask;
684 if (defproxy.monitor_uri)
685 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
686 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100687 if (defproxy.defbe.name)
688 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100689 }
690
691 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100692 curproxy->timeout.connect = defproxy.timeout.connect;
693 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100694 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100695 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100696 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100697 curproxy->source_addr = defproxy.source_addr;
698 }
699
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700 curproxy->mode = defproxy.mode;
701 curproxy->logfac1 = defproxy.logfac1;
702 curproxy->logsrv1 = defproxy.logsrv1;
703 curproxy->loglev1 = defproxy.loglev1;
704 curproxy->logfac2 = defproxy.logfac2;
705 curproxy->logsrv2 = defproxy.logsrv2;
706 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200707 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100708 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
709 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200710
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 return 0;
712 }
713 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
714 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100715 /* FIXME-20070101: we should do this too at the end of the
716 * config parsing to free all default values.
717 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200718 if (defproxy.check_req) free(defproxy.check_req);
719 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100720 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200722 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100723 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100724
725 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
726 if (defproxy.errmsg[rc].len)
727 free(defproxy.errmsg[rc].str);
728 }
729
Willy Tarreaubaaee002006-06-26 02:48:02 +0200730 /* we cannot free uri_auth because it might already be used */
731 init_default_instance();
732 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100733 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200734 return 0;
735 }
736 else if (curproxy == NULL) {
737 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
738 return -1;
739 }
740
Willy Tarreau977b8e42006-12-29 14:19:17 +0100741
742 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200743 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100744 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200745 if (curproxy == &defproxy) {
746 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
747 return -1;
748 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100749 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
750 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751
752 if (strchr(args[1], ':') == NULL) {
753 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
754 file, linenum, args[0]);
755 return -1;
756 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100757
758 last_listen = curproxy->listen;
759 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200760 if (!curproxy->listen)
761 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100762 if (*args[2]) {
763#ifdef CONFIG_HAP_LINUX_TPROXY
764 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
765 struct listener *l;
766
767 for (l = curproxy->listen; l != last_listen; l = l->next)
768 l->options |= LI_O_FOREIGN;
769 }
770 else {
771 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
772 file, linenum, args[0]);
773 return -1;
774 }
775#else
776 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
777 file, linenum, args[0]);
778 return -1;
779#endif
780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 global.maxsock++;
782 return 0;
783 }
784 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
785 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
786 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
787 file, linenum, args[0]);
788 return -1;
789 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100790 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
791 return 0;
792
Willy Tarreaubaaee002006-06-26 02:48:02 +0200793 /* flush useless bits */
794 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
795 return 0;
796 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200797 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100798 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
799 return 0;
800
Willy Tarreau1c47f852006-07-09 08:22:27 +0200801 if (!*args[1]) {
802 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
803 file, linenum, args[0]);
804 return -1;
805 }
806
807 if (curproxy->monitor_uri != NULL)
808 free(curproxy->monitor_uri);
809
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100810 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200811 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100812 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200813 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
814
815 return 0;
816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200817 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
818 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
819 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
820 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
821 else {
822 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
823 return -1;
824 }
825 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100826 else if (!strcmp(args[0], "id")) {
827 struct proxy *target;
828
829 if (curproxy == &defproxy) {
830 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
831 file, linenum, args[0]);
832 return -1;
833 }
834
835 if (!*args[1]) {
836 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
837 file, linenum, args[0]);
838 return -1;
839 }
840
841 curproxy->uuid = atol(args[1]);
842
843 if (curproxy->uuid < 1001) {
844 Alert("parsing [%s:%d]: custom id has to be > 1000",
845 file, linenum);
846 return -1;
847 }
848
849 for (target = proxy; target; target = target->next)
850 if (curproxy != target && curproxy->uuid == target->uuid) {
851 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
852 file, linenum, curproxy->id, target->id);
853 return -1;
854 }
855 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200856 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
857 curproxy->state = PR_STSTOPPED;
858 }
859 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
860 curproxy->state = PR_STNEW;
861 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200862 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100863 err = invalid_char(args[1]);
864 if (err) {
865 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
866 file, linenum, *err, args[1]);
867 return -1;
868 }
869
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200870 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
871 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
872 file, linenum, args[1]);
873 return -1;
874 }
875 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200876 else if (!strcmp(args[0], "cookie")) { /* cookie name */
877 int cur_arg;
878 // if (curproxy == &defproxy) {
879 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
880 // return -1;
881 // }
882
Willy Tarreau977b8e42006-12-29 14:19:17 +0100883 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
884 return 0;
885
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886 if (curproxy->cookie_name != NULL) {
887 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
888 // file, linenum);
889 // return 0;
890 free(curproxy->cookie_name);
891 }
892
893 if (*(args[1]) == 0) {
894 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
895 file, linenum, args[0]);
896 return -1;
897 }
898 curproxy->cookie_name = strdup(args[1]);
899 curproxy->cookie_len = strlen(curproxy->cookie_name);
900
901 cur_arg = 2;
902 while (*(args[cur_arg])) {
903 if (!strcmp(args[cur_arg], "rewrite")) {
904 curproxy->options |= PR_O_COOK_RW;
905 }
906 else if (!strcmp(args[cur_arg], "indirect")) {
907 curproxy->options |= PR_O_COOK_IND;
908 }
909 else if (!strcmp(args[cur_arg], "insert")) {
910 curproxy->options |= PR_O_COOK_INS;
911 }
912 else if (!strcmp(args[cur_arg], "nocache")) {
913 curproxy->options |= PR_O_COOK_NOC;
914 }
915 else if (!strcmp(args[cur_arg], "postonly")) {
916 curproxy->options |= PR_O_COOK_POST;
917 }
918 else if (!strcmp(args[cur_arg], "prefix")) {
919 curproxy->options |= PR_O_COOK_PFX;
920 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200921 else if (!strcmp(args[cur_arg], "domain")) {
922 if (!*args[cur_arg + 1]) {
923 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
924 file, linenum, args[cur_arg]);
925 return -1;
926 }
927
928 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
929 /* rfc2109, 4.3.2 Rejecting Cookies */
930 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
931 " dots or does not start with a dot.\n",
932 file, linenum, args[cur_arg + 1]);
933 return -1;
934 }
935
936 err = invalid_domainchar(args[cur_arg + 1]);
937 if (err) {
938 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
939 file, linenum, *err, args[cur_arg + 1]);
940 return -1;
941 }
942
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +0200943 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200944 cur_arg++;
945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200947 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 file, linenum, args[0]);
949 return -1;
950 }
951 cur_arg++;
952 }
953 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
954 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
955 file, linenum);
956 return -1;
957 }
958
959 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
960 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
961 file, linenum);
962 return -1;
963 }
964 }/* end else if (!strcmp(args[0], "cookie")) */
965 else if (!strcmp(args[0], "appsession")) { /* cookie name */
966 // if (curproxy == &defproxy) {
967 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
968 // return -1;
969 // }
970
Willy Tarreau977b8e42006-12-29 14:19:17 +0100971 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
972 return 0;
973
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974 if (curproxy->appsession_name != NULL) {
975 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
976 // file, linenum);
977 // return 0;
978 free(curproxy->appsession_name);
979 }
980
981 if (*(args[5]) == 0) {
982 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
983 file, linenum, args[0]);
984 return -1;
985 }
986 have_appsession = 1;
987 curproxy->appsession_name = strdup(args[1]);
988 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
989 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100990 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
991 if (err) {
992 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
993 file, linenum, *err, args[0]);
994 return -1;
995 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200996 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +0200997
Willy Tarreau51041c72007-09-09 21:56:53 +0200998 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
999 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001000 return -1;
1001 }
1002 } /* Url App Session */
1003 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001004 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1005 return 0;
1006
Willy Tarreaubaaee002006-06-26 02:48:02 +02001007 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
1008 // if (curproxy == &defproxy) {
1009 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1010 // return -1;
1011 // }
1012
1013 if (curproxy->capture_name != NULL) {
1014 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
1015 // file, linenum, args[0]);
1016 // return 0;
1017 free(curproxy->capture_name);
1018 }
1019
1020 if (*(args[4]) == 0) {
1021 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1022 file, linenum, args[0]);
1023 return -1;
1024 }
1025 curproxy->capture_name = strdup(args[2]);
1026 curproxy->capture_namelen = strlen(curproxy->capture_name);
1027 curproxy->capture_len = atol(args[4]);
1028 if (curproxy->capture_len >= CAPTURE_LEN) {
1029 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1030 file, linenum, CAPTURE_LEN - 1);
1031 curproxy->capture_len = CAPTURE_LEN - 1;
1032 }
1033 curproxy->to_log |= LW_COOKIE;
1034 }
1035 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1036 struct cap_hdr *hdr;
1037
1038 if (curproxy == &defproxy) {
1039 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1040 return -1;
1041 }
1042
1043 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1044 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1045 file, linenum, args[0], args[1]);
1046 return -1;
1047 }
1048
1049 hdr = calloc(sizeof(struct cap_hdr), 1);
1050 hdr->next = curproxy->req_cap;
1051 hdr->name = strdup(args[3]);
1052 hdr->namelen = strlen(args[3]);
1053 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001054 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 hdr->index = curproxy->nb_req_cap++;
1056 curproxy->req_cap = hdr;
1057 curproxy->to_log |= LW_REQHDR;
1058 }
1059 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1060 struct cap_hdr *hdr;
1061
1062 if (curproxy == &defproxy) {
1063 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1064 return -1;
1065 }
1066
1067 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1068 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1069 file, linenum, args[0], args[1]);
1070 return -1;
1071 }
1072 hdr = calloc(sizeof(struct cap_hdr), 1);
1073 hdr->next = curproxy->rsp_cap;
1074 hdr->name = strdup(args[3]);
1075 hdr->namelen = strlen(args[3]);
1076 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001077 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078 hdr->index = curproxy->nb_rsp_cap++;
1079 curproxy->rsp_cap = hdr;
1080 curproxy->to_log |= LW_RSPHDR;
1081 }
1082 else {
1083 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1084 file, linenum, args[0]);
1085 return -1;
1086 }
1087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001089 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1090 return 0;
1091
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 if (*(args[1]) == 0) {
1093 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1094 file, linenum, args[0]);
1095 return -1;
1096 }
1097 curproxy->conn_retries = atol(args[1]);
1098 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001099 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1100 int pol = ACL_COND_NONE;
1101 struct acl_cond *cond;
1102
1103 if (!strcmp(args[1], "if"))
1104 pol = ACL_COND_IF;
1105 else if (!strcmp(args[1], "unless"))
1106 pol = ACL_COND_UNLESS;
1107
1108 if (pol == ACL_COND_NONE) {
1109 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1110 file, linenum, args[0]);
1111 return -1;
1112 }
1113
1114 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1115 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1116 file, linenum);
1117 return -1;
1118 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001119 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001120 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1121 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001122 else if (!strcmp(args[0], "redirect")) {
1123 int pol = ACL_COND_NONE;
1124 struct acl_cond *cond;
1125 struct redirect_rule *rule;
1126 int cur_arg;
1127 int type = REDIRECT_TYPE_NONE;
1128 int code = 302;
1129 char *destination = NULL;
1130
1131 cur_arg = 1;
1132 while (*(args[cur_arg])) {
1133 if (!strcmp(args[cur_arg], "location")) {
1134 if (!*args[cur_arg + 1]) {
1135 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1136 file, linenum, args[0], args[cur_arg]);
1137 return -1;
1138 }
1139
1140 type = REDIRECT_TYPE_LOCATION;
1141 cur_arg++;
1142 destination = args[cur_arg];
1143 }
1144 else if (!strcmp(args[cur_arg], "prefix")) {
1145 if (!*args[cur_arg + 1]) {
1146 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1147 file, linenum, args[0], args[cur_arg]);
1148 return -1;
1149 }
1150
1151 type = REDIRECT_TYPE_PREFIX;
1152 cur_arg++;
1153 destination = args[cur_arg];
1154 }
1155 else if (!strcmp(args[cur_arg],"code")) {
1156 if (!*args[cur_arg + 1]) {
1157 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1158 file, linenum, args[0]);
1159 return -1;
1160 }
1161 cur_arg++;
1162 code = atol(args[cur_arg]);
1163 if (code < 301 || code > 303) {
1164 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1165 file, linenum, args[0], code);
1166 return -1;
1167 }
1168 }
1169 else if (!strcmp(args[cur_arg], "if")) {
1170 pol = ACL_COND_IF;
1171 cur_arg++;
1172 break;
1173 }
1174 else if (!strcmp(args[cur_arg], "unless")) {
1175 pol = ACL_COND_UNLESS;
1176 cur_arg++;
1177 break;
1178 }
1179 else {
1180 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1181 file, linenum, args[0], args[cur_arg]);
1182 return -1;
1183 }
1184 cur_arg++;
1185 }
1186
1187 if (type == REDIRECT_TYPE_NONE) {
1188 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1189 file, linenum, args[0]);
1190 return -1;
1191 }
1192
1193 if (pol == ACL_COND_NONE) {
1194 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1195 file, linenum, args[0]);
1196 return -1;
1197 }
1198
1199 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1200 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1201 file, linenum, args[0]);
1202 return -1;
1203 }
1204
Willy Tarreaua9802632008-07-25 19:13:19 +02001205 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001206 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1207 rule->cond = cond;
1208 rule->rdr_str = strdup(destination);
1209 rule->rdr_len = strlen(destination);
1210 rule->type = type;
1211 rule->code = code;
1212 LIST_INIT(&rule->list);
1213 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1214 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001215 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1216 int pol = ACL_COND_NONE;
1217 struct acl_cond *cond;
1218 struct switching_rule *rule;
1219
1220 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1221 return 0;
1222
1223 if (*(args[1]) == 0) {
1224 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1225 return -1;
1226 }
1227
1228 if (!strcmp(args[2], "if"))
1229 pol = ACL_COND_IF;
1230 else if (!strcmp(args[2], "unless"))
1231 pol = ACL_COND_UNLESS;
1232
1233 if (pol == ACL_COND_NONE) {
1234 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1235 file, linenum, args[0]);
1236 return -1;
1237 }
1238
1239 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001240 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001241 file, linenum);
1242 return -1;
1243 }
1244
Willy Tarreaua9802632008-07-25 19:13:19 +02001245 cond->line = linenum;
1246 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001247 struct acl *acl;
1248 const char *name;
1249
1250 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1251 name = acl ? acl->name : "(unknown)";
1252 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1253 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001254 }
1255
Willy Tarreau55ea7572007-06-17 19:56:27 +02001256 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1257 rule->cond = cond;
1258 rule->be.name = strdup(args[1]);
1259 LIST_INIT(&rule->list);
1260 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001262 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001263 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1264 return 0;
1265
Willy Tarreaubaaee002006-06-26 02:48:02 +02001266 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1267 curproxy->uri_auth = NULL; /* we must detach from the default config */
1268
1269 if (*(args[1]) == 0) {
1270 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1271 return -1;
1272 } else if (!strcmp(args[1], "uri")) {
1273 if (*(args[2]) == 0) {
1274 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1275 return -1;
1276 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1277 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1278 return -1;
1279 }
1280 } else if (!strcmp(args[1], "realm")) {
1281 if (*(args[2]) == 0) {
1282 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1283 return -1;
1284 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1285 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1286 return -1;
1287 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001288 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001289 unsigned interval;
1290
1291 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1292 if (err) {
1293 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1294 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001295 return -1;
1296 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1297 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1298 return -1;
1299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001300 } else if (!strcmp(args[1], "auth")) {
1301 if (*(args[2]) == 0) {
1302 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1303 return -1;
1304 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1305 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1306 return -1;
1307 }
1308 } else if (!strcmp(args[1], "scope")) {
1309 if (*(args[2]) == 0) {
1310 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1311 return -1;
1312 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1313 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1314 return -1;
1315 }
1316 } else if (!strcmp(args[1], "enable")) {
1317 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1318 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1319 return -1;
1320 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001321 } else if (!strcmp(args[1], "hide-version")) {
1322 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1323 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1324 return -1;
1325 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001327 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001328 file, linenum, args[0]);
1329 return -1;
1330 }
1331 }
1332 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001333 int optnum;
1334
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001335 if (*(args[1]) == '\0') {
1336 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1337 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338 return -1;
1339 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001340
1341 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1342 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1343 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1344 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001345
1346 if (!inv)
1347 curproxy->options |= cfg_opts[optnum].val;
1348 else
1349 curproxy->options &= ~cfg_opts[optnum].val;
1350
Willy Tarreau13943ab2006-12-31 00:24:10 +01001351 return 0;
1352 }
1353 }
1354
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001355 if (inv) {
1356 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1357 file, linenum, args[1]);
1358 return -1;
1359 }
1360
Willy Tarreau13943ab2006-12-31 00:24:10 +01001361 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 /* generate a complete HTTP log */
1363 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1364 else if (!strcmp(args[1], "tcplog"))
1365 /* generate a detailed TCP log */
1366 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 else if (!strcmp(args[1], "tcpka")) {
1368 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001369 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1370 return 0;
1371
1372 if (curproxy->cap & PR_CAP_FE)
1373 curproxy->options |= PR_O_TCP_CLI_KA;
1374 if (curproxy->cap & PR_CAP_BE)
1375 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 }
1377 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001378 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1379 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 /* use HTTP request to check servers' health */
1381 if (curproxy->check_req != NULL) {
1382 free(curproxy->check_req);
1383 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001384 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001385 curproxy->options &= ~PR_O_SMTP_CHK;
1386 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001387 if (!*args[2]) { /* no argument */
1388 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1389 curproxy->check_len = strlen(DEF_CHECK_REQ);
1390 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001391 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 curproxy->check_req = (char *)malloc(reqlen);
1393 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1394 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1395 } else { /* more arguments : METHOD URI [HTTP_VER] */
1396 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1397 if (*args[4])
1398 reqlen += strlen(args[4]);
1399 else
1400 reqlen += strlen("HTTP/1.0");
1401
1402 curproxy->check_req = (char *)malloc(reqlen);
1403 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1404 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1405 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001406 }
1407 else if (!strcmp(args[1], "ssl-hello-chk")) {
1408 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001409 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1410 return 0;
1411
Willy Tarreauf3c69202006-07-09 16:42:34 +02001412 if (curproxy->check_req != NULL) {
1413 free(curproxy->check_req);
1414 }
1415 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001416 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001417 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418 }
Willy Tarreau23677902007-05-08 23:50:35 +02001419 else if (!strcmp(args[1], "smtpchk")) {
1420 /* use SMTP request to check servers' health */
1421 if (curproxy->check_req != NULL) {
1422 free(curproxy->check_req);
1423 }
1424 curproxy->options &= ~PR_O_HTTP_CHK;
1425 curproxy->options &= ~PR_O_SSL3_CHK;
1426 curproxy->options |= PR_O_SMTP_CHK;
1427
1428 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1429 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1430 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1431 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1432 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1433 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1434 curproxy->check_req = (char *)malloc(reqlen);
1435 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1436 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1437 } else {
1438 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1439 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1440 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1441 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1442 }
1443 }
1444 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001445 else if (!strcmp(args[1], "forwardfor")) {
1446 /* insert x-forwarded-for field, but not for the
1447 * IP address listed as an except.
1448 */
1449 if (*(args[2])) {
1450 if (!strcmp(args[2], "except")) {
1451 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1452 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1453 file, linenum, args[0]);
1454 return -1;
1455 }
1456 /* flush useless bits */
1457 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1458 } else {
1459 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1460 file, linenum, args[0]);
1461 return -1;
1462 }
1463 }
1464 curproxy->options |= PR_O_FWDFOR;
1465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001466 else {
1467 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1468 return -1;
1469 }
1470 return 0;
1471 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001472 else if (!strcmp(args[0], "default_backend")) {
1473 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1474 return 0;
1475
1476 if (*(args[1]) == 0) {
1477 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1478 return -1;
1479 }
1480 if (curproxy->defbe.name)
1481 free(curproxy->defbe.name);
1482 curproxy->defbe.name = strdup(args[1]);
1483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001484 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001485 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1486 return 0;
1487
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001488 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1489 file, linenum, args[0]);
1490
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491 /* enable reconnections to dispatch */
1492 curproxy->options |= PR_O_REDISP;
1493 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001494 else if (!strcmp(args[0], "http-check")) {
1495 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1496 return 0;
1497
1498 if (strcmp(args[1], "disable-on-404") == 0) {
1499 /* enable a graceful server shutdown on an HTTP 404 response */
1500 curproxy->options |= PR_O_DISABLE404;
1501 }
1502 else {
1503 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1504 return -1;
1505 }
1506 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001507 else if (!strcmp(args[0], "monitor")) {
1508 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1509 return 0;
1510
1511 if (strcmp(args[1], "fail") == 0) {
1512 /* add a condition to fail monitor requests */
1513 int pol = ACL_COND_NONE;
1514 struct acl_cond *cond;
1515
1516 if (!strcmp(args[2], "if"))
1517 pol = ACL_COND_IF;
1518 else if (!strcmp(args[2], "unless"))
1519 pol = ACL_COND_UNLESS;
1520
1521 if (pol == ACL_COND_NONE) {
1522 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1523 file, linenum, args[0], args[1]);
1524 return -1;
1525 }
1526
1527 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1528 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1529 file, linenum, args[0], args[1]);
1530 return -1;
1531 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001532 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001533 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1534 }
1535 else {
1536 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1537 return -1;
1538 }
1539 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540#ifdef TPROXY
1541 else if (!strcmp(args[0], "transparent")) {
1542 /* enable transparent proxy connections */
1543 curproxy->options |= PR_O_TRANSP;
1544 }
1545#endif
1546 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001547 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1548 return 0;
1549
Willy Tarreaubaaee002006-06-26 02:48:02 +02001550 if (*(args[1]) == 0) {
1551 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1552 return -1;
1553 }
1554 curproxy->maxconn = atol(args[1]);
1555 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001556 else if (!strcmp(args[0], "backlog")) { /* backlog */
1557 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1558 return 0;
1559
1560 if (*(args[1]) == 0) {
1561 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1562 return -1;
1563 }
1564 curproxy->backlog = atol(args[1]);
1565 }
Willy Tarreau86034312006-12-29 00:10:33 +01001566 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001567 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1568 return 0;
1569
Willy Tarreau86034312006-12-29 00:10:33 +01001570 if (*(args[1]) == 0) {
1571 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1572 return -1;
1573 }
1574 curproxy->fullconn = atol(args[1]);
1575 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001576 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1577 if (*(args[1]) == 0) {
1578 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1579 return -1;
1580 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001581 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1582 if (err) {
1583 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1584 file, linenum, *err);
1585 return -1;
1586 }
1587 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 }
1589 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1590 if (curproxy == &defproxy) {
1591 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1592 return -1;
1593 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001594 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1595 return 0;
1596
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 if (strchr(args[1], ':') == NULL) {
1598 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1599 return -1;
1600 }
1601 curproxy->dispatch_addr = *str2sa(args[1]);
1602 }
1603 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001604 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1605 return 0;
1606
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001607 memcpy(trash, "error near 'balance'", 19);
1608 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1609 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1610 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001612 }
1613 else if (!strcmp(args[0], "server")) { /* server address */
1614 int cur_arg;
1615 char *rport;
1616 char *raddr;
1617 short realport;
1618 int do_check;
1619
1620 if (curproxy == &defproxy) {
1621 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1622 return -1;
1623 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001624 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1625 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626
1627 if (!*args[2]) {
1628 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1629 file, linenum, args[0]);
1630 return -1;
1631 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001632
1633 err = invalid_char(args[1]);
1634 if (err) {
1635 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1636 file, linenum, *err, args[1]);
1637 return -1;
1638 }
1639
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1641 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1642 return -1;
1643 }
1644
1645 /* the servers are linked backwards first */
1646 newsrv->next = curproxy->srv;
1647 curproxy->srv = newsrv;
1648 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001649 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001650
1651 LIST_INIT(&newsrv->pendconns);
1652 do_check = 0;
1653 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001654 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 newsrv->id = strdup(args[1]);
1656
1657 /* several ways to check the port component :
1658 * - IP => port=+0, relative
1659 * - IP: => port=+0, relative
1660 * - IP:N => port=N, absolute
1661 * - IP:+N => port=+N, relative
1662 * - IP:-N => port=-N, relative
1663 */
1664 raddr = strdup(args[2]);
1665 rport = strchr(raddr, ':');
1666 if (rport) {
1667 *rport++ = 0;
1668 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001669 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670 newsrv->state |= SRV_MAPPORTS;
1671 } else {
1672 realport = 0;
1673 newsrv->state |= SRV_MAPPORTS;
1674 }
1675
1676 newsrv->addr = *str2sa(raddr);
1677 newsrv->addr.sin_port = htons(realport);
1678 free(raddr);
1679
1680 newsrv->curfd = -1; /* no health-check in progress */
1681 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001682 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1683 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001684 newsrv->rise = DEF_RISETIME;
1685 newsrv->fall = DEF_FALLTIME;
1686 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001687 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001688 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001689 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001690
Willy Tarreaubaaee002006-06-26 02:48:02 +02001691 cur_arg = 3;
1692 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001693 if (!strcmp(args[cur_arg], "id")) {
1694 struct server *target;
1695
1696 if (!*args[cur_arg + 1]) {
1697 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1698 file, linenum, args[cur_arg]);
1699 return -1;
1700 }
1701
1702 newsrv->puid = atol(args[cur_arg + 1]);
1703
1704 if (newsrv->puid< 1001) {
1705 Alert("parsing [%s:%d]: custom id has to be > 1000",
1706 file, linenum);
1707 return -1;
1708 }
1709
1710 for (target = proxy->srv; target; target = target->next)
1711 if (newsrv != target && newsrv->puid == target->puid) {
1712 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1713 file, linenum, newsrv->id, target->id);
1714 return -1;
1715 }
1716 cur_arg += 2;
1717 }
1718 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001719 newsrv->cookie = strdup(args[cur_arg + 1]);
1720 newsrv->cklen = strlen(args[cur_arg + 1]);
1721 cur_arg += 2;
1722 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001723 else if (!strcmp(args[cur_arg], "redir")) {
1724 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1725 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1726 cur_arg += 2;
1727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 else if (!strcmp(args[cur_arg], "rise")) {
1729 newsrv->rise = atol(args[cur_arg + 1]);
1730 newsrv->health = newsrv->rise;
1731 cur_arg += 2;
1732 }
1733 else if (!strcmp(args[cur_arg], "fall")) {
1734 newsrv->fall = atol(args[cur_arg + 1]);
1735 cur_arg += 2;
1736 }
1737 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001738 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1739 if (err) {
1740 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1741 file, linenum, *err, newsrv->id);
1742 return -1;
1743 }
1744 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001745 cur_arg += 2;
1746 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001747 else if (!strcmp(args[cur_arg], "fastinter")) {
1748 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1749 if (err) {
1750 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1751 file, linenum, *err, newsrv->id);
1752 return -1;
1753 }
1754 newsrv->fastinter = val;
1755 cur_arg += 2;
1756 }
1757 else if (!strcmp(args[cur_arg], "downinter")) {
1758 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1759 if (err) {
1760 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1761 file, linenum, *err, newsrv->id);
1762 return -1;
1763 }
1764 newsrv->downinter = val;
1765 cur_arg += 2;
1766 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001767 else if (!strcmp(args[cur_arg], "addr")) {
1768 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001769 cur_arg += 2;
1770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771 else if (!strcmp(args[cur_arg], "port")) {
1772 newsrv->check_port = atol(args[cur_arg + 1]);
1773 cur_arg += 2;
1774 }
1775 else if (!strcmp(args[cur_arg], "backup")) {
1776 newsrv->state |= SRV_BACKUP;
1777 cur_arg ++;
1778 }
1779 else if (!strcmp(args[cur_arg], "weight")) {
1780 int w;
1781 w = atol(args[cur_arg + 1]);
1782 if (w < 1 || w > 256) {
1783 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1784 file, linenum, newsrv->id, w);
1785 return -1;
1786 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001787 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001788 cur_arg += 2;
1789 }
1790 else if (!strcmp(args[cur_arg], "minconn")) {
1791 newsrv->minconn = atol(args[cur_arg + 1]);
1792 cur_arg += 2;
1793 }
1794 else if (!strcmp(args[cur_arg], "maxconn")) {
1795 newsrv->maxconn = atol(args[cur_arg + 1]);
1796 cur_arg += 2;
1797 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001798 else if (!strcmp(args[cur_arg], "maxqueue")) {
1799 newsrv->maxqueue = atol(args[cur_arg + 1]);
1800 cur_arg += 2;
1801 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001802 else if (!strcmp(args[cur_arg], "slowstart")) {
1803 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001804 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001805 if (err) {
1806 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1807 file, linenum, *err, newsrv->id);
1808 return -1;
1809 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001810 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001811 cur_arg += 2;
1812 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001813 else if (!strcmp(args[cur_arg], "track")) {
1814
1815 if (!*args[cur_arg + 1]) {
1816 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1817 file, linenum);
1818 return -1;
1819 }
1820
1821 newsrv->trackit = strdup(args[cur_arg + 1]);
1822
1823 cur_arg += 2;
1824 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001825 else if (!strcmp(args[cur_arg], "check")) {
1826 global.maxsock++;
1827 do_check = 1;
1828 cur_arg += 1;
1829 }
1830 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1831 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001832#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001833 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1834 file, linenum, "source", "usesrc");
1835#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001836 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1837 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001838#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001839 return -1;
1840 }
1841 newsrv->state |= SRV_BIND_SRC;
1842 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1843 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001844 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001845#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1846#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001847 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001848 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1849 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001850 return -1;
1851 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001852#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001853 if (!*args[cur_arg + 1]) {
1854 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1855 file, linenum, "usesrc");
1856 return -1;
1857 }
1858 if (!strcmp(args[cur_arg + 1], "client")) {
1859 newsrv->state |= SRV_TPROXY_CLI;
1860 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1861 newsrv->state |= SRV_TPROXY_CIP;
1862 } else {
1863 newsrv->state |= SRV_TPROXY_ADDR;
1864 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1865 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001866 global.last_checks |= LSTCHK_NETADM;
1867#if !defined(CONFIG_HAP_LINUX_TPROXY)
1868 global.last_checks |= LSTCHK_CTTPROXY;
1869#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001870 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001871#else /* no TPROXY support */
1872 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001873 file, linenum, "usesrc");
1874 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001875#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001876 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001877 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001878 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1879 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1880 file, linenum, "usesrc", "source");
1881 return -1;
1882 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001883 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001884 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 +02001885 file, linenum, newsrv->id);
1886 return -1;
1887 }
1888 }
1889
1890 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001891 if (newsrv->trackit) {
1892 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1893 file, linenum);
1894 return -1;
1895 }
1896
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001897 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1898 newsrv->check_port = newsrv->check_addr.sin_port;
1899
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1901 newsrv->check_port = realport; /* by default */
1902 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001903 /* not yet valid, because no port was set on
1904 * the server either. We'll check if we have
1905 * a known port on the first listener.
1906 */
1907 struct listener *l;
1908 l = curproxy->listen;
1909 if (l) {
1910 int port;
1911 port = (l->addr.ss_family == AF_INET6)
1912 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1913 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1914 newsrv->check_port = port;
1915 }
1916 }
1917 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1919 file, linenum, newsrv->id);
1920 return -1;
1921 }
1922 newsrv->state |= SRV_CHECKED;
1923 }
1924
1925 if (newsrv->state & SRV_BACKUP)
1926 curproxy->srv_bck++;
1927 else
1928 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001929
1930 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931 }
1932 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001933 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934 int facility;
1935
1936 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1937 curproxy->logfac1 = global.logfac1;
1938 curproxy->logsrv1 = global.logsrv1;
1939 curproxy->loglev1 = global.loglev1;
1940 curproxy->logfac2 = global.logfac2;
1941 curproxy->logsrv2 = global.logsrv2;
1942 curproxy->loglev2 = global.loglev2;
1943 }
1944 else if (*(args[1]) && *(args[2])) {
1945 int level;
1946
1947 facility = get_log_facility(args[2]);
1948 if (facility < 0) {
1949 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1950 exit(1);
1951 }
1952
1953 level = 7; /* max syslog level = debug */
1954 if (*(args[3])) {
1955 level = get_log_level(args[3]);
1956 if (level < 0) {
1957 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1958 exit(1);
1959 }
1960 }
1961
Robert Tsai81ae1952007-12-05 10:47:29 +01001962 if (args[1][0] == '/') {
1963 logsrv.u.addr.sa_family = AF_UNIX;
1964 logsrv.u.un = *str2sun(args[1]);
1965 } else {
1966 logsrv.u.addr.sa_family = AF_INET;
1967 logsrv.u.in = *str2sa(args[1]);
1968 if (!logsrv.u.in.sin_port) {
1969 logsrv.u.in.sin_port =
1970 htons(SYSLOG_PORT);
1971 }
1972 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973
1974 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001975 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976 curproxy->logfac1 = facility;
1977 curproxy->loglev1 = level;
1978 }
1979 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001980 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981 curproxy->logfac2 = facility;
1982 curproxy->loglev2 = level;
1983 }
1984 else {
1985 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1986 return -1;
1987 }
1988 }
1989 else {
1990 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1991 file, linenum);
1992 return -1;
1993 }
1994 }
1995 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001996 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1997 return 0;
1998
Willy Tarreaubaaee002006-06-26 02:48:02 +02001999 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002000#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002001 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2002 file, linenum, "source", "usesrc");
2003#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2005 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002006#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002007 return -1;
2008 }
2009
2010 curproxy->source_addr = *str2sa(args[1]);
2011 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01002012 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002013#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2014#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002015 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2016 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2017 file, linenum, "usesrc");
2018 return -1;
2019 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002020#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002021 if (!*args[3]) {
2022 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2023 file, linenum, "usesrc");
2024 return -1;
2025 }
2026
2027 if (!strcmp(args[3], "client")) {
2028 curproxy->options |= PR_O_TPXY_CLI;
2029 } else if (!strcmp(args[3], "clientip")) {
2030 curproxy->options |= PR_O_TPXY_CIP;
2031 } else {
2032 curproxy->options |= PR_O_TPXY_ADDR;
2033 curproxy->tproxy_addr = *str2sa(args[3]);
2034 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002035 global.last_checks |= LSTCHK_NETADM;
2036#if !defined(CONFIG_HAP_LINUX_TPROXY)
2037 global.last_checks |= LSTCHK_CTTPROXY;
2038#endif
2039#else /* no TPROXY support */
2040 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002041 file, linenum, "usesrc");
2042 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002043#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002044 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002045 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002046 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2047 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2048 file, linenum, "usesrc", "source");
2049 return -1;
2050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2052 regex_t *preg;
2053 if (curproxy == &defproxy) {
2054 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2055 return -1;
2056 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002057 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2058 return 0;
2059
Willy Tarreaubaaee002006-06-26 02:48:02 +02002060 if (*(args[1]) == 0 || *(args[2]) == 0) {
2061 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2062 file, linenum, args[0]);
2063 return -1;
2064 }
2065
2066 preg = calloc(1, sizeof(regex_t));
2067 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2068 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2069 return -1;
2070 }
2071
2072 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2073 if (err) {
2074 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2075 file, linenum, *err);
2076 return -1;
2077 }
2078 }
2079 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2080 regex_t *preg;
2081 if (curproxy == &defproxy) {
2082 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2083 return -1;
2084 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002085 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2086 return 0;
2087
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 if (*(args[1]) == 0) {
2089 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2090 return -1;
2091 }
2092
2093 preg = calloc(1, sizeof(regex_t));
2094 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2095 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2096 return -1;
2097 }
2098
2099 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2100 }
2101 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2102 regex_t *preg;
2103 if (curproxy == &defproxy) {
2104 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2105 return -1;
2106 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002107 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2108 return 0;
2109
Willy Tarreaubaaee002006-06-26 02:48:02 +02002110 if (*(args[1]) == 0) {
2111 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2112 return -1;
2113 }
2114
2115 preg = calloc(1, sizeof(regex_t));
2116 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2117 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2118 return -1;
2119 }
2120
2121 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2122 }
2123 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2124 regex_t *preg;
2125 if (curproxy == &defproxy) {
2126 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2127 return -1;
2128 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002129 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2130 return 0;
2131
Willy Tarreaubaaee002006-06-26 02:48:02 +02002132 if (*(args[1]) == 0) {
2133 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2134 return -1;
2135 }
2136
2137 preg = calloc(1, sizeof(regex_t));
2138 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2139 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2140 return -1;
2141 }
2142
2143 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2144 }
2145 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2146 regex_t *preg;
2147 if (curproxy == &defproxy) {
2148 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2149 return -1;
2150 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002151 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2152 return 0;
2153
Willy Tarreaubaaee002006-06-26 02:48:02 +02002154 if (*(args[1]) == 0) {
2155 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2156 return -1;
2157 }
2158
2159 preg = calloc(1, sizeof(regex_t));
2160 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2161 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2162 return -1;
2163 }
2164
2165 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2166 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002167 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2168 regex_t *preg;
2169 if (curproxy == &defproxy) {
2170 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2171 return -1;
2172 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002173 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2174 return 0;
2175
Willy Tarreaub8750a82006-09-03 09:56:00 +02002176 if (*(args[1]) == 0) {
2177 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2178 return -1;
2179 }
2180
2181 preg = calloc(1, sizeof(regex_t));
2182 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2183 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2184 return -1;
2185 }
2186
2187 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2188 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002189 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2190 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002191 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002192 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2193 return -1;
2194 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002195 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2196 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002197
Willy Tarreau977b8e42006-12-29 14:19:17 +01002198 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002199 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2200 file, linenum, args[0]);
2201 return -1;
2202 }
2203
2204 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002205 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002206 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2207 }
2208
2209 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2210 }
2211 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2212 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002213 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002214 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2215 return -1;
2216 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002217 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2218 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002219
Willy Tarreau977b8e42006-12-29 14:19:17 +01002220 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002221 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2222 file, linenum, args[0]);
2223 return -1;
2224 }
2225
2226 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002227 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002228 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2229 }
2230
2231 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2232 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2234 regex_t *preg;
2235 if (curproxy == &defproxy) {
2236 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2237 return -1;
2238 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002239 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2240 return 0;
2241
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 if (*(args[1]) == 0 || *(args[2]) == 0) {
2243 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2244 file, linenum, args[0]);
2245 return -1;
2246 }
2247
2248 preg = calloc(1, sizeof(regex_t));
2249 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2250 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2251 return -1;
2252 }
2253
2254 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2255 if (err) {
2256 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2257 file, linenum, *err);
2258 return -1;
2259 }
2260 }
2261 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2262 regex_t *preg;
2263 if (curproxy == &defproxy) {
2264 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2265 return -1;
2266 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002267 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2268 return 0;
2269
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 if (*(args[1]) == 0) {
2271 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2272 return -1;
2273 }
2274
2275 preg = calloc(1, sizeof(regex_t));
2276 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2277 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2278 return -1;
2279 }
2280
2281 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2282 }
2283 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2284 regex_t *preg;
2285 if (curproxy == &defproxy) {
2286 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2287 return -1;
2288 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002289 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2290 return 0;
2291
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 if (*(args[1]) == 0) {
2293 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2294 return -1;
2295 }
2296
2297 preg = calloc(1, sizeof(regex_t));
2298 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2299 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2300 return -1;
2301 }
2302
2303 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2304 }
2305 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2306 regex_t *preg;
2307 if (curproxy == &defproxy) {
2308 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2309 return -1;
2310 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002311 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2312 return 0;
2313
Willy Tarreaubaaee002006-06-26 02:48:02 +02002314 if (*(args[1]) == 0) {
2315 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2316 return -1;
2317 }
2318
2319 preg = calloc(1, sizeof(regex_t));
2320 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2321 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2322 return -1;
2323 }
2324
2325 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2326 }
2327 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2328 regex_t *preg;
2329 if (curproxy == &defproxy) {
2330 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2331 return -1;
2332 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002333 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2334 return 0;
2335
Willy Tarreaubaaee002006-06-26 02:48:02 +02002336 if (*(args[1]) == 0) {
2337 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2338 return -1;
2339 }
2340
2341 preg = calloc(1, sizeof(regex_t));
2342 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2343 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2344 return -1;
2345 }
2346
2347 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2348 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002349 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2350 regex_t *preg;
2351 if (curproxy == &defproxy) {
2352 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2353 return -1;
2354 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002355 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2356 return 0;
2357
Willy Tarreaub8750a82006-09-03 09:56:00 +02002358 if (*(args[1]) == 0) {
2359 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2360 return -1;
2361 }
2362
2363 preg = calloc(1, sizeof(regex_t));
2364 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2365 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2366 return -1;
2367 }
2368
2369 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2370 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2372 if (curproxy == &defproxy) {
2373 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2374 return -1;
2375 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002376 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2377 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378
2379 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2380 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2381 return 0;
2382 }
2383
2384 if (*(args[1]) == 0) {
2385 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2386 return -1;
2387 }
2388
2389 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2390 }
2391 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2392 regex_t *preg;
2393
2394 if (*(args[1]) == 0 || *(args[2]) == 0) {
2395 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2396 file, linenum, args[0]);
2397 return -1;
2398 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002399 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2400 return 0;
2401
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 preg = calloc(1, sizeof(regex_t));
2403 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2404 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2405 return -1;
2406 }
2407
2408 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2409 if (err) {
2410 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2411 file, linenum, *err);
2412 return -1;
2413 }
2414 }
2415 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2416 regex_t *preg;
2417 if (curproxy == &defproxy) {
2418 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2419 return -1;
2420 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002421 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2422 return 0;
2423
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 if (*(args[1]) == 0) {
2425 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2426 return -1;
2427 }
2428
2429 preg = calloc(1, sizeof(regex_t));
2430 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2431 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2432 return -1;
2433 }
2434
2435 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2436 if (err) {
2437 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2438 file, linenum, *err);
2439 return -1;
2440 }
2441 }
2442 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2443 regex_t *preg;
2444 if (curproxy == &defproxy) {
2445 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2446 return -1;
2447 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002448 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2449 return 0;
2450
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 if (*(args[1]) == 0) {
2452 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2453 return -1;
2454 }
2455
2456 preg = calloc(1, sizeof(regex_t));
2457 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2458 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2459 return -1;
2460 }
2461
2462 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2463 if (err) {
2464 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2465 file, linenum, *err);
2466 return -1;
2467 }
2468 }
2469 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2470 regex_t *preg;
2471 if (curproxy == &defproxy) {
2472 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2473 return -1;
2474 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002475 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2476 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477
2478 if (*(args[1]) == 0 || *(args[2]) == 0) {
2479 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2480 file, linenum, args[0]);
2481 return -1;
2482 }
2483
2484 preg = calloc(1, sizeof(regex_t));
2485 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2486 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2487 return -1;
2488 }
2489
2490 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2491 if (err) {
2492 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2493 file, linenum, *err);
2494 return -1;
2495 }
2496 }
2497 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2498 regex_t *preg;
2499 if (curproxy == &defproxy) {
2500 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2501 return -1;
2502 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002503 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2504 return 0;
2505
Willy Tarreaubaaee002006-06-26 02:48:02 +02002506 if (*(args[1]) == 0) {
2507 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2508 return -1;
2509 }
2510
2511 preg = calloc(1, sizeof(regex_t));
2512 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2513 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2514 return -1;
2515 }
2516
2517 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2518 if (err) {
2519 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2520 file, linenum, *err);
2521 return -1;
2522 }
2523 }
2524 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2525 regex_t *preg;
2526 if (curproxy == &defproxy) {
2527 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2528 return -1;
2529 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002530 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2531 return 0;
2532
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 if (*(args[1]) == 0) {
2534 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2535 return -1;
2536 }
2537
2538 preg = calloc(1, sizeof(regex_t));
2539 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2540 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2541 return -1;
2542 }
2543
2544 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2545 if (err) {
2546 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2547 file, linenum, *err);
2548 return -1;
2549 }
2550 }
2551 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2552 if (curproxy == &defproxy) {
2553 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2554 return -1;
2555 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002556 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2557 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558
2559 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2560 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2561 return 0;
2562 }
2563
2564 if (*(args[1]) == 0) {
2565 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2566 return -1;
2567 }
2568
2569 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2570 }
2571 else if (!strcmp(args[0], "errorloc") ||
2572 !strcmp(args[0], "errorloc302") ||
2573 !strcmp(args[0], "errorloc303")) { /* error location */
2574 int errnum, errlen;
2575 char *err;
2576
Willy Tarreau977b8e42006-12-29 14:19:17 +01002577 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2578 return 0;
2579
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002581 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 return -1;
2583 }
2584
2585 errnum = atol(args[1]);
2586 if (!strcmp(args[0], "errorloc303")) {
2587 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2588 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2589 } else {
2590 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2591 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2592 }
2593
Willy Tarreau0f772532006-12-23 20:51:41 +01002594 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2595 if (http_err_codes[rc] == errnum) {
2596 if (curproxy->errmsg[rc].str)
2597 free(curproxy->errmsg[rc].str);
2598 curproxy->errmsg[rc].str = err;
2599 curproxy->errmsg[rc].len = errlen;
2600 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002601 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002603
2604 if (rc >= HTTP_ERR_SIZE) {
2605 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2606 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 free(err);
2608 }
2609 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002610 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2611 int errnum, errlen, fd;
2612 char *err;
2613 struct stat stat;
2614
2615 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2616 return 0;
2617
2618 if (*(args[2]) == 0) {
2619 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2620 return -1;
2621 }
2622
2623 fd = open(args[2], O_RDONLY);
2624 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2625 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2626 file, linenum, args[2], args[1]);
2627 if (fd >= 0)
2628 close(fd);
2629 return -1;
2630 }
2631
2632 if (stat.st_size <= BUFSIZE) {
2633 errlen = stat.st_size;
2634 } else {
2635 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2636 file, linenum, args[2], BUFSIZE);
2637 errlen = BUFSIZE;
2638 }
2639
2640 err = malloc(errlen); /* malloc() must succeed during parsing */
2641 errnum = read(fd, err, errlen);
2642 if (errnum != errlen) {
2643 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2644 file, linenum, args[2], args[1]);
2645 close(fd);
2646 free(err);
2647 return -1;
2648 }
2649 close(fd);
2650
2651 errnum = atol(args[1]);
2652 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2653 if (http_err_codes[rc] == errnum) {
2654 if (curproxy->errmsg[rc].str)
2655 free(curproxy->errmsg[rc].str);
2656 curproxy->errmsg[rc].str = err;
2657 curproxy->errmsg[rc].len = errlen;
2658 break;
2659 }
2660 }
2661
2662 if (rc >= HTTP_ERR_SIZE) {
2663 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2664 file, linenum, errnum);
2665 free(err);
2666 }
2667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002669 struct cfg_kw_list *kwl;
2670 int index;
2671
2672 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2673 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2674 if (kwl->kw[index].section != CFG_LISTEN)
2675 continue;
2676 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2677 /* prepare error message just in case */
2678 snprintf(trash, sizeof(trash),
2679 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002680 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2681 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002682 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2683 return -1;
2684 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002685 else if (rc > 0) {
2686 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2687 return 0;
2688 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002689 return 0;
2690 }
2691 }
2692 }
2693
Willy Tarreau6daf3432008-01-22 16:44:08 +01002694 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695 return -1;
2696 }
2697 return 0;
2698}
2699
2700
2701/*
2702 * This function reads and parses the configuration file given in the argument.
2703 * returns 0 if OK, -1 if error.
2704 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002705int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002706{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002707 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002708 FILE *f;
2709 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002710 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002711 int confsect = CFG_NONE;
2712
2713 struct proxy *curproxy = NULL;
2714 struct server *newsrv = NULL;
2715
2716 if ((f=fopen(file,"r")) == NULL)
2717 return -1;
2718
2719 init_default_instance();
2720
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002721 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002722 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002723 char *end;
2724 char *args[MAX_LINE_ARGS + 1];
2725 char *line = thisline;
2726
Willy Tarreaubaaee002006-06-26 02:48:02 +02002727 linenum++;
2728
2729 end = line + strlen(line);
2730
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002731 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2732 /* Check if we reached the limit and the last char is not \n.
2733 * Watch out for the last line without the terminating '\n'!
2734 */
2735 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2736 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002737 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002738 }
2739
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002741 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 line++;
2743
2744 arg = 0;
2745 args[arg] = line;
2746
2747 while (*line && arg < MAX_LINE_ARGS) {
2748 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2749 * C equivalent value. Other combinations left unchanged (eg: \1).
2750 */
2751 if (*line == '\\') {
2752 int skip = 0;
2753 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2754 *line = line[1];
2755 skip = 1;
2756 }
2757 else if (line[1] == 'r') {
2758 *line = '\r';
2759 skip = 1;
2760 }
2761 else if (line[1] == 'n') {
2762 *line = '\n';
2763 skip = 1;
2764 }
2765 else if (line[1] == 't') {
2766 *line = '\t';
2767 skip = 1;
2768 }
2769 else if (line[1] == 'x') {
2770 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2771 unsigned char hex1, hex2;
2772 hex1 = toupper(line[2]) - '0';
2773 hex2 = toupper(line[3]) - '0';
2774 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2775 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2776 *line = (hex1<<4) + hex2;
2777 skip = 3;
2778 }
2779 else {
2780 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002781 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 }
2783 }
2784 if (skip) {
2785 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2786 end -= skip;
2787 }
2788 line++;
2789 }
2790 else if (*line == '#' || *line == '\n' || *line == '\r') {
2791 /* end of string, end of loop */
2792 *line = 0;
2793 break;
2794 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002795 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002796 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002797 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002798 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799 line++;
2800 args[++arg] = line;
2801 }
2802 else {
2803 line++;
2804 }
2805 }
2806
2807 /* empty line */
2808 if (!**args)
2809 continue;
2810
Willy Tarreau540abe42007-05-02 20:50:16 +02002811 /* zero out remaining args and ensure that at least one entry
2812 * is zeroed out.
2813 */
2814 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815 args[arg] = line;
2816 }
2817
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002818 if (!strcmp(args[0], "no")) {
2819 inv = 1;
2820 for (arg=0; *args[arg+1]; arg++)
2821 args[arg] = args[arg+1]; // shift args after inversion
2822 }
2823
2824 if (inv && strcmp(args[0], "option")) {
2825 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002826 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002827 }
2828
Willy Tarreau977b8e42006-12-29 14:19:17 +01002829 if (!strcmp(args[0], "listen") ||
2830 !strcmp(args[0], "frontend") ||
2831 !strcmp(args[0], "backend") ||
2832 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002833 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834 confsect = CFG_LISTEN;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002835 if (cursection)
2836 free(cursection);
2837 cursection = strdup(args[0]);
2838 }
2839 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 confsect = CFG_GLOBAL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002841 if (cursection)
2842 free(cursection);
2843 cursection = strdup(args[0]);
2844 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002845 /* else it's a section keyword */
2846
2847 switch (confsect) {
2848 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002849 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002850 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 break;
2852 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002853 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002854 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 break;
2856 default:
2857 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002858 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002859 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002860 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01002861 if (cursection)
2862 free(cursection);
2863 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864 fclose(f);
2865
2866 /*
2867 * Now, check for the integrity of all that we have collected.
2868 */
2869
2870 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002871 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872
2873 if ((curproxy = proxy) == NULL) {
2874 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2875 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002876 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 }
2878
2879 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002880 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002881 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002882
Willy Tarreaubaaee002006-06-26 02:48:02 +02002883 if (curproxy->state == PR_STSTOPPED) {
2884 curproxy = curproxy->next;
2885 continue;
2886 }
2887
Willy Tarreau977b8e42006-12-29 14:19:17 +01002888 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2889 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 +01002890 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 cfgerr++;
2892 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002893 else if (curproxy->cap & PR_CAP_BE &&
2894 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002895 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002896 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002897 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2898 Alert("parsing %s : %s '%s' has no dispatch address and is not in transparent or balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002899 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002900 cfgerr++;
2901 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002902
Willy Tarreau31682232007-11-29 15:38:04 +01002903 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002905 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002906 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907 cfgerr++;
2908 }
2909#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2910 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002911 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002912 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002913 cfgerr++;
2914 }
2915#endif
2916 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002917 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002918 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 }
2920 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002921
2922 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002923 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002924 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002925 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002926 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002927 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002928 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002929 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002930 }
2931 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002932 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002933 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002935 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002936 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002937 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002938 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002939 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002940 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2941 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002942
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002943 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002944 file, proxy_type_str(curproxy), curproxy->id);
2945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002946 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002947
2948 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2949 if ((newsrv = curproxy->srv) != NULL) {
2950 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2951 file, proxy_type_str(curproxy), curproxy->id);
2952 }
2953 }
2954
2955 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002956 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2957 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2958 file, curproxy->id);
2959 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002960 }
2961 }
2962
Willy Tarreau82936582007-11-30 15:20:09 +01002963 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2964 curproxy->options &= ~PR_O_DISABLE404;
2965 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2966 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2967 }
2968
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002969 /* if a default backend was specified, let's find it */
2970 if (curproxy->defbe.name) {
2971 struct proxy *target;
2972
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002973 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2974 if (!target) {
2975 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2976 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002977 cfgerr++;
2978 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002979 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2980 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002981 } else {
2982 free(curproxy->defbe.name);
2983 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002984 }
2985 }
2986
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002987 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002988 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2989 /* map jump target for ACT_SETBE in req_rep chain */
2990 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002991 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002992 struct proxy *target;
2993
Willy Tarreaua496b602006-12-17 23:15:24 +01002994 if (exp->action != ACT_SETBE)
2995 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002996
2997 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2998 if (!target) {
2999 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3000 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003001 cfgerr++;
3002 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003003 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3004 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003005 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003006 } else {
3007 free((void *)exp->replace);
3008 exp->replace = (const char *)target;
3009 }
3010 }
3011 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003012
3013 /* find the target proxy for 'use_backend' rules */
3014 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003015 struct proxy *target;
3016
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003017 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003018
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003019 if (!target) {
3020 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3021 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003022 cfgerr++;
3023 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003024 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3025 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003026 cfgerr++;
3027 } else {
3028 free((void *)rule->be.name);
3029 rule->be.backend = target;
3030 }
3031 }
3032
Willy Tarreau2738a142006-07-08 17:28:09 +02003033 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003034 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003035 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003036 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003037 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003038 " | While not properly invalid, you will certainly encounter various problems\n"
3039 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003040 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003041 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003042 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003043
Willy Tarreau1fa31262007-12-03 00:36:16 +01003044 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3045 * We must still support older configurations, so let's find out whether those
3046 * parameters have been set or must be copied from contimeouts.
3047 */
3048 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003049 if (!curproxy->timeout.tarpit ||
3050 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003051 /* tarpit timeout not set. We search in the following order:
3052 * default.tarpit, curr.connect, default.connect.
3053 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003054 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003055 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003056 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003057 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003058 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003059 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003060 }
3061 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003062 (!curproxy->timeout.queue ||
3063 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003064 /* queue timeout not set. We search in the following order:
3065 * default.queue, curr.connect, default.connect.
3066 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003067 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003068 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003069 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003070 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003071 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003072 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003073 }
3074 }
3075
Willy Tarreauf3c69202006-07-09 16:42:34 +02003076 if (curproxy->options & PR_O_SSL3_CHK) {
3077 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3078 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3079 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3080 }
3081
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003082 /* The small pools required for the capture lists */
3083 if (curproxy->nb_req_cap)
3084 curproxy->req_cap_pool = create_pool("ptrcap",
3085 curproxy->nb_req_cap * sizeof(char *),
3086 MEM_F_SHARED);
3087 if (curproxy->nb_rsp_cap)
3088 curproxy->rsp_cap_pool = create_pool("ptrcap",
3089 curproxy->nb_rsp_cap * sizeof(char *),
3090 MEM_F_SHARED);
3091
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003092 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3093 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3094 MEM_F_SHARED);
3095
Willy Tarreau86034312006-12-29 00:10:33 +01003096 /* for backwards compatibility with "listen" instances, if
3097 * fullconn is not set but maxconn is set, then maxconn
3098 * is used.
3099 */
3100 if (!curproxy->fullconn)
3101 curproxy->fullconn = curproxy->maxconn;
3102
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 /* first, we will invert the servers list order */
3104 newsrv = NULL;
3105 while (curproxy->srv) {
3106 struct server *next;
3107
3108 next = curproxy->srv->next;
3109 curproxy->srv->next = newsrv;
3110 newsrv = curproxy->srv;
3111 if (!next)
3112 break;
3113 curproxy->srv = next;
3114 }
3115
Willy Tarreau20697042007-11-15 23:26:18 +01003116 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003117 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118
Willy Tarreaub625a082007-11-26 01:15:43 +01003119 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003120 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003121 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003122 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3123 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003124 else
3125 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126
3127 if (curproxy->options & PR_O_LOGASAP)
3128 curproxy->to_log &= ~LW_BYTES;
3129
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003131 * ensure that we're not cross-dressing a TCP server into HTTP.
3132 */
3133 newsrv = curproxy->srv;
3134 while (newsrv != NULL) {
3135 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3136 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3137 file, proxy_type_str(curproxy), curproxy->id, linenum);
3138 goto err;
3139 }
3140 newsrv = newsrv->next;
3141 }
3142
3143 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144 * If this server supports a maxconn parameter, it needs a dedicated
3145 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003146 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 */
3148 newsrv = curproxy->srv;
3149 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003150 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151 /* Only 'minconn' was specified, or it was higher than or equal
3152 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3153 * this will avoid further useless expensive computations.
3154 */
3155 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003156 } else if (newsrv->maxconn && !newsrv->minconn) {
3157 /* minconn was not specified, so we set it to maxconn */
3158 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003159 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3160 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003161 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003162 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163 }
3164
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003165 if (newsrv->trackit) {
3166 struct proxy *px;
3167 struct server *srv;
3168 char *pname, *sname;
3169
3170 pname = newsrv->trackit;
3171 sname = strrchr(pname, '/');
3172
3173 if (sname)
3174 *sname++ = '\0';
3175 else {
3176 sname = pname;
3177 pname = NULL;
3178 }
3179
3180 if (pname) {
3181 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3182 if (!px) {
3183 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3184 file, proxy_type_str(curproxy), curproxy->id,
3185 newsrv->id, pname);
3186 return -1;
3187 }
3188 } else
3189 px = curproxy;
3190
3191 srv = findserver(px, sname);
3192 if (!srv) {
3193 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3194 file, proxy_type_str(curproxy), curproxy->id,
3195 newsrv->id, sname);
3196 return -1;
3197 }
3198
3199 if (!(srv->state & SRV_CHECKED)) {
3200 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3201 "tracing as it does not have checks enabled.\n",
3202 file, proxy_type_str(curproxy), curproxy->id,
3203 newsrv->id, px->id, srv->id);
3204 return -1;
3205 }
3206
3207 if (curproxy != px &&
3208 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3209 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3210 "tracing: disable-on-404 option inconsistency.\n",
3211 file, proxy_type_str(curproxy), curproxy->id,
3212 newsrv->id, px->id, srv->id);
3213 return -1;
3214 }
3215
3216 newsrv->tracked = srv;
3217 newsrv->tracknext = srv->tracknext;
3218 srv->tracknext = newsrv;
3219
3220 free(newsrv->trackit);
3221 }
3222
Willy Tarreaubaaee002006-06-26 02:48:02 +02003223 newsrv = newsrv->next;
3224 }
3225
Willy Tarreaue6b98942007-10-29 01:09:36 +01003226 /* adjust this proxy's listeners */
3227 listener = curproxy->listen;
3228 while (listener) {
3229 if (curproxy->options & PR_O_TCP_NOLING)
3230 listener->options |= LI_O_NOLINGER;
3231 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003232 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003233 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003234 listener->accept = event_accept;
3235 listener->private = curproxy;
3236
3237 listener = listener->next;
3238 }
3239
Willy Tarreaubaaee002006-06-26 02:48:02 +02003240 curproxy = curproxy->next;
3241 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003242
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 if (cfgerr > 0) {
3244 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003245 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003246 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003247
3248 /*
3249 * Recount currently required checks.
3250 */
3251
3252 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3253 int optnum;
3254
3255 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3256 if (!(curproxy->options & cfg_opts[optnum].val))
3257 continue;
3258
3259 global.last_checks |= cfg_opts[optnum].checks;
3260 }
3261 }
3262
Willy Tarreau6daf3432008-01-22 16:44:08 +01003263 if (cursection)
3264 free(cursection);
3265 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003266 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003267
3268 err:
3269 if (cursection)
3270 free(cursection);
3271 cursection = NULL;
3272 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273}
3274
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003275/*
3276 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3277 * parsing sessions.
3278 */
3279void cfg_register_keywords(struct cfg_kw_list *kwl)
3280{
3281 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3282}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003284/*
3285 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3286 */
3287void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3288{
3289 LIST_DEL(&kwl->list);
3290 LIST_INIT(&kwl->list);
3291}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292
3293/*
3294 * Local variables:
3295 * c-indent-level: 8
3296 * c-basic-offset: 8
3297 * End:
3298 */