blob: 9aac0eb81c195525e377b89460d19f9d9674cd86 [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 }
1119 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1120 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001121 else if (!strcmp(args[0], "redirect")) {
1122 int pol = ACL_COND_NONE;
1123 struct acl_cond *cond;
1124 struct redirect_rule *rule;
1125 int cur_arg;
1126 int type = REDIRECT_TYPE_NONE;
1127 int code = 302;
1128 char *destination = NULL;
1129
1130 cur_arg = 1;
1131 while (*(args[cur_arg])) {
1132 if (!strcmp(args[cur_arg], "location")) {
1133 if (!*args[cur_arg + 1]) {
1134 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1135 file, linenum, args[0], args[cur_arg]);
1136 return -1;
1137 }
1138
1139 type = REDIRECT_TYPE_LOCATION;
1140 cur_arg++;
1141 destination = args[cur_arg];
1142 }
1143 else if (!strcmp(args[cur_arg], "prefix")) {
1144 if (!*args[cur_arg + 1]) {
1145 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1146 file, linenum, args[0], args[cur_arg]);
1147 return -1;
1148 }
1149
1150 type = REDIRECT_TYPE_PREFIX;
1151 cur_arg++;
1152 destination = args[cur_arg];
1153 }
1154 else if (!strcmp(args[cur_arg],"code")) {
1155 if (!*args[cur_arg + 1]) {
1156 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1157 file, linenum, args[0]);
1158 return -1;
1159 }
1160 cur_arg++;
1161 code = atol(args[cur_arg]);
1162 if (code < 301 || code > 303) {
1163 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1164 file, linenum, args[0], code);
1165 return -1;
1166 }
1167 }
1168 else if (!strcmp(args[cur_arg], "if")) {
1169 pol = ACL_COND_IF;
1170 cur_arg++;
1171 break;
1172 }
1173 else if (!strcmp(args[cur_arg], "unless")) {
1174 pol = ACL_COND_UNLESS;
1175 cur_arg++;
1176 break;
1177 }
1178 else {
1179 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1180 file, linenum, args[0], args[cur_arg]);
1181 return -1;
1182 }
1183 cur_arg++;
1184 }
1185
1186 if (type == REDIRECT_TYPE_NONE) {
1187 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1188 file, linenum, args[0]);
1189 return -1;
1190 }
1191
1192 if (pol == ACL_COND_NONE) {
1193 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1194 file, linenum, args[0]);
1195 return -1;
1196 }
1197
1198 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1199 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1200 file, linenum, args[0]);
1201 return -1;
1202 }
1203
1204 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1205 rule->cond = cond;
1206 rule->rdr_str = strdup(destination);
1207 rule->rdr_len = strlen(destination);
1208 rule->type = type;
1209 rule->code = code;
1210 LIST_INIT(&rule->list);
1211 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1212 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001213 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1214 int pol = ACL_COND_NONE;
1215 struct acl_cond *cond;
1216 struct switching_rule *rule;
1217
1218 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1219 return 0;
1220
1221 if (*(args[1]) == 0) {
1222 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1223 return -1;
1224 }
1225
1226 if (!strcmp(args[2], "if"))
1227 pol = ACL_COND_IF;
1228 else if (!strcmp(args[2], "unless"))
1229 pol = ACL_COND_UNLESS;
1230
1231 if (pol == ACL_COND_NONE) {
1232 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1233 file, linenum, args[0]);
1234 return -1;
1235 }
1236
1237 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1238 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1239 file, linenum);
1240 return -1;
1241 }
1242
1243 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1244 rule->cond = cond;
1245 rule->be.name = strdup(args[1]);
1246 LIST_INIT(&rule->list);
1247 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001249 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001250 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1251 return 0;
1252
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1254 curproxy->uri_auth = NULL; /* we must detach from the default config */
1255
1256 if (*(args[1]) == 0) {
1257 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1258 return -1;
1259 } else if (!strcmp(args[1], "uri")) {
1260 if (*(args[2]) == 0) {
1261 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1262 return -1;
1263 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1264 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1265 return -1;
1266 }
1267 } else if (!strcmp(args[1], "realm")) {
1268 if (*(args[2]) == 0) {
1269 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1270 return -1;
1271 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1272 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1273 return -1;
1274 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001275 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001276 unsigned interval;
1277
1278 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1279 if (err) {
1280 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1281 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001282 return -1;
1283 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1284 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1285 return -1;
1286 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001287 } else if (!strcmp(args[1], "auth")) {
1288 if (*(args[2]) == 0) {
1289 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1290 return -1;
1291 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1292 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1293 return -1;
1294 }
1295 } else if (!strcmp(args[1], "scope")) {
1296 if (*(args[2]) == 0) {
1297 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1298 return -1;
1299 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1300 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1301 return -1;
1302 }
1303 } else if (!strcmp(args[1], "enable")) {
1304 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1305 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1306 return -1;
1307 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001308 } else if (!strcmp(args[1], "hide-version")) {
1309 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1310 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1311 return -1;
1312 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001313 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001314 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315 file, linenum, args[0]);
1316 return -1;
1317 }
1318 }
1319 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001320 int optnum;
1321
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001322 if (*(args[1]) == '\0') {
1323 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1324 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001325 return -1;
1326 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001327
1328 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1329 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1330 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1331 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001332
1333 if (!inv)
1334 curproxy->options |= cfg_opts[optnum].val;
1335 else
1336 curproxy->options &= ~cfg_opts[optnum].val;
1337
Willy Tarreau13943ab2006-12-31 00:24:10 +01001338 return 0;
1339 }
1340 }
1341
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001342 if (inv) {
1343 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1344 file, linenum, args[1]);
1345 return -1;
1346 }
1347
Willy Tarreau13943ab2006-12-31 00:24:10 +01001348 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 /* generate a complete HTTP log */
1350 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1351 else if (!strcmp(args[1], "tcplog"))
1352 /* generate a detailed TCP log */
1353 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001354 else if (!strcmp(args[1], "tcpka")) {
1355 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001356 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1357 return 0;
1358
1359 if (curproxy->cap & PR_CAP_FE)
1360 curproxy->options |= PR_O_TCP_CLI_KA;
1361 if (curproxy->cap & PR_CAP_BE)
1362 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363 }
1364 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001365 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1366 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 /* use HTTP request to check servers' health */
1368 if (curproxy->check_req != NULL) {
1369 free(curproxy->check_req);
1370 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001371 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001372 curproxy->options &= ~PR_O_SMTP_CHK;
1373 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001374 if (!*args[2]) { /* no argument */
1375 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1376 curproxy->check_len = strlen(DEF_CHECK_REQ);
1377 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001378 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001379 curproxy->check_req = (char *)malloc(reqlen);
1380 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1381 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1382 } else { /* more arguments : METHOD URI [HTTP_VER] */
1383 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1384 if (*args[4])
1385 reqlen += strlen(args[4]);
1386 else
1387 reqlen += strlen("HTTP/1.0");
1388
1389 curproxy->check_req = (char *)malloc(reqlen);
1390 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1391 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1392 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001393 }
1394 else if (!strcmp(args[1], "ssl-hello-chk")) {
1395 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001396 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1397 return 0;
1398
Willy Tarreauf3c69202006-07-09 16:42:34 +02001399 if (curproxy->check_req != NULL) {
1400 free(curproxy->check_req);
1401 }
1402 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001403 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001404 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405 }
Willy Tarreau23677902007-05-08 23:50:35 +02001406 else if (!strcmp(args[1], "smtpchk")) {
1407 /* use SMTP request to check servers' health */
1408 if (curproxy->check_req != NULL) {
1409 free(curproxy->check_req);
1410 }
1411 curproxy->options &= ~PR_O_HTTP_CHK;
1412 curproxy->options &= ~PR_O_SSL3_CHK;
1413 curproxy->options |= PR_O_SMTP_CHK;
1414
1415 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1416 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1417 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1418 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1419 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1420 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1421 curproxy->check_req = (char *)malloc(reqlen);
1422 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1423 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1424 } else {
1425 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1426 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1427 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1428 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1429 }
1430 }
1431 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001432 else if (!strcmp(args[1], "forwardfor")) {
1433 /* insert x-forwarded-for field, but not for the
1434 * IP address listed as an except.
1435 */
1436 if (*(args[2])) {
1437 if (!strcmp(args[2], "except")) {
1438 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1439 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1440 file, linenum, args[0]);
1441 return -1;
1442 }
1443 /* flush useless bits */
1444 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1445 } else {
1446 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1447 file, linenum, args[0]);
1448 return -1;
1449 }
1450 }
1451 curproxy->options |= PR_O_FWDFOR;
1452 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453 else {
1454 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1455 return -1;
1456 }
1457 return 0;
1458 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001459 else if (!strcmp(args[0], "default_backend")) {
1460 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1461 return 0;
1462
1463 if (*(args[1]) == 0) {
1464 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1465 return -1;
1466 }
1467 if (curproxy->defbe.name)
1468 free(curproxy->defbe.name);
1469 curproxy->defbe.name = strdup(args[1]);
1470 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001471 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001472 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1473 return 0;
1474
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001475 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1476 file, linenum, args[0]);
1477
Willy Tarreaubaaee002006-06-26 02:48:02 +02001478 /* enable reconnections to dispatch */
1479 curproxy->options |= PR_O_REDISP;
1480 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001481 else if (!strcmp(args[0], "http-check")) {
1482 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1483 return 0;
1484
1485 if (strcmp(args[1], "disable-on-404") == 0) {
1486 /* enable a graceful server shutdown on an HTTP 404 response */
1487 curproxy->options |= PR_O_DISABLE404;
1488 }
1489 else {
1490 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1491 return -1;
1492 }
1493 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001494 else if (!strcmp(args[0], "monitor")) {
1495 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1496 return 0;
1497
1498 if (strcmp(args[1], "fail") == 0) {
1499 /* add a condition to fail monitor requests */
1500 int pol = ACL_COND_NONE;
1501 struct acl_cond *cond;
1502
1503 if (!strcmp(args[2], "if"))
1504 pol = ACL_COND_IF;
1505 else if (!strcmp(args[2], "unless"))
1506 pol = ACL_COND_UNLESS;
1507
1508 if (pol == ACL_COND_NONE) {
1509 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1510 file, linenum, args[0], args[1]);
1511 return -1;
1512 }
1513
1514 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1515 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1516 file, linenum, args[0], args[1]);
1517 return -1;
1518 }
1519 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1520 }
1521 else {
1522 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1523 return -1;
1524 }
1525 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001526#ifdef TPROXY
1527 else if (!strcmp(args[0], "transparent")) {
1528 /* enable transparent proxy connections */
1529 curproxy->options |= PR_O_TRANSP;
1530 }
1531#endif
1532 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001533 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1534 return 0;
1535
Willy Tarreaubaaee002006-06-26 02:48:02 +02001536 if (*(args[1]) == 0) {
1537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1538 return -1;
1539 }
1540 curproxy->maxconn = atol(args[1]);
1541 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001542 else if (!strcmp(args[0], "backlog")) { /* backlog */
1543 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1544 return 0;
1545
1546 if (*(args[1]) == 0) {
1547 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1548 return -1;
1549 }
1550 curproxy->backlog = atol(args[1]);
1551 }
Willy Tarreau86034312006-12-29 00:10:33 +01001552 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001553 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1554 return 0;
1555
Willy Tarreau86034312006-12-29 00:10:33 +01001556 if (*(args[1]) == 0) {
1557 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1558 return -1;
1559 }
1560 curproxy->fullconn = atol(args[1]);
1561 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1563 if (*(args[1]) == 0) {
1564 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1565 return -1;
1566 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001567 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1568 if (err) {
1569 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1570 file, linenum, *err);
1571 return -1;
1572 }
1573 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001574 }
1575 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1576 if (curproxy == &defproxy) {
1577 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1578 return -1;
1579 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001580 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1581 return 0;
1582
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 if (strchr(args[1], ':') == NULL) {
1584 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1585 return -1;
1586 }
1587 curproxy->dispatch_addr = *str2sa(args[1]);
1588 }
1589 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001590 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1591 return 0;
1592
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001593 memcpy(trash, "error near 'balance'", 19);
1594 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1595 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1596 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001597 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 }
1599 else if (!strcmp(args[0], "server")) { /* server address */
1600 int cur_arg;
1601 char *rport;
1602 char *raddr;
1603 short realport;
1604 int do_check;
1605
1606 if (curproxy == &defproxy) {
1607 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1608 return -1;
1609 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001610 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1611 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001612
1613 if (!*args[2]) {
1614 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1615 file, linenum, args[0]);
1616 return -1;
1617 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001618
1619 err = invalid_char(args[1]);
1620 if (err) {
1621 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1622 file, linenum, *err, args[1]);
1623 return -1;
1624 }
1625
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1627 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1628 return -1;
1629 }
1630
1631 /* the servers are linked backwards first */
1632 newsrv->next = curproxy->srv;
1633 curproxy->srv = newsrv;
1634 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001635 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636
1637 LIST_INIT(&newsrv->pendconns);
1638 do_check = 0;
1639 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001640 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001641 newsrv->id = strdup(args[1]);
1642
1643 /* several ways to check the port component :
1644 * - IP => port=+0, relative
1645 * - IP: => port=+0, relative
1646 * - IP:N => port=N, absolute
1647 * - IP:+N => port=+N, relative
1648 * - IP:-N => port=-N, relative
1649 */
1650 raddr = strdup(args[2]);
1651 rport = strchr(raddr, ':');
1652 if (rport) {
1653 *rport++ = 0;
1654 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001655 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 newsrv->state |= SRV_MAPPORTS;
1657 } else {
1658 realport = 0;
1659 newsrv->state |= SRV_MAPPORTS;
1660 }
1661
1662 newsrv->addr = *str2sa(raddr);
1663 newsrv->addr.sin_port = htons(realport);
1664 free(raddr);
1665
1666 newsrv->curfd = -1; /* no health-check in progress */
1667 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001668 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1669 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670 newsrv->rise = DEF_RISETIME;
1671 newsrv->fall = DEF_FALLTIME;
1672 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001673 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001674 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001675 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001676
Willy Tarreaubaaee002006-06-26 02:48:02 +02001677 cur_arg = 3;
1678 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001679 if (!strcmp(args[cur_arg], "id")) {
1680 struct server *target;
1681
1682 if (!*args[cur_arg + 1]) {
1683 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1684 file, linenum, args[cur_arg]);
1685 return -1;
1686 }
1687
1688 newsrv->puid = atol(args[cur_arg + 1]);
1689
1690 if (newsrv->puid< 1001) {
1691 Alert("parsing [%s:%d]: custom id has to be > 1000",
1692 file, linenum);
1693 return -1;
1694 }
1695
1696 for (target = proxy->srv; target; target = target->next)
1697 if (newsrv != target && newsrv->puid == target->puid) {
1698 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1699 file, linenum, newsrv->id, target->id);
1700 return -1;
1701 }
1702 cur_arg += 2;
1703 }
1704 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001705 newsrv->cookie = strdup(args[cur_arg + 1]);
1706 newsrv->cklen = strlen(args[cur_arg + 1]);
1707 cur_arg += 2;
1708 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001709 else if (!strcmp(args[cur_arg], "redir")) {
1710 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1711 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1712 cur_arg += 2;
1713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 else if (!strcmp(args[cur_arg], "rise")) {
1715 newsrv->rise = atol(args[cur_arg + 1]);
1716 newsrv->health = newsrv->rise;
1717 cur_arg += 2;
1718 }
1719 else if (!strcmp(args[cur_arg], "fall")) {
1720 newsrv->fall = atol(args[cur_arg + 1]);
1721 cur_arg += 2;
1722 }
1723 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001724 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1725 if (err) {
1726 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1727 file, linenum, *err, newsrv->id);
1728 return -1;
1729 }
1730 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001731 cur_arg += 2;
1732 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001733 else if (!strcmp(args[cur_arg], "fastinter")) {
1734 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1735 if (err) {
1736 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1737 file, linenum, *err, newsrv->id);
1738 return -1;
1739 }
1740 newsrv->fastinter = val;
1741 cur_arg += 2;
1742 }
1743 else if (!strcmp(args[cur_arg], "downinter")) {
1744 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1745 if (err) {
1746 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1747 file, linenum, *err, newsrv->id);
1748 return -1;
1749 }
1750 newsrv->downinter = val;
1751 cur_arg += 2;
1752 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001753 else if (!strcmp(args[cur_arg], "addr")) {
1754 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001755 cur_arg += 2;
1756 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001757 else if (!strcmp(args[cur_arg], "port")) {
1758 newsrv->check_port = atol(args[cur_arg + 1]);
1759 cur_arg += 2;
1760 }
1761 else if (!strcmp(args[cur_arg], "backup")) {
1762 newsrv->state |= SRV_BACKUP;
1763 cur_arg ++;
1764 }
1765 else if (!strcmp(args[cur_arg], "weight")) {
1766 int w;
1767 w = atol(args[cur_arg + 1]);
1768 if (w < 1 || w > 256) {
1769 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1770 file, linenum, newsrv->id, w);
1771 return -1;
1772 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001773 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774 cur_arg += 2;
1775 }
1776 else if (!strcmp(args[cur_arg], "minconn")) {
1777 newsrv->minconn = atol(args[cur_arg + 1]);
1778 cur_arg += 2;
1779 }
1780 else if (!strcmp(args[cur_arg], "maxconn")) {
1781 newsrv->maxconn = atol(args[cur_arg + 1]);
1782 cur_arg += 2;
1783 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001784 else if (!strcmp(args[cur_arg], "maxqueue")) {
1785 newsrv->maxqueue = atol(args[cur_arg + 1]);
1786 cur_arg += 2;
1787 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001788 else if (!strcmp(args[cur_arg], "slowstart")) {
1789 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001790 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001791 if (err) {
1792 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1793 file, linenum, *err, newsrv->id);
1794 return -1;
1795 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001796 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001797 cur_arg += 2;
1798 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001799 else if (!strcmp(args[cur_arg], "track")) {
1800
1801 if (!*args[cur_arg + 1]) {
1802 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1803 file, linenum);
1804 return -1;
1805 }
1806
1807 newsrv->trackit = strdup(args[cur_arg + 1]);
1808
1809 cur_arg += 2;
1810 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001811 else if (!strcmp(args[cur_arg], "check")) {
1812 global.maxsock++;
1813 do_check = 1;
1814 cur_arg += 1;
1815 }
1816 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1817 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001818#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001819 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1820 file, linenum, "source", "usesrc");
1821#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001822 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1823 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001824#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001825 return -1;
1826 }
1827 newsrv->state |= SRV_BIND_SRC;
1828 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1829 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001830 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001831#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1832#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001833 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001834 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1835 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001836 return -1;
1837 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001838#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001839 if (!*args[cur_arg + 1]) {
1840 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1841 file, linenum, "usesrc");
1842 return -1;
1843 }
1844 if (!strcmp(args[cur_arg + 1], "client")) {
1845 newsrv->state |= SRV_TPROXY_CLI;
1846 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1847 newsrv->state |= SRV_TPROXY_CIP;
1848 } else {
1849 newsrv->state |= SRV_TPROXY_ADDR;
1850 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1851 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001852 global.last_checks |= LSTCHK_NETADM;
1853#if !defined(CONFIG_HAP_LINUX_TPROXY)
1854 global.last_checks |= LSTCHK_CTTPROXY;
1855#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001856 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001857#else /* no TPROXY support */
1858 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001859 file, linenum, "usesrc");
1860 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001861#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001862 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001863 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001864 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1865 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1866 file, linenum, "usesrc", "source");
1867 return -1;
1868 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001869 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001870 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 +02001871 file, linenum, newsrv->id);
1872 return -1;
1873 }
1874 }
1875
1876 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001877 if (newsrv->trackit) {
1878 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1879 file, linenum);
1880 return -1;
1881 }
1882
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001883 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1884 newsrv->check_port = newsrv->check_addr.sin_port;
1885
Willy Tarreaubaaee002006-06-26 02:48:02 +02001886 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1887 newsrv->check_port = realport; /* by default */
1888 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001889 /* not yet valid, because no port was set on
1890 * the server either. We'll check if we have
1891 * a known port on the first listener.
1892 */
1893 struct listener *l;
1894 l = curproxy->listen;
1895 if (l) {
1896 int port;
1897 port = (l->addr.ss_family == AF_INET6)
1898 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1899 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1900 newsrv->check_port = port;
1901 }
1902 }
1903 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1905 file, linenum, newsrv->id);
1906 return -1;
1907 }
1908 newsrv->state |= SRV_CHECKED;
1909 }
1910
1911 if (newsrv->state & SRV_BACKUP)
1912 curproxy->srv_bck++;
1913 else
1914 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001915
1916 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001917 }
1918 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001919 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 int facility;
1921
1922 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1923 curproxy->logfac1 = global.logfac1;
1924 curproxy->logsrv1 = global.logsrv1;
1925 curproxy->loglev1 = global.loglev1;
1926 curproxy->logfac2 = global.logfac2;
1927 curproxy->logsrv2 = global.logsrv2;
1928 curproxy->loglev2 = global.loglev2;
1929 }
1930 else if (*(args[1]) && *(args[2])) {
1931 int level;
1932
1933 facility = get_log_facility(args[2]);
1934 if (facility < 0) {
1935 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1936 exit(1);
1937 }
1938
1939 level = 7; /* max syslog level = debug */
1940 if (*(args[3])) {
1941 level = get_log_level(args[3]);
1942 if (level < 0) {
1943 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1944 exit(1);
1945 }
1946 }
1947
Robert Tsai81ae1952007-12-05 10:47:29 +01001948 if (args[1][0] == '/') {
1949 logsrv.u.addr.sa_family = AF_UNIX;
1950 logsrv.u.un = *str2sun(args[1]);
1951 } else {
1952 logsrv.u.addr.sa_family = AF_INET;
1953 logsrv.u.in = *str2sa(args[1]);
1954 if (!logsrv.u.in.sin_port) {
1955 logsrv.u.in.sin_port =
1956 htons(SYSLOG_PORT);
1957 }
1958 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001959
1960 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001961 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962 curproxy->logfac1 = facility;
1963 curproxy->loglev1 = level;
1964 }
1965 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001966 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001967 curproxy->logfac2 = facility;
1968 curproxy->loglev2 = level;
1969 }
1970 else {
1971 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1972 return -1;
1973 }
1974 }
1975 else {
1976 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1977 file, linenum);
1978 return -1;
1979 }
1980 }
1981 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001982 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1983 return 0;
1984
Willy Tarreaubaaee002006-06-26 02:48:02 +02001985 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001986#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001987 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1988 file, linenum, "source", "usesrc");
1989#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001990 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1991 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001992#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001993 return -1;
1994 }
1995
1996 curproxy->source_addr = *str2sa(args[1]);
1997 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001998 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001999#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2000#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002001 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2002 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2003 file, linenum, "usesrc");
2004 return -1;
2005 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002006#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002007 if (!*args[3]) {
2008 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2009 file, linenum, "usesrc");
2010 return -1;
2011 }
2012
2013 if (!strcmp(args[3], "client")) {
2014 curproxy->options |= PR_O_TPXY_CLI;
2015 } else if (!strcmp(args[3], "clientip")) {
2016 curproxy->options |= PR_O_TPXY_CIP;
2017 } else {
2018 curproxy->options |= PR_O_TPXY_ADDR;
2019 curproxy->tproxy_addr = *str2sa(args[3]);
2020 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002021 global.last_checks |= LSTCHK_NETADM;
2022#if !defined(CONFIG_HAP_LINUX_TPROXY)
2023 global.last_checks |= LSTCHK_CTTPROXY;
2024#endif
2025#else /* no TPROXY support */
2026 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002027 file, linenum, "usesrc");
2028 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002029#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002032 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2033 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2034 file, linenum, "usesrc", "source");
2035 return -1;
2036 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002037 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2038 regex_t *preg;
2039 if (curproxy == &defproxy) {
2040 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2041 return -1;
2042 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002043 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2044 return 0;
2045
Willy Tarreaubaaee002006-06-26 02:48:02 +02002046 if (*(args[1]) == 0 || *(args[2]) == 0) {
2047 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2048 file, linenum, args[0]);
2049 return -1;
2050 }
2051
2052 preg = calloc(1, sizeof(regex_t));
2053 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2054 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2055 return -1;
2056 }
2057
2058 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2059 if (err) {
2060 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2061 file, linenum, *err);
2062 return -1;
2063 }
2064 }
2065 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2066 regex_t *preg;
2067 if (curproxy == &defproxy) {
2068 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2069 return -1;
2070 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002071 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2072 return 0;
2073
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 if (*(args[1]) == 0) {
2075 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2076 return -1;
2077 }
2078
2079 preg = calloc(1, sizeof(regex_t));
2080 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2081 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2082 return -1;
2083 }
2084
2085 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2086 }
2087 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2088 regex_t *preg;
2089 if (curproxy == &defproxy) {
2090 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2091 return -1;
2092 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002093 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2094 return 0;
2095
Willy Tarreaubaaee002006-06-26 02:48:02 +02002096 if (*(args[1]) == 0) {
2097 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2098 return -1;
2099 }
2100
2101 preg = calloc(1, sizeof(regex_t));
2102 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2103 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2104 return -1;
2105 }
2106
2107 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2108 }
2109 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2110 regex_t *preg;
2111 if (curproxy == &defproxy) {
2112 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2113 return -1;
2114 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002115 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2116 return 0;
2117
Willy Tarreaubaaee002006-06-26 02:48:02 +02002118 if (*(args[1]) == 0) {
2119 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2120 return -1;
2121 }
2122
2123 preg = calloc(1, sizeof(regex_t));
2124 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2125 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2126 return -1;
2127 }
2128
2129 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2130 }
2131 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2132 regex_t *preg;
2133 if (curproxy == &defproxy) {
2134 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2135 return -1;
2136 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002137 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2138 return 0;
2139
Willy Tarreaubaaee002006-06-26 02:48:02 +02002140 if (*(args[1]) == 0) {
2141 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2142 return -1;
2143 }
2144
2145 preg = calloc(1, sizeof(regex_t));
2146 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2147 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2148 return -1;
2149 }
2150
2151 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2152 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002153 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2154 regex_t *preg;
2155 if (curproxy == &defproxy) {
2156 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2157 return -1;
2158 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002159 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2160 return 0;
2161
Willy Tarreaub8750a82006-09-03 09:56:00 +02002162 if (*(args[1]) == 0) {
2163 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2164 return -1;
2165 }
2166
2167 preg = calloc(1, sizeof(regex_t));
2168 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2169 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2170 return -1;
2171 }
2172
2173 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2174 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002175 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2176 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002177 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002178 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2179 return -1;
2180 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002181 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2182 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002183
Willy Tarreau977b8e42006-12-29 14:19:17 +01002184 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002185 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2186 file, linenum, args[0]);
2187 return -1;
2188 }
2189
2190 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002191 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002192 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2193 }
2194
2195 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2196 }
2197 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2198 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002199 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002200 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2201 return -1;
2202 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002203 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2204 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002205
Willy Tarreau977b8e42006-12-29 14:19:17 +01002206 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002207 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2208 file, linenum, args[0]);
2209 return -1;
2210 }
2211
2212 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002213 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002214 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2215 }
2216
2217 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2218 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002219 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2220 regex_t *preg;
2221 if (curproxy == &defproxy) {
2222 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2223 return -1;
2224 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002225 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2226 return 0;
2227
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 if (*(args[1]) == 0 || *(args[2]) == 0) {
2229 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2230 file, linenum, args[0]);
2231 return -1;
2232 }
2233
2234 preg = calloc(1, sizeof(regex_t));
2235 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2236 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2237 return -1;
2238 }
2239
2240 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2241 if (err) {
2242 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2243 file, linenum, *err);
2244 return -1;
2245 }
2246 }
2247 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2248 regex_t *preg;
2249 if (curproxy == &defproxy) {
2250 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2251 return -1;
2252 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002253 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2254 return 0;
2255
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 if (*(args[1]) == 0) {
2257 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2258 return -1;
2259 }
2260
2261 preg = calloc(1, sizeof(regex_t));
2262 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2263 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2264 return -1;
2265 }
2266
2267 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2268 }
2269 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2270 regex_t *preg;
2271 if (curproxy == &defproxy) {
2272 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2273 return -1;
2274 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002275 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2276 return 0;
2277
Willy Tarreaubaaee002006-06-26 02:48:02 +02002278 if (*(args[1]) == 0) {
2279 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2280 return -1;
2281 }
2282
2283 preg = calloc(1, sizeof(regex_t));
2284 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2285 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2286 return -1;
2287 }
2288
2289 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2290 }
2291 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2292 regex_t *preg;
2293 if (curproxy == &defproxy) {
2294 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2295 return -1;
2296 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002297 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2298 return 0;
2299
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 if (*(args[1]) == 0) {
2301 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2302 return -1;
2303 }
2304
2305 preg = calloc(1, sizeof(regex_t));
2306 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2307 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2308 return -1;
2309 }
2310
2311 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2312 }
2313 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2314 regex_t *preg;
2315 if (curproxy == &defproxy) {
2316 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2317 return -1;
2318 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002319 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2320 return 0;
2321
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322 if (*(args[1]) == 0) {
2323 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2324 return -1;
2325 }
2326
2327 preg = calloc(1, sizeof(regex_t));
2328 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2329 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2330 return -1;
2331 }
2332
2333 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2334 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002335 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2336 regex_t *preg;
2337 if (curproxy == &defproxy) {
2338 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2339 return -1;
2340 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002341 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2342 return 0;
2343
Willy Tarreaub8750a82006-09-03 09:56:00 +02002344 if (*(args[1]) == 0) {
2345 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2346 return -1;
2347 }
2348
2349 preg = calloc(1, sizeof(regex_t));
2350 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2351 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2352 return -1;
2353 }
2354
2355 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2356 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2358 if (curproxy == &defproxy) {
2359 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2360 return -1;
2361 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002362 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2363 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364
2365 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2366 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2367 return 0;
2368 }
2369
2370 if (*(args[1]) == 0) {
2371 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2372 return -1;
2373 }
2374
2375 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2376 }
2377 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2378 regex_t *preg;
2379
2380 if (*(args[1]) == 0 || *(args[2]) == 0) {
2381 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2382 file, linenum, args[0]);
2383 return -1;
2384 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002385 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2386 return 0;
2387
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 preg = calloc(1, sizeof(regex_t));
2389 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2390 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2391 return -1;
2392 }
2393
2394 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2395 if (err) {
2396 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2397 file, linenum, *err);
2398 return -1;
2399 }
2400 }
2401 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2402 regex_t *preg;
2403 if (curproxy == &defproxy) {
2404 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2405 return -1;
2406 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002407 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2408 return 0;
2409
Willy Tarreaubaaee002006-06-26 02:48:02 +02002410 if (*(args[1]) == 0) {
2411 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2412 return -1;
2413 }
2414
2415 preg = calloc(1, sizeof(regex_t));
2416 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2417 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2418 return -1;
2419 }
2420
2421 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2422 if (err) {
2423 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2424 file, linenum, *err);
2425 return -1;
2426 }
2427 }
2428 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2429 regex_t *preg;
2430 if (curproxy == &defproxy) {
2431 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2432 return -1;
2433 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002434 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2435 return 0;
2436
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 if (*(args[1]) == 0) {
2438 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2439 return -1;
2440 }
2441
2442 preg = calloc(1, sizeof(regex_t));
2443 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2444 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2445 return -1;
2446 }
2447
2448 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2449 if (err) {
2450 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2451 file, linenum, *err);
2452 return -1;
2453 }
2454 }
2455 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2456 regex_t *preg;
2457 if (curproxy == &defproxy) {
2458 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2459 return -1;
2460 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002461 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2462 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463
2464 if (*(args[1]) == 0 || *(args[2]) == 0) {
2465 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2466 file, linenum, args[0]);
2467 return -1;
2468 }
2469
2470 preg = calloc(1, sizeof(regex_t));
2471 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2472 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2473 return -1;
2474 }
2475
2476 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2477 if (err) {
2478 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2479 file, linenum, *err);
2480 return -1;
2481 }
2482 }
2483 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2484 regex_t *preg;
2485 if (curproxy == &defproxy) {
2486 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2487 return -1;
2488 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002489 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2490 return 0;
2491
Willy Tarreaubaaee002006-06-26 02:48:02 +02002492 if (*(args[1]) == 0) {
2493 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2494 return -1;
2495 }
2496
2497 preg = calloc(1, sizeof(regex_t));
2498 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2499 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2500 return -1;
2501 }
2502
2503 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2504 if (err) {
2505 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2506 file, linenum, *err);
2507 return -1;
2508 }
2509 }
2510 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2511 regex_t *preg;
2512 if (curproxy == &defproxy) {
2513 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2514 return -1;
2515 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002516 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2517 return 0;
2518
Willy Tarreaubaaee002006-06-26 02:48:02 +02002519 if (*(args[1]) == 0) {
2520 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2521 return -1;
2522 }
2523
2524 preg = calloc(1, sizeof(regex_t));
2525 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2526 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2527 return -1;
2528 }
2529
2530 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2531 if (err) {
2532 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2533 file, linenum, *err);
2534 return -1;
2535 }
2536 }
2537 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2538 if (curproxy == &defproxy) {
2539 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2540 return -1;
2541 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002542 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2543 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002544
2545 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2546 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2547 return 0;
2548 }
2549
2550 if (*(args[1]) == 0) {
2551 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2552 return -1;
2553 }
2554
2555 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2556 }
2557 else if (!strcmp(args[0], "errorloc") ||
2558 !strcmp(args[0], "errorloc302") ||
2559 !strcmp(args[0], "errorloc303")) { /* error location */
2560 int errnum, errlen;
2561 char *err;
2562
Willy Tarreau977b8e42006-12-29 14:19:17 +01002563 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2564 return 0;
2565
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002567 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 return -1;
2569 }
2570
2571 errnum = atol(args[1]);
2572 if (!strcmp(args[0], "errorloc303")) {
2573 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2574 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2575 } else {
2576 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2577 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2578 }
2579
Willy Tarreau0f772532006-12-23 20:51:41 +01002580 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2581 if (http_err_codes[rc] == errnum) {
2582 if (curproxy->errmsg[rc].str)
2583 free(curproxy->errmsg[rc].str);
2584 curproxy->errmsg[rc].str = err;
2585 curproxy->errmsg[rc].len = errlen;
2586 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002589
2590 if (rc >= HTTP_ERR_SIZE) {
2591 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2592 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 free(err);
2594 }
2595 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002596 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2597 int errnum, errlen, fd;
2598 char *err;
2599 struct stat stat;
2600
2601 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2602 return 0;
2603
2604 if (*(args[2]) == 0) {
2605 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2606 return -1;
2607 }
2608
2609 fd = open(args[2], O_RDONLY);
2610 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2611 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2612 file, linenum, args[2], args[1]);
2613 if (fd >= 0)
2614 close(fd);
2615 return -1;
2616 }
2617
2618 if (stat.st_size <= BUFSIZE) {
2619 errlen = stat.st_size;
2620 } else {
2621 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2622 file, linenum, args[2], BUFSIZE);
2623 errlen = BUFSIZE;
2624 }
2625
2626 err = malloc(errlen); /* malloc() must succeed during parsing */
2627 errnum = read(fd, err, errlen);
2628 if (errnum != errlen) {
2629 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2630 file, linenum, args[2], args[1]);
2631 close(fd);
2632 free(err);
2633 return -1;
2634 }
2635 close(fd);
2636
2637 errnum = atol(args[1]);
2638 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2639 if (http_err_codes[rc] == errnum) {
2640 if (curproxy->errmsg[rc].str)
2641 free(curproxy->errmsg[rc].str);
2642 curproxy->errmsg[rc].str = err;
2643 curproxy->errmsg[rc].len = errlen;
2644 break;
2645 }
2646 }
2647
2648 if (rc >= HTTP_ERR_SIZE) {
2649 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2650 file, linenum, errnum);
2651 free(err);
2652 }
2653 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002654 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002655 struct cfg_kw_list *kwl;
2656 int index;
2657
2658 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2659 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2660 if (kwl->kw[index].section != CFG_LISTEN)
2661 continue;
2662 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2663 /* prepare error message just in case */
2664 snprintf(trash, sizeof(trash),
2665 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002666 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2667 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002668 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2669 return -1;
2670 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002671 else if (rc > 0) {
2672 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2673 return 0;
2674 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002675 return 0;
2676 }
2677 }
2678 }
2679
Willy Tarreau6daf3432008-01-22 16:44:08 +01002680 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681 return -1;
2682 }
2683 return 0;
2684}
2685
2686
2687/*
2688 * This function reads and parses the configuration file given in the argument.
2689 * returns 0 if OK, -1 if error.
2690 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002691int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002693 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694 FILE *f;
2695 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002697 int confsect = CFG_NONE;
2698
2699 struct proxy *curproxy = NULL;
2700 struct server *newsrv = NULL;
2701
2702 if ((f=fopen(file,"r")) == NULL)
2703 return -1;
2704
2705 init_default_instance();
2706
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002707 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002708 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002709 char *end;
2710 char *args[MAX_LINE_ARGS + 1];
2711 char *line = thisline;
2712
Willy Tarreaubaaee002006-06-26 02:48:02 +02002713 linenum++;
2714
2715 end = line + strlen(line);
2716
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002717 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2718 /* Check if we reached the limit and the last char is not \n.
2719 * Watch out for the last line without the terminating '\n'!
2720 */
2721 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2722 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002723 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002724 }
2725
Willy Tarreaubaaee002006-06-26 02:48:02 +02002726 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002727 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728 line++;
2729
2730 arg = 0;
2731 args[arg] = line;
2732
2733 while (*line && arg < MAX_LINE_ARGS) {
2734 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2735 * C equivalent value. Other combinations left unchanged (eg: \1).
2736 */
2737 if (*line == '\\') {
2738 int skip = 0;
2739 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2740 *line = line[1];
2741 skip = 1;
2742 }
2743 else if (line[1] == 'r') {
2744 *line = '\r';
2745 skip = 1;
2746 }
2747 else if (line[1] == 'n') {
2748 *line = '\n';
2749 skip = 1;
2750 }
2751 else if (line[1] == 't') {
2752 *line = '\t';
2753 skip = 1;
2754 }
2755 else if (line[1] == 'x') {
2756 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2757 unsigned char hex1, hex2;
2758 hex1 = toupper(line[2]) - '0';
2759 hex2 = toupper(line[3]) - '0';
2760 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2761 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2762 *line = (hex1<<4) + hex2;
2763 skip = 3;
2764 }
2765 else {
2766 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002767 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002768 }
2769 }
2770 if (skip) {
2771 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2772 end -= skip;
2773 }
2774 line++;
2775 }
2776 else if (*line == '#' || *line == '\n' || *line == '\r') {
2777 /* end of string, end of loop */
2778 *line = 0;
2779 break;
2780 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002781 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002783 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002784 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 line++;
2786 args[++arg] = line;
2787 }
2788 else {
2789 line++;
2790 }
2791 }
2792
2793 /* empty line */
2794 if (!**args)
2795 continue;
2796
Willy Tarreau540abe42007-05-02 20:50:16 +02002797 /* zero out remaining args and ensure that at least one entry
2798 * is zeroed out.
2799 */
2800 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002801 args[arg] = line;
2802 }
2803
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002804 if (!strcmp(args[0], "no")) {
2805 inv = 1;
2806 for (arg=0; *args[arg+1]; arg++)
2807 args[arg] = args[arg+1]; // shift args after inversion
2808 }
2809
2810 if (inv && strcmp(args[0], "option")) {
2811 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002812 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002813 }
2814
Willy Tarreau977b8e42006-12-29 14:19:17 +01002815 if (!strcmp(args[0], "listen") ||
2816 !strcmp(args[0], "frontend") ||
2817 !strcmp(args[0], "backend") ||
2818 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002819 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002820 confsect = CFG_LISTEN;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002821 if (cursection)
2822 free(cursection);
2823 cursection = strdup(args[0]);
2824 }
2825 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002826 confsect = CFG_GLOBAL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002827 if (cursection)
2828 free(cursection);
2829 cursection = strdup(args[0]);
2830 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002831 /* else it's a section keyword */
2832
2833 switch (confsect) {
2834 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002835 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002836 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 break;
2838 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002839 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002840 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841 break;
2842 default:
2843 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002844 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002845 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002846 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01002847 if (cursection)
2848 free(cursection);
2849 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002850 fclose(f);
2851
2852 /*
2853 * Now, check for the integrity of all that we have collected.
2854 */
2855
2856 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002857 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002858
2859 if ((curproxy = proxy) == NULL) {
2860 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2861 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002862 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002863 }
2864
2865 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002866 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002867 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002868
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869 if (curproxy->state == PR_STSTOPPED) {
2870 curproxy = curproxy->next;
2871 continue;
2872 }
2873
Willy Tarreau977b8e42006-12-29 14:19:17 +01002874 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2875 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 +01002876 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 cfgerr++;
2878 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002879 else if (curproxy->cap & PR_CAP_BE &&
2880 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002881 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002882 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002883 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2884 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 +01002885 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886 cfgerr++;
2887 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002888
Willy Tarreau31682232007-11-29 15:38:04 +01002889 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002891 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002892 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002893 cfgerr++;
2894 }
2895#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2896 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002897 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002898 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899 cfgerr++;
2900 }
2901#endif
2902 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002903 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002904 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002905 }
2906 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002907
2908 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002909 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002910 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002911 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002913 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002914 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002915 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916 }
2917 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002918 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002919 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002920 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002921 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002922 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002923 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002924 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002925 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002926 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2927 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002928
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002929 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002930 file, proxy_type_str(curproxy), curproxy->id);
2931 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002932 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002933
2934 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2935 if ((newsrv = curproxy->srv) != NULL) {
2936 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2937 file, proxy_type_str(curproxy), curproxy->id);
2938 }
2939 }
2940
2941 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002942 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2943 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2944 file, curproxy->id);
2945 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002946 }
2947 }
2948
Willy Tarreau82936582007-11-30 15:20:09 +01002949 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2950 curproxy->options &= ~PR_O_DISABLE404;
2951 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2952 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2953 }
2954
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002955 /* if a default backend was specified, let's find it */
2956 if (curproxy->defbe.name) {
2957 struct proxy *target;
2958
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002959 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2960 if (!target) {
2961 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2962 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002963 cfgerr++;
2964 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002965 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2966 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002967 } else {
2968 free(curproxy->defbe.name);
2969 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002970 }
2971 }
2972
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002973 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002974 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2975 /* map jump target for ACT_SETBE in req_rep chain */
2976 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002977 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002978 struct proxy *target;
2979
Willy Tarreaua496b602006-12-17 23:15:24 +01002980 if (exp->action != ACT_SETBE)
2981 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002982
2983 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2984 if (!target) {
2985 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2986 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002987 cfgerr++;
2988 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002989 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2990 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002991 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002992 } else {
2993 free((void *)exp->replace);
2994 exp->replace = (const char *)target;
2995 }
2996 }
2997 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002998
2999 /* find the target proxy for 'use_backend' rules */
3000 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003001 struct proxy *target;
3002
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003003 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003004
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003005 if (!target) {
3006 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3007 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003008 cfgerr++;
3009 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003010 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3011 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003012 cfgerr++;
3013 } else {
3014 free((void *)rule->be.name);
3015 rule->be.backend = target;
3016 }
3017 }
3018
Willy Tarreau2738a142006-07-08 17:28:09 +02003019 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003020 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003021 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003022 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003023 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003024 " | While not properly invalid, you will certainly encounter various problems\n"
3025 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003026 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003027 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003028 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003029
Willy Tarreau1fa31262007-12-03 00:36:16 +01003030 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3031 * We must still support older configurations, so let's find out whether those
3032 * parameters have been set or must be copied from contimeouts.
3033 */
3034 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003035 if (!curproxy->timeout.tarpit ||
3036 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003037 /* tarpit timeout not set. We search in the following order:
3038 * default.tarpit, curr.connect, default.connect.
3039 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003040 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003041 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003042 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003043 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003044 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003045 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003046 }
3047 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003048 (!curproxy->timeout.queue ||
3049 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003050 /* queue timeout not set. We search in the following order:
3051 * default.queue, curr.connect, default.connect.
3052 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003053 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003054 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003055 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003056 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003057 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003058 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003059 }
3060 }
3061
Willy Tarreauf3c69202006-07-09 16:42:34 +02003062 if (curproxy->options & PR_O_SSL3_CHK) {
3063 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3064 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3065 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3066 }
3067
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003068 /* The small pools required for the capture lists */
3069 if (curproxy->nb_req_cap)
3070 curproxy->req_cap_pool = create_pool("ptrcap",
3071 curproxy->nb_req_cap * sizeof(char *),
3072 MEM_F_SHARED);
3073 if (curproxy->nb_rsp_cap)
3074 curproxy->rsp_cap_pool = create_pool("ptrcap",
3075 curproxy->nb_rsp_cap * sizeof(char *),
3076 MEM_F_SHARED);
3077
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003078 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3079 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3080 MEM_F_SHARED);
3081
Willy Tarreau86034312006-12-29 00:10:33 +01003082 /* for backwards compatibility with "listen" instances, if
3083 * fullconn is not set but maxconn is set, then maxconn
3084 * is used.
3085 */
3086 if (!curproxy->fullconn)
3087 curproxy->fullconn = curproxy->maxconn;
3088
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089 /* first, we will invert the servers list order */
3090 newsrv = NULL;
3091 while (curproxy->srv) {
3092 struct server *next;
3093
3094 next = curproxy->srv->next;
3095 curproxy->srv->next = newsrv;
3096 newsrv = curproxy->srv;
3097 if (!next)
3098 break;
3099 curproxy->srv = next;
3100 }
3101
Willy Tarreau20697042007-11-15 23:26:18 +01003102 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003103 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104
Willy Tarreaub625a082007-11-26 01:15:43 +01003105 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003106 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003107 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003108 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3109 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003110 else
3111 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112
3113 if (curproxy->options & PR_O_LOGASAP)
3114 curproxy->to_log &= ~LW_BYTES;
3115
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003117 * ensure that we're not cross-dressing a TCP server into HTTP.
3118 */
3119 newsrv = curproxy->srv;
3120 while (newsrv != NULL) {
3121 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3122 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3123 file, proxy_type_str(curproxy), curproxy->id, linenum);
3124 goto err;
3125 }
3126 newsrv = newsrv->next;
3127 }
3128
3129 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 * If this server supports a maxconn parameter, it needs a dedicated
3131 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003132 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 */
3134 newsrv = curproxy->srv;
3135 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003136 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003137 /* Only 'minconn' was specified, or it was higher than or equal
3138 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3139 * this will avoid further useless expensive computations.
3140 */
3141 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003142 } else if (newsrv->maxconn && !newsrv->minconn) {
3143 /* minconn was not specified, so we set it to maxconn */
3144 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003145 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3146 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003147 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003148 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003149 }
3150
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003151 if (newsrv->trackit) {
3152 struct proxy *px;
3153 struct server *srv;
3154 char *pname, *sname;
3155
3156 pname = newsrv->trackit;
3157 sname = strrchr(pname, '/');
3158
3159 if (sname)
3160 *sname++ = '\0';
3161 else {
3162 sname = pname;
3163 pname = NULL;
3164 }
3165
3166 if (pname) {
3167 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3168 if (!px) {
3169 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3170 file, proxy_type_str(curproxy), curproxy->id,
3171 newsrv->id, pname);
3172 return -1;
3173 }
3174 } else
3175 px = curproxy;
3176
3177 srv = findserver(px, sname);
3178 if (!srv) {
3179 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3180 file, proxy_type_str(curproxy), curproxy->id,
3181 newsrv->id, sname);
3182 return -1;
3183 }
3184
3185 if (!(srv->state & SRV_CHECKED)) {
3186 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3187 "tracing as it does not have checks enabled.\n",
3188 file, proxy_type_str(curproxy), curproxy->id,
3189 newsrv->id, px->id, srv->id);
3190 return -1;
3191 }
3192
3193 if (curproxy != px &&
3194 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3195 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3196 "tracing: disable-on-404 option inconsistency.\n",
3197 file, proxy_type_str(curproxy), curproxy->id,
3198 newsrv->id, px->id, srv->id);
3199 return -1;
3200 }
3201
3202 newsrv->tracked = srv;
3203 newsrv->tracknext = srv->tracknext;
3204 srv->tracknext = newsrv;
3205
3206 free(newsrv->trackit);
3207 }
3208
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 newsrv = newsrv->next;
3210 }
3211
Willy Tarreaue6b98942007-10-29 01:09:36 +01003212 /* adjust this proxy's listeners */
3213 listener = curproxy->listen;
3214 while (listener) {
3215 if (curproxy->options & PR_O_TCP_NOLING)
3216 listener->options |= LI_O_NOLINGER;
3217 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003218 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003219 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003220 listener->accept = event_accept;
3221 listener->private = curproxy;
3222
3223 listener = listener->next;
3224 }
3225
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226 curproxy = curproxy->next;
3227 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003228
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 if (cfgerr > 0) {
3230 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003231 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003233
3234 /*
3235 * Recount currently required checks.
3236 */
3237
3238 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3239 int optnum;
3240
3241 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3242 if (!(curproxy->options & cfg_opts[optnum].val))
3243 continue;
3244
3245 global.last_checks |= cfg_opts[optnum].checks;
3246 }
3247 }
3248
Willy Tarreau6daf3432008-01-22 16:44:08 +01003249 if (cursection)
3250 free(cursection);
3251 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003252 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003253
3254 err:
3255 if (cursection)
3256 free(cursection);
3257 cursection = NULL;
3258 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259}
3260
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003261/*
3262 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3263 * parsing sessions.
3264 */
3265void cfg_register_keywords(struct cfg_kw_list *kwl)
3266{
3267 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3268}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003270/*
3271 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3272 */
3273void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3274{
3275 LIST_DEL(&kwl->list);
3276 LIST_INIT(&kwl->list);
3277}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278
3279/*
3280 * Local variables:
3281 * c-indent-level: 8
3282 * c-basic-offset: 8
3283 * End:
3284 */