blob: 5f4e1238a3b18cf9166126ec2c4c9f1a94be9a3f [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 Tarreau79f5fe82008-08-23 08:18:21 +0200640 if (defproxy.fwdfor_hdr_len) {
641 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
642 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
643 }
644
Willy Tarreau977b8e42006-12-29 14:19:17 +0100645 if (curproxy->cap & PR_CAP_FE) {
646 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100647 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100648
649 /* initialize error relocations */
650 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
651 if (defproxy.errmsg[rc].str)
652 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
653 }
654
655 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657
Willy Tarreau977b8e42006-12-29 14:19:17 +0100658 if (curproxy->cap & PR_CAP_BE) {
659 curproxy->fullconn = defproxy.fullconn;
660 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661
Willy Tarreau977b8e42006-12-29 14:19:17 +0100662 if (defproxy.check_req)
663 curproxy->check_req = strdup(defproxy.check_req);
664 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665
Willy Tarreau977b8e42006-12-29 14:19:17 +0100666 if (defproxy.cookie_name)
667 curproxy->cookie_name = strdup(defproxy.cookie_name);
668 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100669
670 if (defproxy.url_param_name)
671 curproxy->url_param_name = strdup(defproxy.url_param_name);
672 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100673 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674
Willy Tarreau977b8e42006-12-29 14:19:17 +0100675 if (curproxy->cap & PR_CAP_RS) {
676 if (defproxy.capture_name)
677 curproxy->capture_name = strdup(defproxy.capture_name);
678 curproxy->capture_namelen = defproxy.capture_namelen;
679 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100680 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200681
Willy Tarreau977b8e42006-12-29 14:19:17 +0100682 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100683 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100684 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100685 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100686 curproxy->uri_auth = defproxy.uri_auth;
687 curproxy->mon_net = defproxy.mon_net;
688 curproxy->mon_mask = defproxy.mon_mask;
689 if (defproxy.monitor_uri)
690 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
691 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100692 if (defproxy.defbe.name)
693 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100694 }
695
696 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100697 curproxy->timeout.connect = defproxy.timeout.connect;
698 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100699 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100700 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100701 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100702 curproxy->source_addr = defproxy.source_addr;
703 }
704
Willy Tarreaubaaee002006-06-26 02:48:02 +0200705 curproxy->mode = defproxy.mode;
706 curproxy->logfac1 = defproxy.logfac1;
707 curproxy->logsrv1 = defproxy.logsrv1;
708 curproxy->loglev1 = defproxy.loglev1;
709 curproxy->logfac2 = defproxy.logfac2;
710 curproxy->logsrv2 = defproxy.logsrv2;
711 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200712 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100713 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
714 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200715
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716 return 0;
717 }
718 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
719 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100720 /* FIXME-20070101: we should do this too at the end of the
721 * config parsing to free all default values.
722 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200723 free(defproxy.check_req);
724 free(defproxy.cookie_name);
725 free(defproxy.url_param_name);
726 free(defproxy.capture_name);
727 free(defproxy.monitor_uri);
728 free(defproxy.defbe.name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200729 free(defproxy.fwdfor_hdr_name);
730 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100731
Willy Tarreaua534fea2008-08-03 12:19:50 +0200732 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
733 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100734
Willy Tarreaubaaee002006-06-26 02:48:02 +0200735 /* we cannot free uri_auth because it might already be used */
736 init_default_instance();
737 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100738 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200739 return 0;
740 }
741 else if (curproxy == NULL) {
742 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
743 return -1;
744 }
745
Willy Tarreau977b8e42006-12-29 14:19:17 +0100746
747 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100749 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200750 if (curproxy == &defproxy) {
751 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
752 return -1;
753 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100754 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
755 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200756
757 if (strchr(args[1], ':') == NULL) {
758 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
759 file, linenum, args[0]);
760 return -1;
761 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100762
763 last_listen = curproxy->listen;
764 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200765 if (!curproxy->listen)
766 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100767 if (*args[2]) {
768#ifdef CONFIG_HAP_LINUX_TPROXY
769 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
770 struct listener *l;
771
772 for (l = curproxy->listen; l != last_listen; l = l->next)
773 l->options |= LI_O_FOREIGN;
774 }
775 else {
776 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
777 file, linenum, args[0]);
778 return -1;
779 }
780#else
781 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
782 file, linenum, args[0]);
783 return -1;
784#endif
785 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200786 global.maxsock++;
787 return 0;
788 }
789 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
790 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
791 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
792 file, linenum, args[0]);
793 return -1;
794 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100795 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
796 return 0;
797
Willy Tarreaubaaee002006-06-26 02:48:02 +0200798 /* flush useless bits */
799 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
800 return 0;
801 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200802 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100803 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
804 return 0;
805
Willy Tarreau1c47f852006-07-09 08:22:27 +0200806 if (!*args[1]) {
807 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
808 file, linenum, args[0]);
809 return -1;
810 }
811
Willy Tarreaua534fea2008-08-03 12:19:50 +0200812 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100813 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200814 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100815 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200816 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
817
818 return 0;
819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200820 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
821 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
822 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
823 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
824 else {
825 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
826 return -1;
827 }
828 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100829 else if (!strcmp(args[0], "id")) {
830 struct proxy *target;
831
832 if (curproxy == &defproxy) {
833 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
834 file, linenum, args[0]);
835 return -1;
836 }
837
838 if (!*args[1]) {
839 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
840 file, linenum, args[0]);
841 return -1;
842 }
843
844 curproxy->uuid = atol(args[1]);
845
846 if (curproxy->uuid < 1001) {
847 Alert("parsing [%s:%d]: custom id has to be > 1000",
848 file, linenum);
849 return -1;
850 }
851
852 for (target = proxy; target; target = target->next)
853 if (curproxy != target && curproxy->uuid == target->uuid) {
854 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
855 file, linenum, curproxy->id, target->id);
856 return -1;
857 }
858 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200859 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
860 curproxy->state = PR_STSTOPPED;
861 }
862 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
863 curproxy->state = PR_STNEW;
864 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200865 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100866 err = invalid_char(args[1]);
867 if (err) {
868 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
869 file, linenum, *err, args[1]);
870 return -1;
871 }
872
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200873 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
874 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
875 file, linenum, args[1]);
876 return -1;
877 }
878 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879 else if (!strcmp(args[0], "cookie")) { /* cookie name */
880 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200881
Willy Tarreau977b8e42006-12-29 14:19:17 +0100882 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
883 return 0;
884
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885 if (*(args[1]) == 0) {
886 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
887 file, linenum, args[0]);
888 return -1;
889 }
Willy Tarreaua534fea2008-08-03 12:19:50 +0200890
891 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 curproxy->cookie_name = strdup(args[1]);
893 curproxy->cookie_len = strlen(curproxy->cookie_name);
894
895 cur_arg = 2;
896 while (*(args[cur_arg])) {
897 if (!strcmp(args[cur_arg], "rewrite")) {
898 curproxy->options |= PR_O_COOK_RW;
899 }
900 else if (!strcmp(args[cur_arg], "indirect")) {
901 curproxy->options |= PR_O_COOK_IND;
902 }
903 else if (!strcmp(args[cur_arg], "insert")) {
904 curproxy->options |= PR_O_COOK_INS;
905 }
906 else if (!strcmp(args[cur_arg], "nocache")) {
907 curproxy->options |= PR_O_COOK_NOC;
908 }
909 else if (!strcmp(args[cur_arg], "postonly")) {
910 curproxy->options |= PR_O_COOK_POST;
911 }
912 else if (!strcmp(args[cur_arg], "prefix")) {
913 curproxy->options |= PR_O_COOK_PFX;
914 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200915 else if (!strcmp(args[cur_arg], "domain")) {
916 if (!*args[cur_arg + 1]) {
917 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
918 file, linenum, args[cur_arg]);
919 return -1;
920 }
921
922 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
923 /* rfc2109, 4.3.2 Rejecting Cookies */
924 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
925 " dots or does not start with a dot.\n",
926 file, linenum, args[cur_arg + 1]);
927 return -1;
928 }
929
930 err = invalid_domainchar(args[cur_arg + 1]);
931 if (err) {
932 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
933 file, linenum, *err, args[cur_arg + 1]);
934 return -1;
935 }
936
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +0200937 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200938 cur_arg++;
939 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200941 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 file, linenum, args[0]);
943 return -1;
944 }
945 cur_arg++;
946 }
947 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
948 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
949 file, linenum);
950 return -1;
951 }
952
953 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
954 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
955 file, linenum);
956 return -1;
957 }
958 }/* end else if (!strcmp(args[0], "cookie")) */
959 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960
Willy Tarreau977b8e42006-12-29 14:19:17 +0100961 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
962 return 0;
963
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 if (*(args[5]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
966 file, linenum, args[0]);
967 return -1;
968 }
969 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +0200970 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200971 curproxy->appsession_name = strdup(args[1]);
972 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
973 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100974 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
975 if (err) {
976 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
977 file, linenum, *err, args[0]);
978 return -1;
979 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200980 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +0200981
Willy Tarreau51041c72007-09-09 21:56:53 +0200982 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
983 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200984 return -1;
985 }
986 } /* Url App Session */
987 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100988 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
989 return 0;
990
Willy Tarreaubaaee002006-06-26 02:48:02 +0200991 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 if (*(args[4]) == 0) {
993 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
994 file, linenum, args[0]);
995 return -1;
996 }
Willy Tarreaua534fea2008-08-03 12:19:50 +0200997 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200998 curproxy->capture_name = strdup(args[2]);
999 curproxy->capture_namelen = strlen(curproxy->capture_name);
1000 curproxy->capture_len = atol(args[4]);
1001 if (curproxy->capture_len >= CAPTURE_LEN) {
1002 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1003 file, linenum, CAPTURE_LEN - 1);
1004 curproxy->capture_len = CAPTURE_LEN - 1;
1005 }
1006 curproxy->to_log |= LW_COOKIE;
1007 }
1008 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1009 struct cap_hdr *hdr;
1010
1011 if (curproxy == &defproxy) {
1012 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1013 return -1;
1014 }
1015
1016 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1017 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1018 file, linenum, args[0], args[1]);
1019 return -1;
1020 }
1021
1022 hdr = calloc(sizeof(struct cap_hdr), 1);
1023 hdr->next = curproxy->req_cap;
1024 hdr->name = strdup(args[3]);
1025 hdr->namelen = strlen(args[3]);
1026 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001027 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001028 hdr->index = curproxy->nb_req_cap++;
1029 curproxy->req_cap = hdr;
1030 curproxy->to_log |= LW_REQHDR;
1031 }
1032 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1033 struct cap_hdr *hdr;
1034
1035 if (curproxy == &defproxy) {
1036 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1037 return -1;
1038 }
1039
1040 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1041 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1042 file, linenum, args[0], args[1]);
1043 return -1;
1044 }
1045 hdr = calloc(sizeof(struct cap_hdr), 1);
1046 hdr->next = curproxy->rsp_cap;
1047 hdr->name = strdup(args[3]);
1048 hdr->namelen = strlen(args[3]);
1049 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001050 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 hdr->index = curproxy->nb_rsp_cap++;
1052 curproxy->rsp_cap = hdr;
1053 curproxy->to_log |= LW_RSPHDR;
1054 }
1055 else {
1056 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1057 file, linenum, args[0]);
1058 return -1;
1059 }
1060 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001061 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001062 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1063 return 0;
1064
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 if (*(args[1]) == 0) {
1066 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1067 file, linenum, args[0]);
1068 return -1;
1069 }
1070 curproxy->conn_retries = atol(args[1]);
1071 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001072 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1073 int pol = ACL_COND_NONE;
1074 struct acl_cond *cond;
1075
1076 if (!strcmp(args[1], "if"))
1077 pol = ACL_COND_IF;
1078 else if (!strcmp(args[1], "unless"))
1079 pol = ACL_COND_UNLESS;
1080
1081 if (pol == ACL_COND_NONE) {
1082 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1083 file, linenum, args[0]);
1084 return -1;
1085 }
1086
1087 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1088 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1089 file, linenum);
1090 return -1;
1091 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001092 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001093 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1094 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001095 else if (!strcmp(args[0], "redirect")) {
1096 int pol = ACL_COND_NONE;
1097 struct acl_cond *cond;
1098 struct redirect_rule *rule;
1099 int cur_arg;
1100 int type = REDIRECT_TYPE_NONE;
1101 int code = 302;
1102 char *destination = NULL;
1103
1104 cur_arg = 1;
1105 while (*(args[cur_arg])) {
1106 if (!strcmp(args[cur_arg], "location")) {
1107 if (!*args[cur_arg + 1]) {
1108 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1109 file, linenum, args[0], args[cur_arg]);
1110 return -1;
1111 }
1112
1113 type = REDIRECT_TYPE_LOCATION;
1114 cur_arg++;
1115 destination = args[cur_arg];
1116 }
1117 else if (!strcmp(args[cur_arg], "prefix")) {
1118 if (!*args[cur_arg + 1]) {
1119 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1120 file, linenum, args[0], args[cur_arg]);
1121 return -1;
1122 }
1123
1124 type = REDIRECT_TYPE_PREFIX;
1125 cur_arg++;
1126 destination = args[cur_arg];
1127 }
1128 else if (!strcmp(args[cur_arg],"code")) {
1129 if (!*args[cur_arg + 1]) {
1130 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1131 file, linenum, args[0]);
1132 return -1;
1133 }
1134 cur_arg++;
1135 code = atol(args[cur_arg]);
1136 if (code < 301 || code > 303) {
1137 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1138 file, linenum, args[0], code);
1139 return -1;
1140 }
1141 }
1142 else if (!strcmp(args[cur_arg], "if")) {
1143 pol = ACL_COND_IF;
1144 cur_arg++;
1145 break;
1146 }
1147 else if (!strcmp(args[cur_arg], "unless")) {
1148 pol = ACL_COND_UNLESS;
1149 cur_arg++;
1150 break;
1151 }
1152 else {
1153 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1154 file, linenum, args[0], args[cur_arg]);
1155 return -1;
1156 }
1157 cur_arg++;
1158 }
1159
1160 if (type == REDIRECT_TYPE_NONE) {
1161 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1162 file, linenum, args[0]);
1163 return -1;
1164 }
1165
1166 if (pol == ACL_COND_NONE) {
1167 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1168 file, linenum, args[0]);
1169 return -1;
1170 }
1171
1172 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1173 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1174 file, linenum, args[0]);
1175 return -1;
1176 }
1177
Willy Tarreaua9802632008-07-25 19:13:19 +02001178 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001179 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1180 rule->cond = cond;
1181 rule->rdr_str = strdup(destination);
1182 rule->rdr_len = strlen(destination);
1183 rule->type = type;
1184 rule->code = code;
1185 LIST_INIT(&rule->list);
1186 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1187 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001188 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1189 int pol = ACL_COND_NONE;
1190 struct acl_cond *cond;
1191 struct switching_rule *rule;
1192
1193 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1194 return 0;
1195
1196 if (*(args[1]) == 0) {
1197 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1198 return -1;
1199 }
1200
1201 if (!strcmp(args[2], "if"))
1202 pol = ACL_COND_IF;
1203 else if (!strcmp(args[2], "unless"))
1204 pol = ACL_COND_UNLESS;
1205
1206 if (pol == ACL_COND_NONE) {
1207 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1208 file, linenum, args[0]);
1209 return -1;
1210 }
1211
1212 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001213 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001214 file, linenum);
1215 return -1;
1216 }
1217
Willy Tarreaua9802632008-07-25 19:13:19 +02001218 cond->line = linenum;
1219 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001220 struct acl *acl;
1221 const char *name;
1222
1223 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1224 name = acl ? acl->name : "(unknown)";
1225 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1226 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001227 }
1228
Willy Tarreau55ea7572007-06-17 19:56:27 +02001229 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1230 rule->cond = cond;
1231 rule->be.name = strdup(args[1]);
1232 LIST_INIT(&rule->list);
1233 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001235 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001236 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1237 return 0;
1238
Willy Tarreaubaaee002006-06-26 02:48:02 +02001239 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1240 curproxy->uri_auth = NULL; /* we must detach from the default config */
1241
1242 if (*(args[1]) == 0) {
1243 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1244 return -1;
1245 } else if (!strcmp(args[1], "uri")) {
1246 if (*(args[2]) == 0) {
1247 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1248 return -1;
1249 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1250 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1251 return -1;
1252 }
1253 } else if (!strcmp(args[1], "realm")) {
1254 if (*(args[2]) == 0) {
1255 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1256 return -1;
1257 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1258 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1259 return -1;
1260 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001261 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001262 unsigned interval;
1263
1264 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1265 if (err) {
1266 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1267 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001268 return -1;
1269 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1270 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1271 return -1;
1272 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001273 } else if (!strcmp(args[1], "auth")) {
1274 if (*(args[2]) == 0) {
1275 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1276 return -1;
1277 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1278 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1279 return -1;
1280 }
1281 } else if (!strcmp(args[1], "scope")) {
1282 if (*(args[2]) == 0) {
1283 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1284 return -1;
1285 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1286 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1287 return -1;
1288 }
1289 } else if (!strcmp(args[1], "enable")) {
1290 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1291 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1292 return -1;
1293 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001294 } else if (!strcmp(args[1], "hide-version")) {
1295 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1296 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1297 return -1;
1298 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001299 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001300 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001301 file, linenum, args[0]);
1302 return -1;
1303 }
1304 }
1305 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001306 int optnum;
1307
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001308 if (*(args[1]) == '\0') {
1309 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1310 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001311 return -1;
1312 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001313
1314 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1315 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1316 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1317 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001318
1319 if (!inv)
1320 curproxy->options |= cfg_opts[optnum].val;
1321 else
1322 curproxy->options &= ~cfg_opts[optnum].val;
1323
Willy Tarreau13943ab2006-12-31 00:24:10 +01001324 return 0;
1325 }
1326 }
1327
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001328 if (inv) {
1329 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1330 file, linenum, args[1]);
1331 return -1;
1332 }
1333
Willy Tarreau13943ab2006-12-31 00:24:10 +01001334 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001335 /* generate a complete HTTP log */
1336 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1337 else if (!strcmp(args[1], "tcplog"))
1338 /* generate a detailed TCP log */
1339 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001340 else if (!strcmp(args[1], "tcpka")) {
1341 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001342 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1343 return 0;
1344
1345 if (curproxy->cap & PR_CAP_FE)
1346 curproxy->options |= PR_O_TCP_CLI_KA;
1347 if (curproxy->cap & PR_CAP_BE)
1348 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 }
1350 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001351 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1352 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001354 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001355 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001356 curproxy->options &= ~PR_O_SMTP_CHK;
1357 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 if (!*args[2]) { /* no argument */
1359 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1360 curproxy->check_len = strlen(DEF_CHECK_REQ);
1361 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001362 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363 curproxy->check_req = (char *)malloc(reqlen);
1364 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1365 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1366 } else { /* more arguments : METHOD URI [HTTP_VER] */
1367 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1368 if (*args[4])
1369 reqlen += strlen(args[4]);
1370 else
1371 reqlen += strlen("HTTP/1.0");
1372
1373 curproxy->check_req = (char *)malloc(reqlen);
1374 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1375 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1376 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001377 }
1378 else if (!strcmp(args[1], "ssl-hello-chk")) {
1379 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001380 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1381 return 0;
1382
Willy Tarreaua534fea2008-08-03 12:19:50 +02001383 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001384 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001385 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001386 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001387 }
Willy Tarreau23677902007-05-08 23:50:35 +02001388 else if (!strcmp(args[1], "smtpchk")) {
1389 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001390 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001391 curproxy->options &= ~PR_O_HTTP_CHK;
1392 curproxy->options &= ~PR_O_SSL3_CHK;
1393 curproxy->options |= PR_O_SMTP_CHK;
1394
1395 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1396 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1397 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1398 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1399 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1400 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1401 curproxy->check_req = (char *)malloc(reqlen);
1402 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1403 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1404 } else {
1405 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1406 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1407 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1408 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1409 }
1410 }
1411 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001412 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001413 int cur_arg;
1414
1415 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1416 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001417 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001418
1419 curproxy->options |= PR_O_FWDFOR;
1420
1421 free(curproxy->fwdfor_hdr_name);
1422 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1423 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1424
1425 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1426 cur_arg = 2;
1427 while (*(args[cur_arg])) {
1428 if (!strcmp(args[cur_arg], "except")) {
1429 /* suboption except - needs additional argument for it */
1430 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1431 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1432 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001433 return -1;
1434 }
1435 /* flush useless bits */
1436 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001437 cur_arg += 2;
1438 } else if (!strcmp(args[cur_arg], "header")) {
1439 /* suboption header - needs additional argument for it */
1440 if (*(args[cur_arg+1]) == 0) {
1441 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1442 file, linenum, args[0], args[1], args[cur_arg]);
1443 return -1;
1444 }
1445 free(curproxy->fwdfor_hdr_name);
1446 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1447 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1448 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001449 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001450 /* unknown suboption - catchall */
1451 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1452 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001453 return -1;
1454 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001455 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001456 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 else {
1458 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1459 return -1;
1460 }
1461 return 0;
1462 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001463 else if (!strcmp(args[0], "default_backend")) {
1464 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1465 return 0;
1466
1467 if (*(args[1]) == 0) {
1468 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1469 return -1;
1470 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001471 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001472 curproxy->defbe.name = strdup(args[1]);
1473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001474 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001475 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1476 return 0;
1477
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001478 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1479 file, linenum, args[0]);
1480
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481 /* enable reconnections to dispatch */
1482 curproxy->options |= PR_O_REDISP;
1483 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001484 else if (!strcmp(args[0], "http-check")) {
1485 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1486 return 0;
1487
1488 if (strcmp(args[1], "disable-on-404") == 0) {
1489 /* enable a graceful server shutdown on an HTTP 404 response */
1490 curproxy->options |= PR_O_DISABLE404;
1491 }
1492 else {
1493 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1494 return -1;
1495 }
1496 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001497 else if (!strcmp(args[0], "monitor")) {
1498 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1499 return 0;
1500
1501 if (strcmp(args[1], "fail") == 0) {
1502 /* add a condition to fail monitor requests */
1503 int pol = ACL_COND_NONE;
1504 struct acl_cond *cond;
1505
1506 if (!strcmp(args[2], "if"))
1507 pol = ACL_COND_IF;
1508 else if (!strcmp(args[2], "unless"))
1509 pol = ACL_COND_UNLESS;
1510
1511 if (pol == ACL_COND_NONE) {
1512 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1513 file, linenum, args[0], args[1]);
1514 return -1;
1515 }
1516
1517 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1518 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1519 file, linenum, args[0], args[1]);
1520 return -1;
1521 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001522 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001523 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1524 }
1525 else {
1526 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1527 return -1;
1528 }
1529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530#ifdef TPROXY
1531 else if (!strcmp(args[0], "transparent")) {
1532 /* enable transparent proxy connections */
1533 curproxy->options |= PR_O_TRANSP;
1534 }
1535#endif
1536 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001537 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1538 return 0;
1539
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540 if (*(args[1]) == 0) {
1541 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1542 return -1;
1543 }
1544 curproxy->maxconn = atol(args[1]);
1545 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001546 else if (!strcmp(args[0], "backlog")) { /* backlog */
1547 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1548 return 0;
1549
1550 if (*(args[1]) == 0) {
1551 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1552 return -1;
1553 }
1554 curproxy->backlog = atol(args[1]);
1555 }
Willy Tarreau86034312006-12-29 00:10:33 +01001556 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001557 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1558 return 0;
1559
Willy Tarreau86034312006-12-29 00:10:33 +01001560 if (*(args[1]) == 0) {
1561 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1562 return -1;
1563 }
1564 curproxy->fullconn = atol(args[1]);
1565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001566 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1567 if (*(args[1]) == 0) {
1568 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1569 return -1;
1570 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001571 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1572 if (err) {
1573 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1574 file, linenum, *err);
1575 return -1;
1576 }
1577 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 }
1579 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1580 if (curproxy == &defproxy) {
1581 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1582 return -1;
1583 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001584 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1585 return 0;
1586
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 if (strchr(args[1], ':') == NULL) {
1588 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1589 return -1;
1590 }
1591 curproxy->dispatch_addr = *str2sa(args[1]);
1592 }
1593 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001594 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1595 return 0;
1596
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001597 memcpy(trash, "error near 'balance'", 19);
1598 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1599 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1600 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001601 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001602 }
1603 else if (!strcmp(args[0], "server")) { /* server address */
1604 int cur_arg;
1605 char *rport;
1606 char *raddr;
1607 short realport;
1608 int do_check;
1609
1610 if (curproxy == &defproxy) {
1611 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1612 return -1;
1613 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001614 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1615 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001616
1617 if (!*args[2]) {
1618 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1619 file, linenum, args[0]);
1620 return -1;
1621 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001622
1623 err = invalid_char(args[1]);
1624 if (err) {
1625 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1626 file, linenum, *err, args[1]);
1627 return -1;
1628 }
1629
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1631 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1632 return -1;
1633 }
1634
1635 /* the servers are linked backwards first */
1636 newsrv->next = curproxy->srv;
1637 curproxy->srv = newsrv;
1638 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001639 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640
1641 LIST_INIT(&newsrv->pendconns);
1642 do_check = 0;
1643 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001644 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001645 newsrv->id = strdup(args[1]);
1646
1647 /* several ways to check the port component :
1648 * - IP => port=+0, relative
1649 * - IP: => port=+0, relative
1650 * - IP:N => port=N, absolute
1651 * - IP:+N => port=+N, relative
1652 * - IP:-N => port=-N, relative
1653 */
1654 raddr = strdup(args[2]);
1655 rport = strchr(raddr, ':');
1656 if (rport) {
1657 *rport++ = 0;
1658 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001659 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001660 newsrv->state |= SRV_MAPPORTS;
1661 } else {
1662 realport = 0;
1663 newsrv->state |= SRV_MAPPORTS;
1664 }
1665
1666 newsrv->addr = *str2sa(raddr);
1667 newsrv->addr.sin_port = htons(realport);
1668 free(raddr);
1669
1670 newsrv->curfd = -1; /* no health-check in progress */
1671 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001672 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1673 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001674 newsrv->rise = DEF_RISETIME;
1675 newsrv->fall = DEF_FALLTIME;
1676 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001677 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001678 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001679 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001680
Willy Tarreaubaaee002006-06-26 02:48:02 +02001681 cur_arg = 3;
1682 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001683 if (!strcmp(args[cur_arg], "id")) {
1684 struct server *target;
1685
1686 if (!*args[cur_arg + 1]) {
1687 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1688 file, linenum, args[cur_arg]);
1689 return -1;
1690 }
1691
1692 newsrv->puid = atol(args[cur_arg + 1]);
1693
1694 if (newsrv->puid< 1001) {
1695 Alert("parsing [%s:%d]: custom id has to be > 1000",
1696 file, linenum);
1697 return -1;
1698 }
1699
1700 for (target = proxy->srv; target; target = target->next)
1701 if (newsrv != target && newsrv->puid == target->puid) {
1702 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1703 file, linenum, newsrv->id, target->id);
1704 return -1;
1705 }
1706 cur_arg += 2;
1707 }
1708 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001709 newsrv->cookie = strdup(args[cur_arg + 1]);
1710 newsrv->cklen = strlen(args[cur_arg + 1]);
1711 cur_arg += 2;
1712 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001713 else if (!strcmp(args[cur_arg], "redir")) {
1714 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1715 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1716 cur_arg += 2;
1717 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001718 else if (!strcmp(args[cur_arg], "rise")) {
1719 newsrv->rise = atol(args[cur_arg + 1]);
1720 newsrv->health = newsrv->rise;
1721 cur_arg += 2;
1722 }
1723 else if (!strcmp(args[cur_arg], "fall")) {
1724 newsrv->fall = atol(args[cur_arg + 1]);
1725 cur_arg += 2;
1726 }
1727 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001728 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1729 if (err) {
1730 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1731 file, linenum, *err, newsrv->id);
1732 return -1;
1733 }
1734 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001735 cur_arg += 2;
1736 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001737 else if (!strcmp(args[cur_arg], "fastinter")) {
1738 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1739 if (err) {
1740 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1741 file, linenum, *err, newsrv->id);
1742 return -1;
1743 }
1744 newsrv->fastinter = val;
1745 cur_arg += 2;
1746 }
1747 else if (!strcmp(args[cur_arg], "downinter")) {
1748 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1749 if (err) {
1750 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1751 file, linenum, *err, newsrv->id);
1752 return -1;
1753 }
1754 newsrv->downinter = val;
1755 cur_arg += 2;
1756 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001757 else if (!strcmp(args[cur_arg], "addr")) {
1758 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001759 cur_arg += 2;
1760 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001761 else if (!strcmp(args[cur_arg], "port")) {
1762 newsrv->check_port = atol(args[cur_arg + 1]);
1763 cur_arg += 2;
1764 }
1765 else if (!strcmp(args[cur_arg], "backup")) {
1766 newsrv->state |= SRV_BACKUP;
1767 cur_arg ++;
1768 }
1769 else if (!strcmp(args[cur_arg], "weight")) {
1770 int w;
1771 w = atol(args[cur_arg + 1]);
1772 if (w < 1 || w > 256) {
1773 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1774 file, linenum, newsrv->id, w);
1775 return -1;
1776 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001777 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 cur_arg += 2;
1779 }
1780 else if (!strcmp(args[cur_arg], "minconn")) {
1781 newsrv->minconn = atol(args[cur_arg + 1]);
1782 cur_arg += 2;
1783 }
1784 else if (!strcmp(args[cur_arg], "maxconn")) {
1785 newsrv->maxconn = atol(args[cur_arg + 1]);
1786 cur_arg += 2;
1787 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001788 else if (!strcmp(args[cur_arg], "maxqueue")) {
1789 newsrv->maxqueue = atol(args[cur_arg + 1]);
1790 cur_arg += 2;
1791 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001792 else if (!strcmp(args[cur_arg], "slowstart")) {
1793 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001794 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001795 if (err) {
1796 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1797 file, linenum, *err, newsrv->id);
1798 return -1;
1799 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001800 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001801 cur_arg += 2;
1802 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001803 else if (!strcmp(args[cur_arg], "track")) {
1804
1805 if (!*args[cur_arg + 1]) {
1806 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1807 file, linenum);
1808 return -1;
1809 }
1810
1811 newsrv->trackit = strdup(args[cur_arg + 1]);
1812
1813 cur_arg += 2;
1814 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001815 else if (!strcmp(args[cur_arg], "check")) {
1816 global.maxsock++;
1817 do_check = 1;
1818 cur_arg += 1;
1819 }
1820 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1821 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001822#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001823 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1824 file, linenum, "source", "usesrc");
1825#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001826 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1827 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001828#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001829 return -1;
1830 }
1831 newsrv->state |= SRV_BIND_SRC;
1832 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1833 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001834 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001835#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1836#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001837 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001838 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1839 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001840 return -1;
1841 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001842#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001843 if (!*args[cur_arg + 1]) {
1844 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1845 file, linenum, "usesrc");
1846 return -1;
1847 }
1848 if (!strcmp(args[cur_arg + 1], "client")) {
1849 newsrv->state |= SRV_TPROXY_CLI;
1850 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1851 newsrv->state |= SRV_TPROXY_CIP;
1852 } else {
1853 newsrv->state |= SRV_TPROXY_ADDR;
1854 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1855 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001856 global.last_checks |= LSTCHK_NETADM;
1857#if !defined(CONFIG_HAP_LINUX_TPROXY)
1858 global.last_checks |= LSTCHK_CTTPROXY;
1859#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001860 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001861#else /* no TPROXY support */
1862 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001863 file, linenum, "usesrc");
1864 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001865#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001866 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001867 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001868 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1869 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1870 file, linenum, "usesrc", "source");
1871 return -1;
1872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001873 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001874 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 +02001875 file, linenum, newsrv->id);
1876 return -1;
1877 }
1878 }
1879
1880 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001881 if (newsrv->trackit) {
1882 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1883 file, linenum);
1884 return -1;
1885 }
1886
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001887 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1888 newsrv->check_port = newsrv->check_addr.sin_port;
1889
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1891 newsrv->check_port = realport; /* by default */
1892 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001893 /* not yet valid, because no port was set on
1894 * the server either. We'll check if we have
1895 * a known port on the first listener.
1896 */
1897 struct listener *l;
1898 l = curproxy->listen;
1899 if (l) {
1900 int port;
1901 port = (l->addr.ss_family == AF_INET6)
1902 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1903 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1904 newsrv->check_port = port;
1905 }
1906 }
1907 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001908 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1909 file, linenum, newsrv->id);
1910 return -1;
1911 }
1912 newsrv->state |= SRV_CHECKED;
1913 }
1914
1915 if (newsrv->state & SRV_BACKUP)
1916 curproxy->srv_bck++;
1917 else
1918 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001919
1920 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 }
1922 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001923 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 int facility;
1925
1926 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1927 curproxy->logfac1 = global.logfac1;
1928 curproxy->logsrv1 = global.logsrv1;
1929 curproxy->loglev1 = global.loglev1;
1930 curproxy->logfac2 = global.logfac2;
1931 curproxy->logsrv2 = global.logsrv2;
1932 curproxy->loglev2 = global.loglev2;
1933 }
1934 else if (*(args[1]) && *(args[2])) {
1935 int level;
1936
1937 facility = get_log_facility(args[2]);
1938 if (facility < 0) {
1939 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1940 exit(1);
1941 }
1942
1943 level = 7; /* max syslog level = debug */
1944 if (*(args[3])) {
1945 level = get_log_level(args[3]);
1946 if (level < 0) {
1947 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1948 exit(1);
1949 }
1950 }
1951
Robert Tsai81ae1952007-12-05 10:47:29 +01001952 if (args[1][0] == '/') {
1953 logsrv.u.addr.sa_family = AF_UNIX;
1954 logsrv.u.un = *str2sun(args[1]);
1955 } else {
1956 logsrv.u.addr.sa_family = AF_INET;
1957 logsrv.u.in = *str2sa(args[1]);
1958 if (!logsrv.u.in.sin_port) {
1959 logsrv.u.in.sin_port =
1960 htons(SYSLOG_PORT);
1961 }
1962 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963
1964 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001965 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966 curproxy->logfac1 = facility;
1967 curproxy->loglev1 = level;
1968 }
1969 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001970 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001971 curproxy->logfac2 = facility;
1972 curproxy->loglev2 = level;
1973 }
1974 else {
1975 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1976 return -1;
1977 }
1978 }
1979 else {
1980 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1981 file, linenum);
1982 return -1;
1983 }
1984 }
1985 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001986 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1987 return 0;
1988
Willy Tarreaubaaee002006-06-26 02:48:02 +02001989 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001990#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001991 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1992 file, linenum, "source", "usesrc");
1993#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1995 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001996#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001997 return -1;
1998 }
1999
2000 curproxy->source_addr = *str2sa(args[1]);
2001 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01002002 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002003#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2004#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002005 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2006 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2007 file, linenum, "usesrc");
2008 return -1;
2009 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002010#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002011 if (!*args[3]) {
2012 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2013 file, linenum, "usesrc");
2014 return -1;
2015 }
2016
2017 if (!strcmp(args[3], "client")) {
2018 curproxy->options |= PR_O_TPXY_CLI;
2019 } else if (!strcmp(args[3], "clientip")) {
2020 curproxy->options |= PR_O_TPXY_CIP;
2021 } else {
2022 curproxy->options |= PR_O_TPXY_ADDR;
2023 curproxy->tproxy_addr = *str2sa(args[3]);
2024 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002025 global.last_checks |= LSTCHK_NETADM;
2026#if !defined(CONFIG_HAP_LINUX_TPROXY)
2027 global.last_checks |= LSTCHK_CTTPROXY;
2028#endif
2029#else /* no TPROXY support */
2030 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002031 file, linenum, "usesrc");
2032 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002033#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002034 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002035 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002036 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2037 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2038 file, linenum, "usesrc", "source");
2039 return -1;
2040 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2042 regex_t *preg;
2043 if (curproxy == &defproxy) {
2044 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2045 return -1;
2046 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002047 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2048 return 0;
2049
Willy Tarreaubaaee002006-06-26 02:48:02 +02002050 if (*(args[1]) == 0 || *(args[2]) == 0) {
2051 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2052 file, linenum, args[0]);
2053 return -1;
2054 }
2055
2056 preg = calloc(1, sizeof(regex_t));
2057 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2058 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2059 return -1;
2060 }
2061
2062 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2063 if (err) {
2064 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2065 file, linenum, *err);
2066 return -1;
2067 }
2068 }
2069 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2070 regex_t *preg;
2071 if (curproxy == &defproxy) {
2072 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2073 return -1;
2074 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002075 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2076 return 0;
2077
Willy Tarreaubaaee002006-06-26 02:48:02 +02002078 if (*(args[1]) == 0) {
2079 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2080 return -1;
2081 }
2082
2083 preg = calloc(1, sizeof(regex_t));
2084 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2085 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2086 return -1;
2087 }
2088
2089 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2090 }
2091 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2092 regex_t *preg;
2093 if (curproxy == &defproxy) {
2094 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2095 return -1;
2096 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002097 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2098 return 0;
2099
Willy Tarreaubaaee002006-06-26 02:48:02 +02002100 if (*(args[1]) == 0) {
2101 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2102 return -1;
2103 }
2104
2105 preg = calloc(1, sizeof(regex_t));
2106 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2107 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2108 return -1;
2109 }
2110
2111 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2112 }
2113 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2114 regex_t *preg;
2115 if (curproxy == &defproxy) {
2116 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2117 return -1;
2118 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002119 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2120 return 0;
2121
Willy Tarreaubaaee002006-06-26 02:48:02 +02002122 if (*(args[1]) == 0) {
2123 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2124 return -1;
2125 }
2126
2127 preg = calloc(1, sizeof(regex_t));
2128 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2129 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2130 return -1;
2131 }
2132
2133 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2134 }
2135 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2136 regex_t *preg;
2137 if (curproxy == &defproxy) {
2138 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2139 return -1;
2140 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002141 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2142 return 0;
2143
Willy Tarreaubaaee002006-06-26 02:48:02 +02002144 if (*(args[1]) == 0) {
2145 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2146 return -1;
2147 }
2148
2149 preg = calloc(1, sizeof(regex_t));
2150 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2151 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2152 return -1;
2153 }
2154
2155 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2156 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002157 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2158 regex_t *preg;
2159 if (curproxy == &defproxy) {
2160 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2161 return -1;
2162 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002163 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2164 return 0;
2165
Willy Tarreaub8750a82006-09-03 09:56:00 +02002166 if (*(args[1]) == 0) {
2167 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2168 return -1;
2169 }
2170
2171 preg = calloc(1, sizeof(regex_t));
2172 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2173 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2174 return -1;
2175 }
2176
2177 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2178 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002179 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2180 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002181 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002182 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2183 return -1;
2184 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002185 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2186 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002187
Willy Tarreau977b8e42006-12-29 14:19:17 +01002188 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002189 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2190 file, linenum, args[0]);
2191 return -1;
2192 }
2193
2194 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002195 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002196 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2197 }
2198
2199 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2200 }
2201 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2202 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002203 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002204 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2205 return -1;
2206 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002207 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2208 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002209
Willy Tarreau977b8e42006-12-29 14:19:17 +01002210 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002211 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2212 file, linenum, args[0]);
2213 return -1;
2214 }
2215
2216 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002217 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002218 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2219 }
2220
2221 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002223 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2224 regex_t *preg;
2225 if (curproxy == &defproxy) {
2226 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2227 return -1;
2228 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002229 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2230 return 0;
2231
Willy Tarreaubaaee002006-06-26 02:48:02 +02002232 if (*(args[1]) == 0 || *(args[2]) == 0) {
2233 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2234 file, linenum, args[0]);
2235 return -1;
2236 }
2237
2238 preg = calloc(1, sizeof(regex_t));
2239 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2240 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2241 return -1;
2242 }
2243
2244 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2245 if (err) {
2246 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2247 file, linenum, *err);
2248 return -1;
2249 }
2250 }
2251 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2252 regex_t *preg;
2253 if (curproxy == &defproxy) {
2254 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2255 return -1;
2256 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002257 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2258 return 0;
2259
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 if (*(args[1]) == 0) {
2261 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2262 return -1;
2263 }
2264
2265 preg = calloc(1, sizeof(regex_t));
2266 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2267 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2268 return -1;
2269 }
2270
2271 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2272 }
2273 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2274 regex_t *preg;
2275 if (curproxy == &defproxy) {
2276 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2277 return -1;
2278 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002279 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2280 return 0;
2281
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 if (*(args[1]) == 0) {
2283 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2284 return -1;
2285 }
2286
2287 preg = calloc(1, sizeof(regex_t));
2288 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2289 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2290 return -1;
2291 }
2292
2293 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2294 }
2295 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2296 regex_t *preg;
2297 if (curproxy == &defproxy) {
2298 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2299 return -1;
2300 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002301 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2302 return 0;
2303
Willy Tarreaubaaee002006-06-26 02:48:02 +02002304 if (*(args[1]) == 0) {
2305 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2306 return -1;
2307 }
2308
2309 preg = calloc(1, sizeof(regex_t));
2310 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2311 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2312 return -1;
2313 }
2314
2315 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2316 }
2317 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2318 regex_t *preg;
2319 if (curproxy == &defproxy) {
2320 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2321 return -1;
2322 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002323 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2324 return 0;
2325
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326 if (*(args[1]) == 0) {
2327 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2328 return -1;
2329 }
2330
2331 preg = calloc(1, sizeof(regex_t));
2332 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2333 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2334 return -1;
2335 }
2336
2337 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2338 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002339 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2340 regex_t *preg;
2341 if (curproxy == &defproxy) {
2342 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2343 return -1;
2344 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002345 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2346 return 0;
2347
Willy Tarreaub8750a82006-09-03 09:56:00 +02002348 if (*(args[1]) == 0) {
2349 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2350 return -1;
2351 }
2352
2353 preg = calloc(1, sizeof(regex_t));
2354 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2355 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2356 return -1;
2357 }
2358
2359 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2360 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2362 if (curproxy == &defproxy) {
2363 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2364 return -1;
2365 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002366 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2367 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368
2369 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2370 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2371 return 0;
2372 }
2373
2374 if (*(args[1]) == 0) {
2375 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2376 return -1;
2377 }
2378
2379 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2380 }
2381 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2382 regex_t *preg;
2383
2384 if (*(args[1]) == 0 || *(args[2]) == 0) {
2385 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2386 file, linenum, args[0]);
2387 return -1;
2388 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002389 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2390 return 0;
2391
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 preg = calloc(1, sizeof(regex_t));
2393 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2394 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2395 return -1;
2396 }
2397
2398 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2399 if (err) {
2400 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2401 file, linenum, *err);
2402 return -1;
2403 }
2404 }
2405 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2406 regex_t *preg;
2407 if (curproxy == &defproxy) {
2408 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2409 return -1;
2410 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002411 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2412 return 0;
2413
Willy Tarreaubaaee002006-06-26 02:48:02 +02002414 if (*(args[1]) == 0) {
2415 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2416 return -1;
2417 }
2418
2419 preg = calloc(1, sizeof(regex_t));
2420 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2421 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2422 return -1;
2423 }
2424
2425 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2426 if (err) {
2427 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2428 file, linenum, *err);
2429 return -1;
2430 }
2431 }
2432 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2433 regex_t *preg;
2434 if (curproxy == &defproxy) {
2435 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2436 return -1;
2437 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002438 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2439 return 0;
2440
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 if (*(args[1]) == 0) {
2442 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2443 return -1;
2444 }
2445
2446 preg = calloc(1, sizeof(regex_t));
2447 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2448 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2449 return -1;
2450 }
2451
2452 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2453 if (err) {
2454 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2455 file, linenum, *err);
2456 return -1;
2457 }
2458 }
2459 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2460 regex_t *preg;
2461 if (curproxy == &defproxy) {
2462 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2463 return -1;
2464 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002465 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2466 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467
2468 if (*(args[1]) == 0 || *(args[2]) == 0) {
2469 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2470 file, linenum, args[0]);
2471 return -1;
2472 }
2473
2474 preg = calloc(1, sizeof(regex_t));
2475 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2476 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2477 return -1;
2478 }
2479
2480 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2481 if (err) {
2482 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2483 file, linenum, *err);
2484 return -1;
2485 }
2486 }
2487 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2488 regex_t *preg;
2489 if (curproxy == &defproxy) {
2490 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2491 return -1;
2492 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002493 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2494 return 0;
2495
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 if (*(args[1]) == 0) {
2497 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2498 return -1;
2499 }
2500
2501 preg = calloc(1, sizeof(regex_t));
2502 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2503 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2504 return -1;
2505 }
2506
2507 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2508 if (err) {
2509 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2510 file, linenum, *err);
2511 return -1;
2512 }
2513 }
2514 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2515 regex_t *preg;
2516 if (curproxy == &defproxy) {
2517 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2518 return -1;
2519 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002520 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2521 return 0;
2522
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 if (*(args[1]) == 0) {
2524 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2525 return -1;
2526 }
2527
2528 preg = calloc(1, sizeof(regex_t));
2529 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2530 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2531 return -1;
2532 }
2533
2534 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2535 if (err) {
2536 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2537 file, linenum, *err);
2538 return -1;
2539 }
2540 }
2541 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2542 if (curproxy == &defproxy) {
2543 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2544 return -1;
2545 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002546 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2547 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548
2549 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2550 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2551 return 0;
2552 }
2553
2554 if (*(args[1]) == 0) {
2555 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2556 return -1;
2557 }
2558
2559 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2560 }
2561 else if (!strcmp(args[0], "errorloc") ||
2562 !strcmp(args[0], "errorloc302") ||
2563 !strcmp(args[0], "errorloc303")) { /* error location */
2564 int errnum, errlen;
2565 char *err;
2566
Willy Tarreau977b8e42006-12-29 14:19:17 +01002567 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2568 return 0;
2569
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002571 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 return -1;
2573 }
2574
2575 errnum = atol(args[1]);
2576 if (!strcmp(args[0], "errorloc303")) {
2577 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2578 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2579 } else {
2580 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2581 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2582 }
2583
Willy Tarreau0f772532006-12-23 20:51:41 +01002584 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2585 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002586 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002587 curproxy->errmsg[rc].str = err;
2588 curproxy->errmsg[rc].len = errlen;
2589 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002592
2593 if (rc >= HTTP_ERR_SIZE) {
2594 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2595 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 free(err);
2597 }
2598 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002599 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2600 int errnum, errlen, fd;
2601 char *err;
2602 struct stat stat;
2603
2604 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2605 return 0;
2606
2607 if (*(args[2]) == 0) {
2608 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2609 return -1;
2610 }
2611
2612 fd = open(args[2], O_RDONLY);
2613 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2614 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2615 file, linenum, args[2], args[1]);
2616 if (fd >= 0)
2617 close(fd);
2618 return -1;
2619 }
2620
2621 if (stat.st_size <= BUFSIZE) {
2622 errlen = stat.st_size;
2623 } else {
2624 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2625 file, linenum, args[2], BUFSIZE);
2626 errlen = BUFSIZE;
2627 }
2628
2629 err = malloc(errlen); /* malloc() must succeed during parsing */
2630 errnum = read(fd, err, errlen);
2631 if (errnum != errlen) {
2632 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2633 file, linenum, args[2], args[1]);
2634 close(fd);
2635 free(err);
2636 return -1;
2637 }
2638 close(fd);
2639
2640 errnum = atol(args[1]);
2641 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2642 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002643 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002644 curproxy->errmsg[rc].str = err;
2645 curproxy->errmsg[rc].len = errlen;
2646 break;
2647 }
2648 }
2649
2650 if (rc >= HTTP_ERR_SIZE) {
2651 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2652 file, linenum, errnum);
2653 free(err);
2654 }
2655 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002656 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002657 struct cfg_kw_list *kwl;
2658 int index;
2659
2660 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2661 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2662 if (kwl->kw[index].section != CFG_LISTEN)
2663 continue;
2664 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2665 /* prepare error message just in case */
2666 snprintf(trash, sizeof(trash),
2667 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002668 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2669 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002670 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2671 return -1;
2672 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002673 else if (rc > 0) {
2674 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2675 return 0;
2676 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002677 return 0;
2678 }
2679 }
2680 }
2681
Willy Tarreau6daf3432008-01-22 16:44:08 +01002682 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002683 return -1;
2684 }
2685 return 0;
2686}
2687
2688
2689/*
2690 * This function reads and parses the configuration file given in the argument.
2691 * returns 0 if OK, -1 if error.
2692 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002693int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002695 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696 FILE *f;
2697 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 int confsect = CFG_NONE;
2700
2701 struct proxy *curproxy = NULL;
2702 struct server *newsrv = NULL;
2703
2704 if ((f=fopen(file,"r")) == NULL)
2705 return -1;
2706
2707 init_default_instance();
2708
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002709 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002710 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002711 char *end;
2712 char *args[MAX_LINE_ARGS + 1];
2713 char *line = thisline;
2714
Willy Tarreaubaaee002006-06-26 02:48:02 +02002715 linenum++;
2716
2717 end = line + strlen(line);
2718
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002719 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2720 /* Check if we reached the limit and the last char is not \n.
2721 * Watch out for the last line without the terminating '\n'!
2722 */
2723 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2724 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002725 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002726 }
2727
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002729 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002730 line++;
2731
2732 arg = 0;
2733 args[arg] = line;
2734
2735 while (*line && arg < MAX_LINE_ARGS) {
2736 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2737 * C equivalent value. Other combinations left unchanged (eg: \1).
2738 */
2739 if (*line == '\\') {
2740 int skip = 0;
2741 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2742 *line = line[1];
2743 skip = 1;
2744 }
2745 else if (line[1] == 'r') {
2746 *line = '\r';
2747 skip = 1;
2748 }
2749 else if (line[1] == 'n') {
2750 *line = '\n';
2751 skip = 1;
2752 }
2753 else if (line[1] == 't') {
2754 *line = '\t';
2755 skip = 1;
2756 }
2757 else if (line[1] == 'x') {
2758 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2759 unsigned char hex1, hex2;
2760 hex1 = toupper(line[2]) - '0';
2761 hex2 = toupper(line[3]) - '0';
2762 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2763 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2764 *line = (hex1<<4) + hex2;
2765 skip = 3;
2766 }
2767 else {
2768 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002769 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 }
2771 }
2772 if (skip) {
2773 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2774 end -= skip;
2775 }
2776 line++;
2777 }
2778 else if (*line == '#' || *line == '\n' || *line == '\r') {
2779 /* end of string, end of loop */
2780 *line = 0;
2781 break;
2782 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002783 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002784 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002785 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002786 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002787 line++;
2788 args[++arg] = line;
2789 }
2790 else {
2791 line++;
2792 }
2793 }
2794
2795 /* empty line */
2796 if (!**args)
2797 continue;
2798
Willy Tarreau540abe42007-05-02 20:50:16 +02002799 /* zero out remaining args and ensure that at least one entry
2800 * is zeroed out.
2801 */
2802 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002803 args[arg] = line;
2804 }
2805
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002806 if (!strcmp(args[0], "no")) {
2807 inv = 1;
2808 for (arg=0; *args[arg+1]; arg++)
2809 args[arg] = args[arg+1]; // shift args after inversion
2810 }
2811
2812 if (inv && strcmp(args[0], "option")) {
2813 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002814 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002815 }
2816
Willy Tarreau977b8e42006-12-29 14:19:17 +01002817 if (!strcmp(args[0], "listen") ||
2818 !strcmp(args[0], "frontend") ||
2819 !strcmp(args[0], "backend") ||
2820 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002821 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002822 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002823 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002824 cursection = strdup(args[0]);
2825 }
2826 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002827 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002828 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002829 cursection = strdup(args[0]);
2830 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002831 /* else it's a section keyword */
2832
2833 switch (confsect) {
2834 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002835 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002836 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 break;
2838 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002839 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002840 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841 break;
2842 default:
2843 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002844 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002845 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002846 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002847 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002848 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849 fclose(f);
2850
2851 /*
2852 * Now, check for the integrity of all that we have collected.
2853 */
2854
2855 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002856 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002857
2858 if ((curproxy = proxy) == NULL) {
2859 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2860 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002861 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002862 }
2863
2864 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002865 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002866 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002867
Willy Tarreaubaaee002006-06-26 02:48:02 +02002868 if (curproxy->state == PR_STSTOPPED) {
2869 curproxy = curproxy->next;
2870 continue;
2871 }
2872
Willy Tarreau977b8e42006-12-29 14:19:17 +01002873 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2874 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 +01002875 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002876 cfgerr++;
2877 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002878 else if (curproxy->cap & PR_CAP_BE &&
2879 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002880 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002881 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002882 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2883 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 +01002884 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885 cfgerr++;
2886 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002887
Willy Tarreau31682232007-11-29 15:38:04 +01002888 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002889 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002890 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002891 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892 cfgerr++;
2893 }
2894#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2895 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002896 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002897 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002898 cfgerr++;
2899 }
2900#endif
2901 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002902 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002903 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 }
2905 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002906
2907 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002908 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002909 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002910 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002911 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002913 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002914 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 }
2916 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002917 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002918 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002920 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002921 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002922 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002923 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002924 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002925 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2926 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002927
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002928 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002929 file, proxy_type_str(curproxy), curproxy->id);
2930 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002931 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002932
2933 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2934 if ((newsrv = curproxy->srv) != NULL) {
2935 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2936 file, proxy_type_str(curproxy), curproxy->id);
2937 }
2938 }
2939
2940 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002941 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2942 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2943 file, curproxy->id);
2944 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002945 }
2946 }
2947
Willy Tarreau82936582007-11-30 15:20:09 +01002948 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2949 curproxy->options &= ~PR_O_DISABLE404;
2950 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2951 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2952 }
2953
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002954 /* if a default backend was specified, let's find it */
2955 if (curproxy->defbe.name) {
2956 struct proxy *target;
2957
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002958 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2959 if (!target) {
2960 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2961 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002962 cfgerr++;
2963 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002964 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2965 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002966 } else {
2967 free(curproxy->defbe.name);
2968 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969 }
2970 }
2971
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002972 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002973 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2974 /* map jump target for ACT_SETBE in req_rep chain */
2975 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002976 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002977 struct proxy *target;
2978
Willy Tarreaua496b602006-12-17 23:15:24 +01002979 if (exp->action != ACT_SETBE)
2980 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002981
2982 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2983 if (!target) {
2984 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2985 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002986 cfgerr++;
2987 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002988 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2989 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002990 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002991 } else {
2992 free((void *)exp->replace);
2993 exp->replace = (const char *)target;
2994 }
2995 }
2996 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002997
2998 /* find the target proxy for 'use_backend' rules */
2999 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003000 struct proxy *target;
3001
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003002 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003003
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003004 if (!target) {
3005 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3006 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003007 cfgerr++;
3008 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003009 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3010 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003011 cfgerr++;
3012 } else {
3013 free((void *)rule->be.name);
3014 rule->be.backend = target;
3015 }
3016 }
3017
Willy Tarreau2738a142006-07-08 17:28:09 +02003018 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003019 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003020 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003021 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003022 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003023 " | While not properly invalid, you will certainly encounter various problems\n"
3024 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003025 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003026 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003027 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003028
Willy Tarreau1fa31262007-12-03 00:36:16 +01003029 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3030 * We must still support older configurations, so let's find out whether those
3031 * parameters have been set or must be copied from contimeouts.
3032 */
3033 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003034 if (!curproxy->timeout.tarpit ||
3035 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003036 /* tarpit timeout not set. We search in the following order:
3037 * default.tarpit, curr.connect, default.connect.
3038 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003039 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003040 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003041 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003042 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003043 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003044 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003045 }
3046 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003047 (!curproxy->timeout.queue ||
3048 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003049 /* queue timeout not set. We search in the following order:
3050 * default.queue, curr.connect, default.connect.
3051 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003052 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003053 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003054 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003055 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003056 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003057 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003058 }
3059 }
3060
Willy Tarreauf3c69202006-07-09 16:42:34 +02003061 if (curproxy->options & PR_O_SSL3_CHK) {
3062 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3063 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3064 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3065 }
3066
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003067 /* The small pools required for the capture lists */
3068 if (curproxy->nb_req_cap)
3069 curproxy->req_cap_pool = create_pool("ptrcap",
3070 curproxy->nb_req_cap * sizeof(char *),
3071 MEM_F_SHARED);
3072 if (curproxy->nb_rsp_cap)
3073 curproxy->rsp_cap_pool = create_pool("ptrcap",
3074 curproxy->nb_rsp_cap * sizeof(char *),
3075 MEM_F_SHARED);
3076
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003077 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3078 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3079 MEM_F_SHARED);
3080
Willy Tarreau86034312006-12-29 00:10:33 +01003081 /* for backwards compatibility with "listen" instances, if
3082 * fullconn is not set but maxconn is set, then maxconn
3083 * is used.
3084 */
3085 if (!curproxy->fullconn)
3086 curproxy->fullconn = curproxy->maxconn;
3087
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088 /* first, we will invert the servers list order */
3089 newsrv = NULL;
3090 while (curproxy->srv) {
3091 struct server *next;
3092
3093 next = curproxy->srv->next;
3094 curproxy->srv->next = newsrv;
3095 newsrv = curproxy->srv;
3096 if (!next)
3097 break;
3098 curproxy->srv = next;
3099 }
3100
Willy Tarreau20697042007-11-15 23:26:18 +01003101 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003102 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103
Willy Tarreaub625a082007-11-26 01:15:43 +01003104 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003105 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003106 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003107 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3108 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003109 else
3110 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003111
3112 if (curproxy->options & PR_O_LOGASAP)
3113 curproxy->to_log &= ~LW_BYTES;
3114
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003116 * ensure that we're not cross-dressing a TCP server into HTTP.
3117 */
3118 newsrv = curproxy->srv;
3119 while (newsrv != NULL) {
3120 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3121 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3122 file, proxy_type_str(curproxy), curproxy->id, linenum);
3123 goto err;
3124 }
3125 newsrv = newsrv->next;
3126 }
3127
3128 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 * If this server supports a maxconn parameter, it needs a dedicated
3130 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003131 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 */
3133 newsrv = curproxy->srv;
3134 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003135 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 /* Only 'minconn' was specified, or it was higher than or equal
3137 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3138 * this will avoid further useless expensive computations.
3139 */
3140 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003141 } else if (newsrv->maxconn && !newsrv->minconn) {
3142 /* minconn was not specified, so we set it to maxconn */
3143 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003144 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3145 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003146 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003147 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 }
3149
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003150 if (newsrv->trackit) {
3151 struct proxy *px;
3152 struct server *srv;
3153 char *pname, *sname;
3154
3155 pname = newsrv->trackit;
3156 sname = strrchr(pname, '/');
3157
3158 if (sname)
3159 *sname++ = '\0';
3160 else {
3161 sname = pname;
3162 pname = NULL;
3163 }
3164
3165 if (pname) {
3166 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3167 if (!px) {
3168 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3169 file, proxy_type_str(curproxy), curproxy->id,
3170 newsrv->id, pname);
3171 return -1;
3172 }
3173 } else
3174 px = curproxy;
3175
3176 srv = findserver(px, sname);
3177 if (!srv) {
3178 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3179 file, proxy_type_str(curproxy), curproxy->id,
3180 newsrv->id, sname);
3181 return -1;
3182 }
3183
3184 if (!(srv->state & SRV_CHECKED)) {
3185 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3186 "tracing as it does not have checks enabled.\n",
3187 file, proxy_type_str(curproxy), curproxy->id,
3188 newsrv->id, px->id, srv->id);
3189 return -1;
3190 }
3191
3192 if (curproxy != px &&
3193 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3194 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3195 "tracing: disable-on-404 option inconsistency.\n",
3196 file, proxy_type_str(curproxy), curproxy->id,
3197 newsrv->id, px->id, srv->id);
3198 return -1;
3199 }
3200
3201 newsrv->tracked = srv;
3202 newsrv->tracknext = srv->tracknext;
3203 srv->tracknext = newsrv;
3204
3205 free(newsrv->trackit);
3206 }
3207
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 newsrv = newsrv->next;
3209 }
3210
Willy Tarreaue6b98942007-10-29 01:09:36 +01003211 /* adjust this proxy's listeners */
3212 listener = curproxy->listen;
3213 while (listener) {
3214 if (curproxy->options & PR_O_TCP_NOLING)
3215 listener->options |= LI_O_NOLINGER;
3216 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003217 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003218 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003219 listener->accept = event_accept;
3220 listener->private = curproxy;
3221
3222 listener = listener->next;
3223 }
3224
Willy Tarreaubaaee002006-06-26 02:48:02 +02003225 curproxy = curproxy->next;
3226 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003227
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 if (cfgerr > 0) {
3229 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003230 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003231 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003232
3233 /*
3234 * Recount currently required checks.
3235 */
3236
3237 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3238 int optnum;
3239
3240 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3241 if (!(curproxy->options & cfg_opts[optnum].val))
3242 continue;
3243
3244 global.last_checks |= cfg_opts[optnum].checks;
3245 }
3246 }
3247
Willy Tarreaua534fea2008-08-03 12:19:50 +02003248 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003249 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003250 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003251
3252 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003253 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003254 cursection = NULL;
3255 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256}
3257
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003258/*
3259 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3260 * parsing sessions.
3261 */
3262void cfg_register_keywords(struct cfg_kw_list *kwl)
3263{
3264 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3265}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003267/*
3268 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3269 */
3270void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3271{
3272 LIST_DEL(&kwl->list);
3273 LIST_INIT(&kwl->list);
3274}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275
3276/*
3277 * Local variables:
3278 * c-indent-level: 8
3279 * c-basic-offset: 8
3280 * End:
3281 */