blob: ea73f537559ee54ac021c7d976b27f909d42f44d [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau7c669d72008-06-20 15:04:11 +02004 * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
27#include <common/config.h>
28#include <common/memory.h>
29#include <common/standard.h>
30#include <common/time.h>
31#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020032
33#include <types/capture.h>
34#include <types/global.h>
35#include <types/polling.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036
Willy Tarreaueb0c6142007-05-07 00:53:22 +020037#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010039#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020041#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010044#include <proto/protocols.h>
45#include <proto/proto_tcp.h>
46#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010047#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <proto/server.h>
49#include <proto/task.h>
50
51
Willy Tarreauf3c69202006-07-09 16:42:34 +020052/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
53 * ssl-hello-chk option to ensure that the remote server speaks SSL.
54 *
55 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
56 */
57const char sslv3_client_hello_pkt[] = {
58 "\x16" /* ContentType : 0x16 = Hanshake */
59 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
60 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
61 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
62 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
63 "\x03\x00" /* Hello Version : 0x0300 = v3 */
64 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
65 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
66 "\x00" /* Session ID length : empty (no session ID) */
67 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
68 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
69 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
70 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
71 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
72 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
73 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
74 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
75 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
76 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
77 "\x00\x38" "\x00\x39" "\x00\x3A"
78 "\x01" /* Compression Length : 0x01 = 1 byte for types */
79 "\x00" /* Compression Type : 0x00 = NULL compression */
80};
81
Willy Tarreau13943ab2006-12-31 00:24:10 +010082/* some of the most common options which are also the easiest to handle */
83static const struct {
84 const char *name;
85 unsigned int val;
86 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010087 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010088} cfg_opts[] =
89{
Willy Tarreau4fee4e92007-01-06 21:09:17 +010090 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010091 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010092 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010094 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
95 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
96 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
97 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
98 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
99 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
100 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
101 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100102 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100103 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
104 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100105#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100106 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
107#endif
108#ifdef TPROXY
109 { "transparent", PR_O_TRANSP, PR_CAP_FE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100110#endif
111
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100112 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113};
114
Willy Tarreaubaaee002006-06-26 02:48:02 +0200115
Willy Tarreau6daf3432008-01-22 16:44:08 +0100116static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200117static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
118int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
119int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
120
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200121/* List head of all known configuration keywords */
122static struct cfg_kw_list cfg_keywords = {
123 .list = LIST_HEAD_INIT(cfg_keywords.list)
124};
125
Willy Tarreaubaaee002006-06-26 02:48:02 +0200126/*
127 * converts <str> to a list of listeners which are dynamically allocated.
128 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
129 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
130 * - <port> is a numerical port from 1 to 65535 ;
131 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
132 * This can be repeated as many times as necessary, separated by a coma.
133 * The <tail> argument is a pointer to a current list which should be appended
134 * to the tail of the new list. The pointer to the new list is returned.
135 */
136static struct listener *str2listener(char *str, struct listener *tail)
137{
138 struct listener *l;
139 char *c, *next, *range, *dupstr;
140 int port, end;
141
142 next = dupstr = strdup(str);
143
144 while (next && *next) {
145 struct sockaddr_storage ss;
146
147 str = next;
148 /* 1) look for the end of the first address */
149 if ((next = strrchr(str, ',')) != NULL) {
150 *next++ = 0;
151 }
152
153 /* 2) look for the addr/port delimiter, it's the last colon. */
154 if ((range = strrchr(str, ':')) == NULL) {
155 Alert("Missing port number: '%s'\n", str);
156 goto fail;
157 }
158
159 *range++ = 0;
160
161 if (strrchr(str, ':') != NULL) {
162 /* IPv6 address contains ':' */
163 memset(&ss, 0, sizeof(ss));
164 ss.ss_family = AF_INET6;
165
166 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
167 Alert("Invalid server address: '%s'\n", str);
168 goto fail;
169 }
170 }
171 else {
172 memset(&ss, 0, sizeof(ss));
173 ss.ss_family = AF_INET;
174
175 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
176 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
177 }
178 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
179 struct hostent *he;
180
181 if ((he = gethostbyname(str)) == NULL) {
182 Alert("Invalid server name: '%s'\n", str);
183 goto fail;
184 }
185 else
186 ((struct sockaddr_in *)&ss)->sin_addr =
187 *(struct in_addr *) *(he->h_addr_list);
188 }
189 }
190
191 /* 3) look for the port-end delimiter */
192 if ((c = strchr(range, '-')) != NULL) {
193 *c++ = 0;
194 end = atol(c);
195 }
196 else {
197 end = atol(range);
198 }
199
200 port = atol(range);
201
202 if (port < 1 || port > 65535) {
203 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
204 goto fail;
205 }
206
207 if (end < 1 || end > 65535) {
208 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
209 goto fail;
210 }
211
212 for (; port <= end; port++) {
213 l = (struct listener *)calloc(1, sizeof(struct listener));
214 l->next = tail;
215 tail = l;
216
217 l->fd = -1;
218 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100219 l->state = LI_INIT;
220
221 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100223 tcpv6_add_listener(l);
224 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100226 tcpv4_add_listener(l);
227 }
228 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229 } /* end for(port) */
230 } /* end while(next) */
231 free(dupstr);
232 return tail;
233 fail:
234 free(dupstr);
235 return NULL;
236}
237
Willy Tarreau977b8e42006-12-29 14:19:17 +0100238/*
239 * Sends a warning if proxy <proxy> does not have at least one of the
240 * capabilities in <cap>. An optionnal <hint> may be added at the end
241 * of the warning to help the user. Returns 1 if a warning was emitted
242 * or 0 if the condition is valid.
243 */
244int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
245{
246 char *msg;
247
248 switch (cap) {
249 case PR_CAP_BE: msg = "no backend"; break;
250 case PR_CAP_FE: msg = "no frontend"; break;
251 case PR_CAP_RS: msg = "no ruleset"; break;
252 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
253 default: msg = "not enough"; break;
254 }
255
256 if (!(proxy->cap & cap)) {
257 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100258 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100259 return 1;
260 }
261 return 0;
262}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
264/*
265 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
266 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100267int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268{
269
270 if (!strcmp(args[0], "global")) { /* new section */
271 /* no option, nothing special to do */
272 return 0;
273 }
274 else if (!strcmp(args[0], "daemon")) {
275 global.mode |= MODE_DAEMON;
276 }
277 else if (!strcmp(args[0], "debug")) {
278 global.mode |= MODE_DEBUG;
279 }
280 else if (!strcmp(args[0], "noepoll")) {
281 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
282 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200283 else if (!strcmp(args[0], "nosepoll")) {
284 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
285 }
286 else if (!strcmp(args[0], "nokqueue")) {
287 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 else if (!strcmp(args[0], "nopoll")) {
290 cfg_polling_mechanism &= ~POLL_USE_POLL;
291 }
292 else if (!strcmp(args[0], "quiet")) {
293 global.mode |= MODE_QUIET;
294 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200295 else if (!strcmp(args[0], "tune.maxpollevents")) {
296 if (global.tune.maxpollevents != 0) {
297 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
298 return 0;
299 }
300 if (*(args[1]) == 0) {
301 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
302 return -1;
303 }
304 global.tune.maxpollevents = atol(args[1]);
305 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100306 else if (!strcmp(args[0], "tune.maxaccept")) {
307 if (global.tune.maxaccept != 0) {
308 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
309 return 0;
310 }
311 if (*(args[1]) == 0) {
312 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
313 return -1;
314 }
315 global.tune.maxaccept = atol(args[1]);
316 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317 else if (!strcmp(args[0], "uid")) {
318 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200319 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200320 return 0;
321 }
322 if (*(args[1]) == 0) {
323 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
324 return -1;
325 }
326 global.uid = atol(args[1]);
327 }
328 else if (!strcmp(args[0], "gid")) {
329 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200330 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200331 return 0;
332 }
333 if (*(args[1]) == 0) {
334 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
335 return -1;
336 }
337 global.gid = atol(args[1]);
338 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200339 /* user/group name handling */
340 else if (!strcmp(args[0], "user")) {
341 struct passwd *ha_user;
342 if (global.uid != 0) {
343 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
344 return 0;
345 }
346 errno = 0;
347 ha_user = getpwnam(args[1]);
348 if (ha_user != NULL) {
349 global.uid = (int)ha_user->pw_uid;
350 }
351 else {
352 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
353 exit(1);
354 }
355 }
356 else if (!strcmp(args[0], "group")) {
357 struct group *ha_group;
358 if (global.gid != 0) {
359 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
360 return 0;
361 }
362 errno = 0;
363 ha_group = getgrnam(args[1]);
364 if (ha_group != NULL) {
365 global.gid = (int)ha_group->gr_gid;
366 }
367 else {
368 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
369 exit(1);
370 }
371 }
372 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200373 else if (!strcmp(args[0], "nbproc")) {
374 if (global.nbproc != 0) {
375 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
376 return 0;
377 }
378 if (*(args[1]) == 0) {
379 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
380 return -1;
381 }
382 global.nbproc = atol(args[1]);
383 }
384 else if (!strcmp(args[0], "maxconn")) {
385 if (global.maxconn != 0) {
386 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
387 return 0;
388 }
389 if (*(args[1]) == 0) {
390 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
391 return -1;
392 }
393 global.maxconn = atol(args[1]);
394#ifdef SYSTEM_MAXCONN
395 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
396 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
397 global.maxconn = DEFAULT_MAXCONN;
398 }
399#endif /* SYSTEM_MAXCONN */
400 }
401 else if (!strcmp(args[0], "ulimit-n")) {
402 if (global.rlimit_nofile != 0) {
403 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
404 return 0;
405 }
406 if (*(args[1]) == 0) {
407 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
408 return -1;
409 }
410 global.rlimit_nofile = atol(args[1]);
411 }
412 else if (!strcmp(args[0], "chroot")) {
413 if (global.chroot != NULL) {
414 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
415 return 0;
416 }
417 if (*(args[1]) == 0) {
418 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
419 return -1;
420 }
421 global.chroot = strdup(args[1]);
422 }
423 else if (!strcmp(args[0], "pidfile")) {
424 if (global.pidfile != NULL) {
425 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
426 return 0;
427 }
428 if (*(args[1]) == 0) {
429 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
430 return -1;
431 }
432 global.pidfile = strdup(args[1]);
433 }
434 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100435 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200436 int facility, level;
437
438 if (*(args[1]) == 0 || *(args[2]) == 0) {
439 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
440 return -1;
441 }
442
443 facility = get_log_facility(args[2]);
444 if (facility < 0) {
445 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
446 exit(1);
447 }
448
449 level = 7; /* max syslog level = debug */
450 if (*(args[3])) {
451 level = get_log_level(args[3]);
452 if (level < 0) {
453 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
454 exit(1);
455 }
456 }
457
Robert Tsai81ae1952007-12-05 10:47:29 +0100458 if (args[1][0] == '/') {
459 logsrv.u.addr.sa_family = AF_UNIX;
460 logsrv.u.un = *str2sun(args[1]);
461 } else {
462 logsrv.u.addr.sa_family = AF_INET;
463 logsrv.u.in = *str2sa(args[1]);
464 if (!logsrv.u.in.sin_port)
465 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
466 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467
468 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100469 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 global.logfac1 = facility;
471 global.loglev1 = level;
472 }
473 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100474 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 global.logfac2 = facility;
476 global.loglev2 = level;
477 }
478 else {
479 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
480 return -1;
481 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200482 }
483 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
484 if (global.spread_checks != 0) {
485 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
486 return 0;
487 }
488 if (*(args[1]) == 0) {
489 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
490 return -1;
491 }
492 global.spread_checks = atol(args[1]);
493 if (global.spread_checks < 0 || global.spread_checks > 50) {
494 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
495 return -1;
496 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200497 }
498 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200499 struct cfg_kw_list *kwl;
500 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200501 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200502
503 list_for_each_entry(kwl, &cfg_keywords.list, list) {
504 for (index = 0; kwl->kw[index].kw != NULL; index++) {
505 if (kwl->kw[index].section != CFG_GLOBAL)
506 continue;
507 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
508 /* prepare error message just in case */
509 snprintf(trash, sizeof(trash),
510 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200511 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
512 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200513 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
514 return -1;
515 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200516 else if (rc > 0) {
517 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
518 return 0;
519 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200520 return 0;
521 }
522 }
523 }
524
Willy Tarreaubaaee002006-06-26 02:48:02 +0200525 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
526 return -1;
527 }
528 return 0;
529}
530
531
532static void init_default_instance()
533{
534 memset(&defproxy, 0, sizeof(defproxy));
535 defproxy.mode = PR_MODE_TCP;
536 defproxy.state = PR_STNEW;
537 defproxy.maxconn = cfg_maxpconn;
538 defproxy.conn_retries = CONN_RETRIES;
539 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100540 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541}
542
543/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100544 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
545 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100547int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548{
549 static struct proxy *curproxy = NULL;
550 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200551 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100552 int rc;
553 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200554
Willy Tarreau977b8e42006-12-29 14:19:17 +0100555 if (!strcmp(args[0], "listen"))
556 rc = PR_CAP_LISTEN;
557 else if (!strcmp(args[0], "frontend"))
558 rc = PR_CAP_FE | PR_CAP_RS;
559 else if (!strcmp(args[0], "backend"))
560 rc = PR_CAP_BE | PR_CAP_RS;
561 else if (!strcmp(args[0], "ruleset"))
562 rc = PR_CAP_RS;
563 else
564 rc = PR_CAP_NONE;
565
566 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 if (!*args[1]) {
568 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
569 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
570 file, linenum, args[0]);
571 return -1;
572 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200573
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100574 err = invalid_char(args[1]);
575 if (err) {
576 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
577 file, linenum, *err, args[0], args[1]);
578 return -1;
579 }
580
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200581 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
582 /*
583 * If there are two proxies with the same name only following
584 * combinations are allowed:
585 *
586 * listen backend frontend ruleset
587 * listen - - - -
588 * backend - - OK -
589 * frontend - OK - -
590 * ruleset - - - -
591 */
592
593 if (!strcmp(curproxy->id, args[1]) &&
594 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
595 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100596 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
597 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200598 }
599 }
600
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
602 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
603 return -1;
604 }
605
606 curproxy->next = proxy;
607 proxy = curproxy;
608 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200609 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200610 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200611 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100612 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200613 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200614 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615
Willy Tarreauee991362007-05-14 14:37:50 +0200616 /* Timeouts are defined as -1, so we cannot use the zeroed area
617 * as a default value.
618 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100619 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200620
621 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100623 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200624
625 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100626 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200627 curproxy->listen = str2listener(args[2], curproxy->listen);
628 if (!curproxy->listen)
629 return -1;
630 global.maxsock++;
631 }
632
633 /* set default values */
634 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100636 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200637 curproxy->except_net = defproxy.except_net;
638 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639
Willy Tarreau977b8e42006-12-29 14:19:17 +0100640 if (curproxy->cap & PR_CAP_FE) {
641 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100642 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100643
644 /* initialize error relocations */
645 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
646 if (defproxy.errmsg[rc].str)
647 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
648 }
649
650 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652
Willy Tarreau977b8e42006-12-29 14:19:17 +0100653 if (curproxy->cap & PR_CAP_BE) {
654 curproxy->fullconn = defproxy.fullconn;
655 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656
Willy Tarreau977b8e42006-12-29 14:19:17 +0100657 if (defproxy.check_req)
658 curproxy->check_req = strdup(defproxy.check_req);
659 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200660
Willy Tarreau977b8e42006-12-29 14:19:17 +0100661 if (defproxy.cookie_name)
662 curproxy->cookie_name = strdup(defproxy.cookie_name);
663 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100664
665 if (defproxy.url_param_name)
666 curproxy->url_param_name = strdup(defproxy.url_param_name);
667 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669
Willy Tarreau977b8e42006-12-29 14:19:17 +0100670 if (curproxy->cap & PR_CAP_RS) {
671 if (defproxy.capture_name)
672 curproxy->capture_name = strdup(defproxy.capture_name);
673 curproxy->capture_namelen = defproxy.capture_namelen;
674 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676
Willy Tarreau977b8e42006-12-29 14:19:17 +0100677 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100678 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100679 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100680 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100681 curproxy->uri_auth = defproxy.uri_auth;
682 curproxy->mon_net = defproxy.mon_net;
683 curproxy->mon_mask = defproxy.mon_mask;
684 if (defproxy.monitor_uri)
685 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
686 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100687 if (defproxy.defbe.name)
688 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100689 }
690
691 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100692 curproxy->timeout.connect = defproxy.timeout.connect;
693 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100694 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100695 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100696 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100697 curproxy->source_addr = defproxy.source_addr;
698 }
699
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700 curproxy->mode = defproxy.mode;
701 curproxy->logfac1 = defproxy.logfac1;
702 curproxy->logsrv1 = defproxy.logsrv1;
703 curproxy->loglev1 = defproxy.loglev1;
704 curproxy->logfac2 = defproxy.logfac2;
705 curproxy->logsrv2 = defproxy.logsrv2;
706 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200707 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100708 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
709 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200710
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 return 0;
712 }
713 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
714 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100715 /* FIXME-20070101: we should do this too at the end of the
716 * config parsing to free all default values.
717 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200718 if (defproxy.check_req) free(defproxy.check_req);
719 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100720 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200722 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100723 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100724
725 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
726 if (defproxy.errmsg[rc].len)
727 free(defproxy.errmsg[rc].str);
728 }
729
Willy Tarreaubaaee002006-06-26 02:48:02 +0200730 /* we cannot free uri_auth because it might already be used */
731 init_default_instance();
732 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100733 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200734 return 0;
735 }
736 else if (curproxy == NULL) {
737 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
738 return -1;
739 }
740
Willy Tarreau977b8e42006-12-29 14:19:17 +0100741
742 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200743 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100744 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200745 if (curproxy == &defproxy) {
746 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
747 return -1;
748 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100749 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
750 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751
752 if (strchr(args[1], ':') == NULL) {
753 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
754 file, linenum, args[0]);
755 return -1;
756 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100757
758 last_listen = curproxy->listen;
759 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200760 if (!curproxy->listen)
761 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100762 if (*args[2]) {
763#ifdef CONFIG_HAP_LINUX_TPROXY
764 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
765 struct listener *l;
766
767 for (l = curproxy->listen; l != last_listen; l = l->next)
768 l->options |= LI_O_FOREIGN;
769 }
770 else {
771 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
772 file, linenum, args[0]);
773 return -1;
774 }
775#else
776 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
777 file, linenum, args[0]);
778 return -1;
779#endif
780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 global.maxsock++;
782 return 0;
783 }
784 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
785 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
786 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
787 file, linenum, args[0]);
788 return -1;
789 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100790 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
791 return 0;
792
Willy Tarreaubaaee002006-06-26 02:48:02 +0200793 /* flush useless bits */
794 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
795 return 0;
796 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200797 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100798 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
799 return 0;
800
Willy Tarreau1c47f852006-07-09 08:22:27 +0200801 if (!*args[1]) {
802 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
803 file, linenum, args[0]);
804 return -1;
805 }
806
807 if (curproxy->monitor_uri != NULL)
808 free(curproxy->monitor_uri);
809
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100810 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200811 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100812 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200813 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
814
815 return 0;
816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200817 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
818 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
819 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
820 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
821 else {
822 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
823 return -1;
824 }
825 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100826 else if (!strcmp(args[0], "id")) {
827 struct proxy *target;
828
829 if (curproxy == &defproxy) {
830 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
831 file, linenum, args[0]);
832 return -1;
833 }
834
835 if (!*args[1]) {
836 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
837 file, linenum, args[0]);
838 return -1;
839 }
840
841 curproxy->uuid = atol(args[1]);
842
843 if (curproxy->uuid < 1001) {
844 Alert("parsing [%s:%d]: custom id has to be > 1000",
845 file, linenum);
846 return -1;
847 }
848
849 for (target = proxy; target; target = target->next)
850 if (curproxy != target && curproxy->uuid == target->uuid) {
851 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
852 file, linenum, curproxy->id, target->id);
853 return -1;
854 }
855 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200856 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
857 curproxy->state = PR_STSTOPPED;
858 }
859 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
860 curproxy->state = PR_STNEW;
861 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200862 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100863 err = invalid_char(args[1]);
864 if (err) {
865 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
866 file, linenum, *err, args[1]);
867 return -1;
868 }
869
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200870 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
871 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
872 file, linenum, args[1]);
873 return -1;
874 }
875 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200876 else if (!strcmp(args[0], "cookie")) { /* cookie name */
877 int cur_arg;
878 // if (curproxy == &defproxy) {
879 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
880 // return -1;
881 // }
882
Willy Tarreau977b8e42006-12-29 14:19:17 +0100883 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
884 return 0;
885
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886 if (curproxy->cookie_name != NULL) {
887 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
888 // file, linenum);
889 // return 0;
890 free(curproxy->cookie_name);
891 }
892
893 if (*(args[1]) == 0) {
894 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
895 file, linenum, args[0]);
896 return -1;
897 }
898 curproxy->cookie_name = strdup(args[1]);
899 curproxy->cookie_len = strlen(curproxy->cookie_name);
900
901 cur_arg = 2;
902 while (*(args[cur_arg])) {
903 if (!strcmp(args[cur_arg], "rewrite")) {
904 curproxy->options |= PR_O_COOK_RW;
905 }
906 else if (!strcmp(args[cur_arg], "indirect")) {
907 curproxy->options |= PR_O_COOK_IND;
908 }
909 else if (!strcmp(args[cur_arg], "insert")) {
910 curproxy->options |= PR_O_COOK_INS;
911 }
912 else if (!strcmp(args[cur_arg], "nocache")) {
913 curproxy->options |= PR_O_COOK_NOC;
914 }
915 else if (!strcmp(args[cur_arg], "postonly")) {
916 curproxy->options |= PR_O_COOK_POST;
917 }
918 else if (!strcmp(args[cur_arg], "prefix")) {
919 curproxy->options |= PR_O_COOK_PFX;
920 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200921 else if (!strcmp(args[cur_arg], "domain")) {
922 if (!*args[cur_arg + 1]) {
923 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
924 file, linenum, args[cur_arg]);
925 return -1;
926 }
927
928 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
929 /* rfc2109, 4.3.2 Rejecting Cookies */
930 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
931 " dots or does not start with a dot.\n",
932 file, linenum, args[cur_arg + 1]);
933 return -1;
934 }
935
936 err = invalid_domainchar(args[cur_arg + 1]);
937 if (err) {
938 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
939 file, linenum, *err, args[cur_arg + 1]);
940 return -1;
941 }
942
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +0200943 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200944 cur_arg++;
945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200947 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 file, linenum, args[0]);
949 return -1;
950 }
951 cur_arg++;
952 }
953 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
954 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
955 file, linenum);
956 return -1;
957 }
958
959 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
960 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
961 file, linenum);
962 return -1;
963 }
964 }/* end else if (!strcmp(args[0], "cookie")) */
965 else if (!strcmp(args[0], "appsession")) { /* cookie name */
966 // if (curproxy == &defproxy) {
967 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
968 // return -1;
969 // }
970
Willy Tarreau977b8e42006-12-29 14:19:17 +0100971 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
972 return 0;
973
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974 if (curproxy->appsession_name != NULL) {
975 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
976 // file, linenum);
977 // return 0;
978 free(curproxy->appsession_name);
979 }
980
981 if (*(args[5]) == 0) {
982 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
983 file, linenum, args[0]);
984 return -1;
985 }
986 have_appsession = 1;
987 curproxy->appsession_name = strdup(args[1]);
988 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
989 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100990 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
991 if (err) {
992 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
993 file, linenum, *err, args[0]);
994 return -1;
995 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200996 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +0200997
Willy Tarreau51041c72007-09-09 21:56:53 +0200998 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
999 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001000 return -1;
1001 }
1002 } /* Url App Session */
1003 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001004 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1005 return 0;
1006
Willy Tarreaubaaee002006-06-26 02:48:02 +02001007 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
1008 // if (curproxy == &defproxy) {
1009 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1010 // return -1;
1011 // }
1012
1013 if (curproxy->capture_name != NULL) {
1014 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
1015 // file, linenum, args[0]);
1016 // return 0;
1017 free(curproxy->capture_name);
1018 }
1019
1020 if (*(args[4]) == 0) {
1021 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1022 file, linenum, args[0]);
1023 return -1;
1024 }
1025 curproxy->capture_name = strdup(args[2]);
1026 curproxy->capture_namelen = strlen(curproxy->capture_name);
1027 curproxy->capture_len = atol(args[4]);
1028 if (curproxy->capture_len >= CAPTURE_LEN) {
1029 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1030 file, linenum, CAPTURE_LEN - 1);
1031 curproxy->capture_len = CAPTURE_LEN - 1;
1032 }
1033 curproxy->to_log |= LW_COOKIE;
1034 }
1035 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1036 struct cap_hdr *hdr;
1037
1038 if (curproxy == &defproxy) {
1039 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1040 return -1;
1041 }
1042
1043 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1044 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1045 file, linenum, args[0], args[1]);
1046 return -1;
1047 }
1048
1049 hdr = calloc(sizeof(struct cap_hdr), 1);
1050 hdr->next = curproxy->req_cap;
1051 hdr->name = strdup(args[3]);
1052 hdr->namelen = strlen(args[3]);
1053 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001054 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 hdr->index = curproxy->nb_req_cap++;
1056 curproxy->req_cap = hdr;
1057 curproxy->to_log |= LW_REQHDR;
1058 }
1059 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1060 struct cap_hdr *hdr;
1061
1062 if (curproxy == &defproxy) {
1063 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1064 return -1;
1065 }
1066
1067 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1068 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1069 file, linenum, args[0], args[1]);
1070 return -1;
1071 }
1072 hdr = calloc(sizeof(struct cap_hdr), 1);
1073 hdr->next = curproxy->rsp_cap;
1074 hdr->name = strdup(args[3]);
1075 hdr->namelen = strlen(args[3]);
1076 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001077 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078 hdr->index = curproxy->nb_rsp_cap++;
1079 curproxy->rsp_cap = hdr;
1080 curproxy->to_log |= LW_RSPHDR;
1081 }
1082 else {
1083 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1084 file, linenum, args[0]);
1085 return -1;
1086 }
1087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001089 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1090 return 0;
1091
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 if (*(args[1]) == 0) {
1093 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1094 file, linenum, args[0]);
1095 return -1;
1096 }
1097 curproxy->conn_retries = atol(args[1]);
1098 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001099 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1100 int pol = ACL_COND_NONE;
1101 struct acl_cond *cond;
1102
1103 if (!strcmp(args[1], "if"))
1104 pol = ACL_COND_IF;
1105 else if (!strcmp(args[1], "unless"))
1106 pol = ACL_COND_UNLESS;
1107
1108 if (pol == ACL_COND_NONE) {
1109 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1110 file, linenum, args[0]);
1111 return -1;
1112 }
1113
1114 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1115 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1116 file, linenum);
1117 return -1;
1118 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001119 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001120 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1121 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001122 else if (!strcmp(args[0], "redirect")) {
1123 int pol = ACL_COND_NONE;
1124 struct acl_cond *cond;
1125 struct redirect_rule *rule;
1126 int cur_arg;
1127 int type = REDIRECT_TYPE_NONE;
1128 int code = 302;
1129 char *destination = NULL;
1130
1131 cur_arg = 1;
1132 while (*(args[cur_arg])) {
1133 if (!strcmp(args[cur_arg], "location")) {
1134 if (!*args[cur_arg + 1]) {
1135 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1136 file, linenum, args[0], args[cur_arg]);
1137 return -1;
1138 }
1139
1140 type = REDIRECT_TYPE_LOCATION;
1141 cur_arg++;
1142 destination = args[cur_arg];
1143 }
1144 else if (!strcmp(args[cur_arg], "prefix")) {
1145 if (!*args[cur_arg + 1]) {
1146 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1147 file, linenum, args[0], args[cur_arg]);
1148 return -1;
1149 }
1150
1151 type = REDIRECT_TYPE_PREFIX;
1152 cur_arg++;
1153 destination = args[cur_arg];
1154 }
1155 else if (!strcmp(args[cur_arg],"code")) {
1156 if (!*args[cur_arg + 1]) {
1157 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1158 file, linenum, args[0]);
1159 return -1;
1160 }
1161 cur_arg++;
1162 code = atol(args[cur_arg]);
1163 if (code < 301 || code > 303) {
1164 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1165 file, linenum, args[0], code);
1166 return -1;
1167 }
1168 }
1169 else if (!strcmp(args[cur_arg], "if")) {
1170 pol = ACL_COND_IF;
1171 cur_arg++;
1172 break;
1173 }
1174 else if (!strcmp(args[cur_arg], "unless")) {
1175 pol = ACL_COND_UNLESS;
1176 cur_arg++;
1177 break;
1178 }
1179 else {
1180 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1181 file, linenum, args[0], args[cur_arg]);
1182 return -1;
1183 }
1184 cur_arg++;
1185 }
1186
1187 if (type == REDIRECT_TYPE_NONE) {
1188 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1189 file, linenum, args[0]);
1190 return -1;
1191 }
1192
1193 if (pol == ACL_COND_NONE) {
1194 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1195 file, linenum, args[0]);
1196 return -1;
1197 }
1198
1199 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1200 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1201 file, linenum, args[0]);
1202 return -1;
1203 }
1204
Willy Tarreaua9802632008-07-25 19:13:19 +02001205 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001206 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1207 rule->cond = cond;
1208 rule->rdr_str = strdup(destination);
1209 rule->rdr_len = strlen(destination);
1210 rule->type = type;
1211 rule->code = code;
1212 LIST_INIT(&rule->list);
1213 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1214 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001215 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1216 int pol = ACL_COND_NONE;
1217 struct acl_cond *cond;
1218 struct switching_rule *rule;
1219
1220 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1221 return 0;
1222
1223 if (*(args[1]) == 0) {
1224 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1225 return -1;
1226 }
1227
1228 if (!strcmp(args[2], "if"))
1229 pol = ACL_COND_IF;
1230 else if (!strcmp(args[2], "unless"))
1231 pol = ACL_COND_UNLESS;
1232
1233 if (pol == ACL_COND_NONE) {
1234 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1235 file, linenum, args[0]);
1236 return -1;
1237 }
1238
1239 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001240 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001241 file, linenum);
1242 return -1;
1243 }
1244
Willy Tarreaua9802632008-07-25 19:13:19 +02001245 cond->line = linenum;
1246 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001247 struct acl *acl;
1248 const char *name;
1249
1250 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1251 name = acl ? acl->name : "(unknown)";
1252 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1253 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001254 }
1255
Willy Tarreau55ea7572007-06-17 19:56:27 +02001256 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1257 rule->cond = cond;
1258 rule->be.name = strdup(args[1]);
1259 LIST_INIT(&rule->list);
1260 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001262 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001263 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1264 return 0;
1265
Willy Tarreaubaaee002006-06-26 02:48:02 +02001266 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1267 curproxy->uri_auth = NULL; /* we must detach from the default config */
1268
1269 if (*(args[1]) == 0) {
1270 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1271 return -1;
1272 } else if (!strcmp(args[1], "uri")) {
1273 if (*(args[2]) == 0) {
1274 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1275 return -1;
1276 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1277 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1278 return -1;
1279 }
1280 } else if (!strcmp(args[1], "realm")) {
1281 if (*(args[2]) == 0) {
1282 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1283 return -1;
1284 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1285 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1286 return -1;
1287 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001288 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001289 unsigned interval;
1290
1291 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1292 if (err) {
1293 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1294 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001295 return -1;
1296 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1297 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1298 return -1;
1299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001300 } else if (!strcmp(args[1], "auth")) {
1301 if (*(args[2]) == 0) {
1302 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1303 return -1;
1304 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1305 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1306 return -1;
1307 }
1308 } else if (!strcmp(args[1], "scope")) {
1309 if (*(args[2]) == 0) {
1310 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1311 return -1;
1312 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1313 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1314 return -1;
1315 }
1316 } else if (!strcmp(args[1], "enable")) {
1317 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1318 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1319 return -1;
1320 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001321 } else if (!strcmp(args[1], "hide-version")) {
1322 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1323 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1324 return -1;
1325 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001327 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001328 file, linenum, args[0]);
1329 return -1;
1330 }
1331 }
1332 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001333 int optnum;
1334
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001335 if (*(args[1]) == '\0') {
1336 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1337 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338 return -1;
1339 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001340
1341 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1342 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1343 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1344 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001345
1346 if (!inv)
1347 curproxy->options |= cfg_opts[optnum].val;
1348 else
1349 curproxy->options &= ~cfg_opts[optnum].val;
1350
Willy Tarreau13943ab2006-12-31 00:24:10 +01001351 return 0;
1352 }
1353 }
1354
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001355 if (inv) {
1356 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1357 file, linenum, args[1]);
1358 return -1;
1359 }
1360
Willy Tarreau13943ab2006-12-31 00:24:10 +01001361 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 /* generate a complete HTTP log */
1363 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1364 else if (!strcmp(args[1], "tcplog"))
1365 /* generate a detailed TCP log */
1366 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 else if (!strcmp(args[1], "tcpka")) {
1368 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001369 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1370 return 0;
1371
1372 if (curproxy->cap & PR_CAP_FE)
1373 curproxy->options |= PR_O_TCP_CLI_KA;
1374 if (curproxy->cap & PR_CAP_BE)
1375 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 }
1377 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001378 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1379 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 /* use HTTP request to check servers' health */
1381 if (curproxy->check_req != NULL) {
1382 free(curproxy->check_req);
1383 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001384 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001385 curproxy->options &= ~PR_O_SMTP_CHK;
1386 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001387 if (!*args[2]) { /* no argument */
1388 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1389 curproxy->check_len = strlen(DEF_CHECK_REQ);
1390 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001391 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 curproxy->check_req = (char *)malloc(reqlen);
1393 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1394 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1395 } else { /* more arguments : METHOD URI [HTTP_VER] */
1396 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1397 if (*args[4])
1398 reqlen += strlen(args[4]);
1399 else
1400 reqlen += strlen("HTTP/1.0");
1401
1402 curproxy->check_req = (char *)malloc(reqlen);
1403 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1404 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1405 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001406 }
1407 else if (!strcmp(args[1], "ssl-hello-chk")) {
1408 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001409 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1410 return 0;
1411
Willy Tarreauf3c69202006-07-09 16:42:34 +02001412 if (curproxy->check_req != NULL) {
1413 free(curproxy->check_req);
1414 }
1415 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001416 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001417 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418 }
Willy Tarreau23677902007-05-08 23:50:35 +02001419 else if (!strcmp(args[1], "smtpchk")) {
1420 /* use SMTP request to check servers' health */
1421 if (curproxy->check_req != NULL) {
1422 free(curproxy->check_req);
1423 }
1424 curproxy->options &= ~PR_O_HTTP_CHK;
1425 curproxy->options &= ~PR_O_SSL3_CHK;
1426 curproxy->options |= PR_O_SMTP_CHK;
1427
1428 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1429 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1430 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1431 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1432 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1433 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1434 curproxy->check_req = (char *)malloc(reqlen);
1435 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1436 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1437 } else {
1438 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1439 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1440 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1441 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1442 }
1443 }
1444 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001445 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001446 int cur_arg;
1447
1448 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1449 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001450 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001451
1452 curproxy->options |= PR_O_FWDFOR;
1453
1454 free(curproxy->fwdfor_hdr_name);
1455 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1456 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1457
1458 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1459 cur_arg = 2;
1460 while (*(args[cur_arg])) {
1461 if (!strcmp(args[cur_arg], "except")) {
1462 /* suboption except - needs additional argument for it */
1463 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1464 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1465 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001466 return -1;
1467 }
1468 /* flush useless bits */
1469 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001470 cur_arg += 2;
1471 } else if (!strcmp(args[cur_arg], "header")) {
1472 /* suboption header - needs additional argument for it */
1473 if (*(args[cur_arg+1]) == 0) {
1474 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1475 file, linenum, args[0], args[1], args[cur_arg]);
1476 return -1;
1477 }
1478 free(curproxy->fwdfor_hdr_name);
1479 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1480 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1481 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001482 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001483 /* unknown suboption - catchall */
1484 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1485 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001486 return -1;
1487 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001488 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 else {
1491 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1492 return -1;
1493 }
1494 return 0;
1495 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001496 else if (!strcmp(args[0], "default_backend")) {
1497 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1498 return 0;
1499
1500 if (*(args[1]) == 0) {
1501 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1502 return -1;
1503 }
1504 if (curproxy->defbe.name)
1505 free(curproxy->defbe.name);
1506 curproxy->defbe.name = strdup(args[1]);
1507 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001508 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001509 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1510 return 0;
1511
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001512 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1513 file, linenum, args[0]);
1514
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515 /* enable reconnections to dispatch */
1516 curproxy->options |= PR_O_REDISP;
1517 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001518 else if (!strcmp(args[0], "http-check")) {
1519 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1520 return 0;
1521
1522 if (strcmp(args[1], "disable-on-404") == 0) {
1523 /* enable a graceful server shutdown on an HTTP 404 response */
1524 curproxy->options |= PR_O_DISABLE404;
1525 }
1526 else {
1527 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1528 return -1;
1529 }
1530 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001531 else if (!strcmp(args[0], "monitor")) {
1532 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1533 return 0;
1534
1535 if (strcmp(args[1], "fail") == 0) {
1536 /* add a condition to fail monitor requests */
1537 int pol = ACL_COND_NONE;
1538 struct acl_cond *cond;
1539
1540 if (!strcmp(args[2], "if"))
1541 pol = ACL_COND_IF;
1542 else if (!strcmp(args[2], "unless"))
1543 pol = ACL_COND_UNLESS;
1544
1545 if (pol == ACL_COND_NONE) {
1546 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1547 file, linenum, args[0], args[1]);
1548 return -1;
1549 }
1550
1551 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1552 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1553 file, linenum, args[0], args[1]);
1554 return -1;
1555 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001556 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001557 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1558 }
1559 else {
1560 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1561 return -1;
1562 }
1563 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564#ifdef TPROXY
1565 else if (!strcmp(args[0], "transparent")) {
1566 /* enable transparent proxy connections */
1567 curproxy->options |= PR_O_TRANSP;
1568 }
1569#endif
1570 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001571 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1572 return 0;
1573
Willy Tarreaubaaee002006-06-26 02:48:02 +02001574 if (*(args[1]) == 0) {
1575 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1576 return -1;
1577 }
1578 curproxy->maxconn = atol(args[1]);
1579 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001580 else if (!strcmp(args[0], "backlog")) { /* backlog */
1581 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1582 return 0;
1583
1584 if (*(args[1]) == 0) {
1585 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1586 return -1;
1587 }
1588 curproxy->backlog = atol(args[1]);
1589 }
Willy Tarreau86034312006-12-29 00:10:33 +01001590 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001591 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1592 return 0;
1593
Willy Tarreau86034312006-12-29 00:10:33 +01001594 if (*(args[1]) == 0) {
1595 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1596 return -1;
1597 }
1598 curproxy->fullconn = atol(args[1]);
1599 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1601 if (*(args[1]) == 0) {
1602 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1603 return -1;
1604 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001605 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1606 if (err) {
1607 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1608 file, linenum, *err);
1609 return -1;
1610 }
1611 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001612 }
1613 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1614 if (curproxy == &defproxy) {
1615 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1616 return -1;
1617 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001618 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1619 return 0;
1620
Willy Tarreaubaaee002006-06-26 02:48:02 +02001621 if (strchr(args[1], ':') == NULL) {
1622 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1623 return -1;
1624 }
1625 curproxy->dispatch_addr = *str2sa(args[1]);
1626 }
1627 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001628 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1629 return 0;
1630
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001631 memcpy(trash, "error near 'balance'", 19);
1632 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1633 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1634 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001635 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636 }
1637 else if (!strcmp(args[0], "server")) { /* server address */
1638 int cur_arg;
1639 char *rport;
1640 char *raddr;
1641 short realport;
1642 int do_check;
1643
1644 if (curproxy == &defproxy) {
1645 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1646 return -1;
1647 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001648 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1649 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001650
1651 if (!*args[2]) {
1652 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1653 file, linenum, args[0]);
1654 return -1;
1655 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001656
1657 err = invalid_char(args[1]);
1658 if (err) {
1659 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1660 file, linenum, *err, args[1]);
1661 return -1;
1662 }
1663
Willy Tarreaubaaee002006-06-26 02:48:02 +02001664 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1665 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1666 return -1;
1667 }
1668
1669 /* the servers are linked backwards first */
1670 newsrv->next = curproxy->srv;
1671 curproxy->srv = newsrv;
1672 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001673 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001674
1675 LIST_INIT(&newsrv->pendconns);
1676 do_check = 0;
1677 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001678 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001679 newsrv->id = strdup(args[1]);
1680
1681 /* several ways to check the port component :
1682 * - IP => port=+0, relative
1683 * - IP: => port=+0, relative
1684 * - IP:N => port=N, absolute
1685 * - IP:+N => port=+N, relative
1686 * - IP:-N => port=-N, relative
1687 */
1688 raddr = strdup(args[2]);
1689 rport = strchr(raddr, ':');
1690 if (rport) {
1691 *rport++ = 0;
1692 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001693 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001694 newsrv->state |= SRV_MAPPORTS;
1695 } else {
1696 realport = 0;
1697 newsrv->state |= SRV_MAPPORTS;
1698 }
1699
1700 newsrv->addr = *str2sa(raddr);
1701 newsrv->addr.sin_port = htons(realport);
1702 free(raddr);
1703
1704 newsrv->curfd = -1; /* no health-check in progress */
1705 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001706 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1707 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 newsrv->rise = DEF_RISETIME;
1709 newsrv->fall = DEF_FALLTIME;
1710 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001711 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001712 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001713 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001714
Willy Tarreaubaaee002006-06-26 02:48:02 +02001715 cur_arg = 3;
1716 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001717 if (!strcmp(args[cur_arg], "id")) {
1718 struct server *target;
1719
1720 if (!*args[cur_arg + 1]) {
1721 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1722 file, linenum, args[cur_arg]);
1723 return -1;
1724 }
1725
1726 newsrv->puid = atol(args[cur_arg + 1]);
1727
1728 if (newsrv->puid< 1001) {
1729 Alert("parsing [%s:%d]: custom id has to be > 1000",
1730 file, linenum);
1731 return -1;
1732 }
1733
1734 for (target = proxy->srv; target; target = target->next)
1735 if (newsrv != target && newsrv->puid == target->puid) {
1736 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1737 file, linenum, newsrv->id, target->id);
1738 return -1;
1739 }
1740 cur_arg += 2;
1741 }
1742 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001743 newsrv->cookie = strdup(args[cur_arg + 1]);
1744 newsrv->cklen = strlen(args[cur_arg + 1]);
1745 cur_arg += 2;
1746 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001747 else if (!strcmp(args[cur_arg], "redir")) {
1748 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1749 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1750 cur_arg += 2;
1751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752 else if (!strcmp(args[cur_arg], "rise")) {
1753 newsrv->rise = atol(args[cur_arg + 1]);
1754 newsrv->health = newsrv->rise;
1755 cur_arg += 2;
1756 }
1757 else if (!strcmp(args[cur_arg], "fall")) {
1758 newsrv->fall = atol(args[cur_arg + 1]);
1759 cur_arg += 2;
1760 }
1761 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001762 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1763 if (err) {
1764 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1765 file, linenum, *err, newsrv->id);
1766 return -1;
1767 }
1768 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001769 cur_arg += 2;
1770 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001771 else if (!strcmp(args[cur_arg], "fastinter")) {
1772 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1773 if (err) {
1774 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1775 file, linenum, *err, newsrv->id);
1776 return -1;
1777 }
1778 newsrv->fastinter = val;
1779 cur_arg += 2;
1780 }
1781 else if (!strcmp(args[cur_arg], "downinter")) {
1782 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1783 if (err) {
1784 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1785 file, linenum, *err, newsrv->id);
1786 return -1;
1787 }
1788 newsrv->downinter = val;
1789 cur_arg += 2;
1790 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001791 else if (!strcmp(args[cur_arg], "addr")) {
1792 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001793 cur_arg += 2;
1794 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001795 else if (!strcmp(args[cur_arg], "port")) {
1796 newsrv->check_port = atol(args[cur_arg + 1]);
1797 cur_arg += 2;
1798 }
1799 else if (!strcmp(args[cur_arg], "backup")) {
1800 newsrv->state |= SRV_BACKUP;
1801 cur_arg ++;
1802 }
1803 else if (!strcmp(args[cur_arg], "weight")) {
1804 int w;
1805 w = atol(args[cur_arg + 1]);
1806 if (w < 1 || w > 256) {
1807 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1808 file, linenum, newsrv->id, w);
1809 return -1;
1810 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001811 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001812 cur_arg += 2;
1813 }
1814 else if (!strcmp(args[cur_arg], "minconn")) {
1815 newsrv->minconn = atol(args[cur_arg + 1]);
1816 cur_arg += 2;
1817 }
1818 else if (!strcmp(args[cur_arg], "maxconn")) {
1819 newsrv->maxconn = atol(args[cur_arg + 1]);
1820 cur_arg += 2;
1821 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001822 else if (!strcmp(args[cur_arg], "maxqueue")) {
1823 newsrv->maxqueue = atol(args[cur_arg + 1]);
1824 cur_arg += 2;
1825 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001826 else if (!strcmp(args[cur_arg], "slowstart")) {
1827 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001828 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001829 if (err) {
1830 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1831 file, linenum, *err, newsrv->id);
1832 return -1;
1833 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001834 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001835 cur_arg += 2;
1836 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001837 else if (!strcmp(args[cur_arg], "track")) {
1838
1839 if (!*args[cur_arg + 1]) {
1840 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1841 file, linenum);
1842 return -1;
1843 }
1844
1845 newsrv->trackit = strdup(args[cur_arg + 1]);
1846
1847 cur_arg += 2;
1848 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001849 else if (!strcmp(args[cur_arg], "check")) {
1850 global.maxsock++;
1851 do_check = 1;
1852 cur_arg += 1;
1853 }
1854 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1855 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001856#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001857 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1858 file, linenum, "source", "usesrc");
1859#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001860 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1861 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001862#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001863 return -1;
1864 }
1865 newsrv->state |= SRV_BIND_SRC;
1866 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1867 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001868 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001869#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1870#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001871 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001872 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1873 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001874 return -1;
1875 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001876#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001877 if (!*args[cur_arg + 1]) {
1878 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1879 file, linenum, "usesrc");
1880 return -1;
1881 }
1882 if (!strcmp(args[cur_arg + 1], "client")) {
1883 newsrv->state |= SRV_TPROXY_CLI;
1884 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1885 newsrv->state |= SRV_TPROXY_CIP;
1886 } else {
1887 newsrv->state |= SRV_TPROXY_ADDR;
1888 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1889 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001890 global.last_checks |= LSTCHK_NETADM;
1891#if !defined(CONFIG_HAP_LINUX_TPROXY)
1892 global.last_checks |= LSTCHK_CTTPROXY;
1893#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001894 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001895#else /* no TPROXY support */
1896 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001897 file, linenum, "usesrc");
1898 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001899#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001902 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1903 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1904 file, linenum, "usesrc", "source");
1905 return -1;
1906 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001908 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 +02001909 file, linenum, newsrv->id);
1910 return -1;
1911 }
1912 }
1913
1914 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001915 if (newsrv->trackit) {
1916 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1917 file, linenum);
1918 return -1;
1919 }
1920
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001921 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1922 newsrv->check_port = newsrv->check_addr.sin_port;
1923
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1925 newsrv->check_port = realport; /* by default */
1926 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001927 /* not yet valid, because no port was set on
1928 * the server either. We'll check if we have
1929 * a known port on the first listener.
1930 */
1931 struct listener *l;
1932 l = curproxy->listen;
1933 if (l) {
1934 int port;
1935 port = (l->addr.ss_family == AF_INET6)
1936 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1937 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1938 newsrv->check_port = port;
1939 }
1940 }
1941 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001942 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1943 file, linenum, newsrv->id);
1944 return -1;
1945 }
1946 newsrv->state |= SRV_CHECKED;
1947 }
1948
1949 if (newsrv->state & SRV_BACKUP)
1950 curproxy->srv_bck++;
1951 else
1952 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001953
1954 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955 }
1956 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001957 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001958 int facility;
1959
1960 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1961 curproxy->logfac1 = global.logfac1;
1962 curproxy->logsrv1 = global.logsrv1;
1963 curproxy->loglev1 = global.loglev1;
1964 curproxy->logfac2 = global.logfac2;
1965 curproxy->logsrv2 = global.logsrv2;
1966 curproxy->loglev2 = global.loglev2;
1967 }
1968 else if (*(args[1]) && *(args[2])) {
1969 int level;
1970
1971 facility = get_log_facility(args[2]);
1972 if (facility < 0) {
1973 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1974 exit(1);
1975 }
1976
1977 level = 7; /* max syslog level = debug */
1978 if (*(args[3])) {
1979 level = get_log_level(args[3]);
1980 if (level < 0) {
1981 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1982 exit(1);
1983 }
1984 }
1985
Robert Tsai81ae1952007-12-05 10:47:29 +01001986 if (args[1][0] == '/') {
1987 logsrv.u.addr.sa_family = AF_UNIX;
1988 logsrv.u.un = *str2sun(args[1]);
1989 } else {
1990 logsrv.u.addr.sa_family = AF_INET;
1991 logsrv.u.in = *str2sa(args[1]);
1992 if (!logsrv.u.in.sin_port) {
1993 logsrv.u.in.sin_port =
1994 htons(SYSLOG_PORT);
1995 }
1996 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001997
1998 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001999 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002000 curproxy->logfac1 = facility;
2001 curproxy->loglev1 = level;
2002 }
2003 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002004 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002005 curproxy->logfac2 = facility;
2006 curproxy->loglev2 = level;
2007 }
2008 else {
2009 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2010 return -1;
2011 }
2012 }
2013 else {
2014 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2015 file, linenum);
2016 return -1;
2017 }
2018 }
2019 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002020 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2021 return 0;
2022
Willy Tarreaubaaee002006-06-26 02:48:02 +02002023 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002024#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002025 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2026 file, linenum, "source", "usesrc");
2027#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2029 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002030#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 return -1;
2032 }
2033
2034 curproxy->source_addr = *str2sa(args[1]);
2035 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01002036 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002037#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2038#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002039 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2040 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2041 file, linenum, "usesrc");
2042 return -1;
2043 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002044#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002045 if (!*args[3]) {
2046 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2047 file, linenum, "usesrc");
2048 return -1;
2049 }
2050
2051 if (!strcmp(args[3], "client")) {
2052 curproxy->options |= PR_O_TPXY_CLI;
2053 } else if (!strcmp(args[3], "clientip")) {
2054 curproxy->options |= PR_O_TPXY_CIP;
2055 } else {
2056 curproxy->options |= PR_O_TPXY_ADDR;
2057 curproxy->tproxy_addr = *str2sa(args[3]);
2058 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002059 global.last_checks |= LSTCHK_NETADM;
2060#if !defined(CONFIG_HAP_LINUX_TPROXY)
2061 global.last_checks |= LSTCHK_CTTPROXY;
2062#endif
2063#else /* no TPROXY support */
2064 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002065 file, linenum, "usesrc");
2066 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002067#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002068 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002069 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002070 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2071 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2072 file, linenum, "usesrc", "source");
2073 return -1;
2074 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002075 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2076 regex_t *preg;
2077 if (curproxy == &defproxy) {
2078 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2079 return -1;
2080 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002081 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2082 return 0;
2083
Willy Tarreaubaaee002006-06-26 02:48:02 +02002084 if (*(args[1]) == 0 || *(args[2]) == 0) {
2085 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2086 file, linenum, args[0]);
2087 return -1;
2088 }
2089
2090 preg = calloc(1, sizeof(regex_t));
2091 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2092 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2093 return -1;
2094 }
2095
2096 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2097 if (err) {
2098 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2099 file, linenum, *err);
2100 return -1;
2101 }
2102 }
2103 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2104 regex_t *preg;
2105 if (curproxy == &defproxy) {
2106 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2107 return -1;
2108 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002109 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2110 return 0;
2111
Willy Tarreaubaaee002006-06-26 02:48:02 +02002112 if (*(args[1]) == 0) {
2113 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2114 return -1;
2115 }
2116
2117 preg = calloc(1, sizeof(regex_t));
2118 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2119 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2120 return -1;
2121 }
2122
2123 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2124 }
2125 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2126 regex_t *preg;
2127 if (curproxy == &defproxy) {
2128 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2129 return -1;
2130 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002131 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2132 return 0;
2133
Willy Tarreaubaaee002006-06-26 02:48:02 +02002134 if (*(args[1]) == 0) {
2135 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2136 return -1;
2137 }
2138
2139 preg = calloc(1, sizeof(regex_t));
2140 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2141 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2142 return -1;
2143 }
2144
2145 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2146 }
2147 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2148 regex_t *preg;
2149 if (curproxy == &defproxy) {
2150 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2151 return -1;
2152 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002153 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2154 return 0;
2155
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156 if (*(args[1]) == 0) {
2157 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2158 return -1;
2159 }
2160
2161 preg = calloc(1, sizeof(regex_t));
2162 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2163 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2164 return -1;
2165 }
2166
2167 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2168 }
2169 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2170 regex_t *preg;
2171 if (curproxy == &defproxy) {
2172 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2173 return -1;
2174 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002175 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2176 return 0;
2177
Willy Tarreaubaaee002006-06-26 02:48:02 +02002178 if (*(args[1]) == 0) {
2179 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2180 return -1;
2181 }
2182
2183 preg = calloc(1, sizeof(regex_t));
2184 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2185 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2186 return -1;
2187 }
2188
2189 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2190 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002191 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2192 regex_t *preg;
2193 if (curproxy == &defproxy) {
2194 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2195 return -1;
2196 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002197 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2198 return 0;
2199
Willy Tarreaub8750a82006-09-03 09:56:00 +02002200 if (*(args[1]) == 0) {
2201 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2202 return -1;
2203 }
2204
2205 preg = calloc(1, sizeof(regex_t));
2206 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2207 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2208 return -1;
2209 }
2210
2211 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2212 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002213 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2214 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002215 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002216 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2217 return -1;
2218 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002219 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2220 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002221
Willy Tarreau977b8e42006-12-29 14:19:17 +01002222 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002223 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2224 file, linenum, args[0]);
2225 return -1;
2226 }
2227
2228 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002229 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002230 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2231 }
2232
2233 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2234 }
2235 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2236 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002237 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002238 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2239 return -1;
2240 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002241 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2242 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002243
Willy Tarreau977b8e42006-12-29 14:19:17 +01002244 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002245 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2246 file, linenum, args[0]);
2247 return -1;
2248 }
2249
2250 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002251 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002252 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2253 }
2254
2255 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2256 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2258 regex_t *preg;
2259 if (curproxy == &defproxy) {
2260 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2261 return -1;
2262 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002263 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2264 return 0;
2265
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 if (*(args[1]) == 0 || *(args[2]) == 0) {
2267 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2268 file, linenum, args[0]);
2269 return -1;
2270 }
2271
2272 preg = calloc(1, sizeof(regex_t));
2273 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2274 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2275 return -1;
2276 }
2277
2278 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2279 if (err) {
2280 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2281 file, linenum, *err);
2282 return -1;
2283 }
2284 }
2285 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2286 regex_t *preg;
2287 if (curproxy == &defproxy) {
2288 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2289 return -1;
2290 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002291 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2292 return 0;
2293
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 if (*(args[1]) == 0) {
2295 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2296 return -1;
2297 }
2298
2299 preg = calloc(1, sizeof(regex_t));
2300 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2301 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2302 return -1;
2303 }
2304
2305 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2306 }
2307 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2308 regex_t *preg;
2309 if (curproxy == &defproxy) {
2310 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2311 return -1;
2312 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002313 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2314 return 0;
2315
Willy Tarreaubaaee002006-06-26 02:48:02 +02002316 if (*(args[1]) == 0) {
2317 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2318 return -1;
2319 }
2320
2321 preg = calloc(1, sizeof(regex_t));
2322 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2323 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2324 return -1;
2325 }
2326
2327 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2328 }
2329 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2330 regex_t *preg;
2331 if (curproxy == &defproxy) {
2332 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2333 return -1;
2334 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002335 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2336 return 0;
2337
Willy Tarreaubaaee002006-06-26 02:48:02 +02002338 if (*(args[1]) == 0) {
2339 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2340 return -1;
2341 }
2342
2343 preg = calloc(1, sizeof(regex_t));
2344 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2345 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2346 return -1;
2347 }
2348
2349 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2350 }
2351 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2352 regex_t *preg;
2353 if (curproxy == &defproxy) {
2354 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2355 return -1;
2356 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002357 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2358 return 0;
2359
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 if (*(args[1]) == 0) {
2361 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2362 return -1;
2363 }
2364
2365 preg = calloc(1, sizeof(regex_t));
2366 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2367 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2368 return -1;
2369 }
2370
2371 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2372 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002373 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2374 regex_t *preg;
2375 if (curproxy == &defproxy) {
2376 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2377 return -1;
2378 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002379 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2380 return 0;
2381
Willy Tarreaub8750a82006-09-03 09:56:00 +02002382 if (*(args[1]) == 0) {
2383 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2384 return -1;
2385 }
2386
2387 preg = calloc(1, sizeof(regex_t));
2388 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2389 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2390 return -1;
2391 }
2392
2393 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2396 if (curproxy == &defproxy) {
2397 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2398 return -1;
2399 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002400 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2401 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402
2403 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2404 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2405 return 0;
2406 }
2407
2408 if (*(args[1]) == 0) {
2409 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2410 return -1;
2411 }
2412
2413 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2414 }
2415 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2416 regex_t *preg;
2417
2418 if (*(args[1]) == 0 || *(args[2]) == 0) {
2419 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2420 file, linenum, args[0]);
2421 return -1;
2422 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002423 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2424 return 0;
2425
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 preg = calloc(1, sizeof(regex_t));
2427 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2428 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2429 return -1;
2430 }
2431
2432 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2433 if (err) {
2434 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2435 file, linenum, *err);
2436 return -1;
2437 }
2438 }
2439 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2440 regex_t *preg;
2441 if (curproxy == &defproxy) {
2442 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2443 return -1;
2444 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002445 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2446 return 0;
2447
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 if (*(args[1]) == 0) {
2449 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2450 return -1;
2451 }
2452
2453 preg = calloc(1, sizeof(regex_t));
2454 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2455 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2456 return -1;
2457 }
2458
2459 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2460 if (err) {
2461 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2462 file, linenum, *err);
2463 return -1;
2464 }
2465 }
2466 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2467 regex_t *preg;
2468 if (curproxy == &defproxy) {
2469 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2470 return -1;
2471 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002472 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2473 return 0;
2474
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 if (*(args[1]) == 0) {
2476 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2477 return -1;
2478 }
2479
2480 preg = calloc(1, sizeof(regex_t));
2481 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2482 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2483 return -1;
2484 }
2485
2486 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2487 if (err) {
2488 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2489 file, linenum, *err);
2490 return -1;
2491 }
2492 }
2493 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2494 regex_t *preg;
2495 if (curproxy == &defproxy) {
2496 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2497 return -1;
2498 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002499 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2500 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501
2502 if (*(args[1]) == 0 || *(args[2]) == 0) {
2503 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2504 file, linenum, args[0]);
2505 return -1;
2506 }
2507
2508 preg = calloc(1, sizeof(regex_t));
2509 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2510 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2511 return -1;
2512 }
2513
2514 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2515 if (err) {
2516 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2517 file, linenum, *err);
2518 return -1;
2519 }
2520 }
2521 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2522 regex_t *preg;
2523 if (curproxy == &defproxy) {
2524 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2525 return -1;
2526 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002527 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2528 return 0;
2529
Willy Tarreaubaaee002006-06-26 02:48:02 +02002530 if (*(args[1]) == 0) {
2531 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2532 return -1;
2533 }
2534
2535 preg = calloc(1, sizeof(regex_t));
2536 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2537 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2538 return -1;
2539 }
2540
2541 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2542 if (err) {
2543 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2544 file, linenum, *err);
2545 return -1;
2546 }
2547 }
2548 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2549 regex_t *preg;
2550 if (curproxy == &defproxy) {
2551 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2552 return -1;
2553 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002554 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2555 return 0;
2556
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 if (*(args[1]) == 0) {
2558 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2559 return -1;
2560 }
2561
2562 preg = calloc(1, sizeof(regex_t));
2563 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2564 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2565 return -1;
2566 }
2567
2568 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2569 if (err) {
2570 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2571 file, linenum, *err);
2572 return -1;
2573 }
2574 }
2575 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2576 if (curproxy == &defproxy) {
2577 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2578 return -1;
2579 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002580 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2581 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582
2583 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2584 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2585 return 0;
2586 }
2587
2588 if (*(args[1]) == 0) {
2589 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2590 return -1;
2591 }
2592
2593 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2594 }
2595 else if (!strcmp(args[0], "errorloc") ||
2596 !strcmp(args[0], "errorloc302") ||
2597 !strcmp(args[0], "errorloc303")) { /* error location */
2598 int errnum, errlen;
2599 char *err;
2600
Willy Tarreau977b8e42006-12-29 14:19:17 +01002601 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2602 return 0;
2603
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002605 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 return -1;
2607 }
2608
2609 errnum = atol(args[1]);
2610 if (!strcmp(args[0], "errorloc303")) {
2611 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2612 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2613 } else {
2614 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2615 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2616 }
2617
Willy Tarreau0f772532006-12-23 20:51:41 +01002618 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2619 if (http_err_codes[rc] == errnum) {
2620 if (curproxy->errmsg[rc].str)
2621 free(curproxy->errmsg[rc].str);
2622 curproxy->errmsg[rc].str = err;
2623 curproxy->errmsg[rc].len = errlen;
2624 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002627
2628 if (rc >= HTTP_ERR_SIZE) {
2629 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2630 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631 free(err);
2632 }
2633 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002634 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2635 int errnum, errlen, fd;
2636 char *err;
2637 struct stat stat;
2638
2639 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2640 return 0;
2641
2642 if (*(args[2]) == 0) {
2643 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2644 return -1;
2645 }
2646
2647 fd = open(args[2], O_RDONLY);
2648 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2649 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2650 file, linenum, args[2], args[1]);
2651 if (fd >= 0)
2652 close(fd);
2653 return -1;
2654 }
2655
2656 if (stat.st_size <= BUFSIZE) {
2657 errlen = stat.st_size;
2658 } else {
2659 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2660 file, linenum, args[2], BUFSIZE);
2661 errlen = BUFSIZE;
2662 }
2663
2664 err = malloc(errlen); /* malloc() must succeed during parsing */
2665 errnum = read(fd, err, errlen);
2666 if (errnum != errlen) {
2667 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2668 file, linenum, args[2], args[1]);
2669 close(fd);
2670 free(err);
2671 return -1;
2672 }
2673 close(fd);
2674
2675 errnum = atol(args[1]);
2676 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2677 if (http_err_codes[rc] == errnum) {
2678 if (curproxy->errmsg[rc].str)
2679 free(curproxy->errmsg[rc].str);
2680 curproxy->errmsg[rc].str = err;
2681 curproxy->errmsg[rc].len = errlen;
2682 break;
2683 }
2684 }
2685
2686 if (rc >= HTTP_ERR_SIZE) {
2687 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2688 file, linenum, errnum);
2689 free(err);
2690 }
2691 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002693 struct cfg_kw_list *kwl;
2694 int index;
2695
2696 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2697 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2698 if (kwl->kw[index].section != CFG_LISTEN)
2699 continue;
2700 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2701 /* prepare error message just in case */
2702 snprintf(trash, sizeof(trash),
2703 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002704 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2705 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002706 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2707 return -1;
2708 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002709 else if (rc > 0) {
2710 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2711 return 0;
2712 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002713 return 0;
2714 }
2715 }
2716 }
2717
Willy Tarreau6daf3432008-01-22 16:44:08 +01002718 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002719 return -1;
2720 }
2721 return 0;
2722}
2723
2724
2725/*
2726 * This function reads and parses the configuration file given in the argument.
2727 * returns 0 if OK, -1 if error.
2728 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002729int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002730{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002731 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 FILE *f;
2733 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002734 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002735 int confsect = CFG_NONE;
2736
2737 struct proxy *curproxy = NULL;
2738 struct server *newsrv = NULL;
2739
2740 if ((f=fopen(file,"r")) == NULL)
2741 return -1;
2742
2743 init_default_instance();
2744
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002745 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002746 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002747 char *end;
2748 char *args[MAX_LINE_ARGS + 1];
2749 char *line = thisline;
2750
Willy Tarreaubaaee002006-06-26 02:48:02 +02002751 linenum++;
2752
2753 end = line + strlen(line);
2754
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002755 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2756 /* Check if we reached the limit and the last char is not \n.
2757 * Watch out for the last line without the terminating '\n'!
2758 */
2759 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2760 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002761 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002762 }
2763
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002765 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002766 line++;
2767
2768 arg = 0;
2769 args[arg] = line;
2770
2771 while (*line && arg < MAX_LINE_ARGS) {
2772 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2773 * C equivalent value. Other combinations left unchanged (eg: \1).
2774 */
2775 if (*line == '\\') {
2776 int skip = 0;
2777 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2778 *line = line[1];
2779 skip = 1;
2780 }
2781 else if (line[1] == 'r') {
2782 *line = '\r';
2783 skip = 1;
2784 }
2785 else if (line[1] == 'n') {
2786 *line = '\n';
2787 skip = 1;
2788 }
2789 else if (line[1] == 't') {
2790 *line = '\t';
2791 skip = 1;
2792 }
2793 else if (line[1] == 'x') {
2794 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2795 unsigned char hex1, hex2;
2796 hex1 = toupper(line[2]) - '0';
2797 hex2 = toupper(line[3]) - '0';
2798 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2799 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2800 *line = (hex1<<4) + hex2;
2801 skip = 3;
2802 }
2803 else {
2804 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002805 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002806 }
2807 }
2808 if (skip) {
2809 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2810 end -= skip;
2811 }
2812 line++;
2813 }
2814 else if (*line == '#' || *line == '\n' || *line == '\r') {
2815 /* end of string, end of loop */
2816 *line = 0;
2817 break;
2818 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002819 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002820 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002821 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002822 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823 line++;
2824 args[++arg] = line;
2825 }
2826 else {
2827 line++;
2828 }
2829 }
2830
2831 /* empty line */
2832 if (!**args)
2833 continue;
2834
Willy Tarreau540abe42007-05-02 20:50:16 +02002835 /* zero out remaining args and ensure that at least one entry
2836 * is zeroed out.
2837 */
2838 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 args[arg] = line;
2840 }
2841
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002842 if (!strcmp(args[0], "no")) {
2843 inv = 1;
2844 for (arg=0; *args[arg+1]; arg++)
2845 args[arg] = args[arg+1]; // shift args after inversion
2846 }
2847
2848 if (inv && strcmp(args[0], "option")) {
2849 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002850 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002851 }
2852
Willy Tarreau977b8e42006-12-29 14:19:17 +01002853 if (!strcmp(args[0], "listen") ||
2854 !strcmp(args[0], "frontend") ||
2855 !strcmp(args[0], "backend") ||
2856 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002857 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002858 confsect = CFG_LISTEN;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002859 if (cursection)
2860 free(cursection);
2861 cursection = strdup(args[0]);
2862 }
2863 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864 confsect = CFG_GLOBAL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002865 if (cursection)
2866 free(cursection);
2867 cursection = strdup(args[0]);
2868 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869 /* else it's a section keyword */
2870
2871 switch (confsect) {
2872 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002873 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002874 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875 break;
2876 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002877 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002878 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879 break;
2880 default:
2881 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002882 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002883 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002884 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01002885 if (cursection)
2886 free(cursection);
2887 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002888 fclose(f);
2889
2890 /*
2891 * Now, check for the integrity of all that we have collected.
2892 */
2893
2894 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002895 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896
2897 if ((curproxy = proxy) == NULL) {
2898 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2899 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002900 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 }
2902
2903 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002904 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002905 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002906
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907 if (curproxy->state == PR_STSTOPPED) {
2908 curproxy = curproxy->next;
2909 continue;
2910 }
2911
Willy Tarreau977b8e42006-12-29 14:19:17 +01002912 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2913 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 +01002914 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 cfgerr++;
2916 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002917 else if (curproxy->cap & PR_CAP_BE &&
2918 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002919 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002920 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002921 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2922 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 +01002923 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002924 cfgerr++;
2925 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002926
Willy Tarreau31682232007-11-29 15:38:04 +01002927 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002929 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002930 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002931 cfgerr++;
2932 }
2933#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2934 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002935 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002936 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002937 cfgerr++;
2938 }
2939#endif
2940 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002941 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002942 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002943 }
2944 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002945
2946 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002948 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002949 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002950 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002951 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002952 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002953 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002954 }
2955 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002956 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002957 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002958 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002959 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002960 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002961 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002962 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002963 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002964 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2965 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002966
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002967 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002968 file, proxy_type_str(curproxy), curproxy->id);
2969 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002970 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002971
2972 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2973 if ((newsrv = curproxy->srv) != NULL) {
2974 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2975 file, proxy_type_str(curproxy), curproxy->id);
2976 }
2977 }
2978
2979 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2981 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2982 file, curproxy->id);
2983 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002984 }
2985 }
2986
Willy Tarreau82936582007-11-30 15:20:09 +01002987 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2988 curproxy->options &= ~PR_O_DISABLE404;
2989 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2990 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2991 }
2992
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002993 /* if a default backend was specified, let's find it */
2994 if (curproxy->defbe.name) {
2995 struct proxy *target;
2996
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002997 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2998 if (!target) {
2999 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3000 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003001 cfgerr++;
3002 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003003 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3004 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003005 } else {
3006 free(curproxy->defbe.name);
3007 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003008 }
3009 }
3010
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003011 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003012 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3013 /* map jump target for ACT_SETBE in req_rep chain */
3014 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003015 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003016 struct proxy *target;
3017
Willy Tarreaua496b602006-12-17 23:15:24 +01003018 if (exp->action != ACT_SETBE)
3019 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003020
3021 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3022 if (!target) {
3023 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3024 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003025 cfgerr++;
3026 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003027 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3028 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003029 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003030 } else {
3031 free((void *)exp->replace);
3032 exp->replace = (const char *)target;
3033 }
3034 }
3035 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003036
3037 /* find the target proxy for 'use_backend' rules */
3038 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003039 struct proxy *target;
3040
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003041 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003042
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003043 if (!target) {
3044 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3045 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003046 cfgerr++;
3047 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003048 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3049 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003050 cfgerr++;
3051 } else {
3052 free((void *)rule->be.name);
3053 rule->be.backend = target;
3054 }
3055 }
3056
Willy Tarreau2738a142006-07-08 17:28:09 +02003057 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003058 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003059 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003060 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003061 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003062 " | While not properly invalid, you will certainly encounter various problems\n"
3063 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003064 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003065 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003066 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003067
Willy Tarreau1fa31262007-12-03 00:36:16 +01003068 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3069 * We must still support older configurations, so let's find out whether those
3070 * parameters have been set or must be copied from contimeouts.
3071 */
3072 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003073 if (!curproxy->timeout.tarpit ||
3074 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003075 /* tarpit timeout not set. We search in the following order:
3076 * default.tarpit, curr.connect, default.connect.
3077 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003078 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003079 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003080 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003081 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003082 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003083 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003084 }
3085 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003086 (!curproxy->timeout.queue ||
3087 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003088 /* queue timeout not set. We search in the following order:
3089 * default.queue, curr.connect, default.connect.
3090 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003091 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003092 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003093 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003094 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003095 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003096 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003097 }
3098 }
3099
Willy Tarreauf3c69202006-07-09 16:42:34 +02003100 if (curproxy->options & PR_O_SSL3_CHK) {
3101 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3102 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3103 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3104 }
3105
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003106 /* The small pools required for the capture lists */
3107 if (curproxy->nb_req_cap)
3108 curproxy->req_cap_pool = create_pool("ptrcap",
3109 curproxy->nb_req_cap * sizeof(char *),
3110 MEM_F_SHARED);
3111 if (curproxy->nb_rsp_cap)
3112 curproxy->rsp_cap_pool = create_pool("ptrcap",
3113 curproxy->nb_rsp_cap * sizeof(char *),
3114 MEM_F_SHARED);
3115
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003116 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3117 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3118 MEM_F_SHARED);
3119
Willy Tarreau86034312006-12-29 00:10:33 +01003120 /* for backwards compatibility with "listen" instances, if
3121 * fullconn is not set but maxconn is set, then maxconn
3122 * is used.
3123 */
3124 if (!curproxy->fullconn)
3125 curproxy->fullconn = curproxy->maxconn;
3126
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127 /* first, we will invert the servers list order */
3128 newsrv = NULL;
3129 while (curproxy->srv) {
3130 struct server *next;
3131
3132 next = curproxy->srv->next;
3133 curproxy->srv->next = newsrv;
3134 newsrv = curproxy->srv;
3135 if (!next)
3136 break;
3137 curproxy->srv = next;
3138 }
3139
Willy Tarreau20697042007-11-15 23:26:18 +01003140 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003141 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142
Willy Tarreaub625a082007-11-26 01:15:43 +01003143 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003144 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003145 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003146 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3147 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003148 else
3149 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150
3151 if (curproxy->options & PR_O_LOGASAP)
3152 curproxy->to_log &= ~LW_BYTES;
3153
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003155 * ensure that we're not cross-dressing a TCP server into HTTP.
3156 */
3157 newsrv = curproxy->srv;
3158 while (newsrv != NULL) {
3159 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3160 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3161 file, proxy_type_str(curproxy), curproxy->id, linenum);
3162 goto err;
3163 }
3164 newsrv = newsrv->next;
3165 }
3166
3167 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003168 * If this server supports a maxconn parameter, it needs a dedicated
3169 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003170 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003171 */
3172 newsrv = curproxy->srv;
3173 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003174 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003175 /* Only 'minconn' was specified, or it was higher than or equal
3176 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3177 * this will avoid further useless expensive computations.
3178 */
3179 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003180 } else if (newsrv->maxconn && !newsrv->minconn) {
3181 /* minconn was not specified, so we set it to maxconn */
3182 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003183 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3184 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003185 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003186 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 }
3188
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003189 if (newsrv->trackit) {
3190 struct proxy *px;
3191 struct server *srv;
3192 char *pname, *sname;
3193
3194 pname = newsrv->trackit;
3195 sname = strrchr(pname, '/');
3196
3197 if (sname)
3198 *sname++ = '\0';
3199 else {
3200 sname = pname;
3201 pname = NULL;
3202 }
3203
3204 if (pname) {
3205 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3206 if (!px) {
3207 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3208 file, proxy_type_str(curproxy), curproxy->id,
3209 newsrv->id, pname);
3210 return -1;
3211 }
3212 } else
3213 px = curproxy;
3214
3215 srv = findserver(px, sname);
3216 if (!srv) {
3217 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3218 file, proxy_type_str(curproxy), curproxy->id,
3219 newsrv->id, sname);
3220 return -1;
3221 }
3222
3223 if (!(srv->state & SRV_CHECKED)) {
3224 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3225 "tracing as it does not have checks enabled.\n",
3226 file, proxy_type_str(curproxy), curproxy->id,
3227 newsrv->id, px->id, srv->id);
3228 return -1;
3229 }
3230
3231 if (curproxy != px &&
3232 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3233 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3234 "tracing: disable-on-404 option inconsistency.\n",
3235 file, proxy_type_str(curproxy), curproxy->id,
3236 newsrv->id, px->id, srv->id);
3237 return -1;
3238 }
3239
3240 newsrv->tracked = srv;
3241 newsrv->tracknext = srv->tracknext;
3242 srv->tracknext = newsrv;
3243
3244 free(newsrv->trackit);
3245 }
3246
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 newsrv = newsrv->next;
3248 }
3249
Willy Tarreaue6b98942007-10-29 01:09:36 +01003250 /* adjust this proxy's listeners */
3251 listener = curproxy->listen;
3252 while (listener) {
3253 if (curproxy->options & PR_O_TCP_NOLING)
3254 listener->options |= LI_O_NOLINGER;
3255 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003256 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003257 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003258 listener->accept = event_accept;
3259 listener->private = curproxy;
3260
3261 listener = listener->next;
3262 }
3263
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 curproxy = curproxy->next;
3265 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003266
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 if (cfgerr > 0) {
3268 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003269 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003271
3272 /*
3273 * Recount currently required checks.
3274 */
3275
3276 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3277 int optnum;
3278
3279 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3280 if (!(curproxy->options & cfg_opts[optnum].val))
3281 continue;
3282
3283 global.last_checks |= cfg_opts[optnum].checks;
3284 }
3285 }
3286
Willy Tarreau6daf3432008-01-22 16:44:08 +01003287 if (cursection)
3288 free(cursection);
3289 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003290 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003291
3292 err:
3293 if (cursection)
3294 free(cursection);
3295 cursection = NULL;
3296 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297}
3298
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003299/*
3300 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3301 * parsing sessions.
3302 */
3303void cfg_register_keywords(struct cfg_kw_list *kwl)
3304{
3305 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3306}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003308/*
3309 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3310 */
3311void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3312{
3313 LIST_DEL(&kwl->list);
3314 LIST_INIT(&kwl->list);
3315}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316
3317/*
3318 * Local variables:
3319 * c-indent-level: 8
3320 * c-basic-offset: 8
3321 * End:
3322 */