blob: 78783c0477f449d30e52e10e1a0c5ee4d74b9611 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau7c669d72008-06-20 15:04:11 +02004 * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
27#include <common/config.h>
28#include <common/memory.h>
29#include <common/standard.h>
30#include <common/time.h>
31#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020032
33#include <types/capture.h>
34#include <types/global.h>
35#include <types/polling.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036
Willy Tarreaueb0c6142007-05-07 00:53:22 +020037#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010039#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020041#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010044#include <proto/protocols.h>
45#include <proto/proto_tcp.h>
46#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010047#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <proto/server.h>
49#include <proto/task.h>
50
51
Willy Tarreauf3c69202006-07-09 16:42:34 +020052/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
53 * ssl-hello-chk option to ensure that the remote server speaks SSL.
54 *
55 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
56 */
57const char sslv3_client_hello_pkt[] = {
58 "\x16" /* ContentType : 0x16 = Hanshake */
59 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
60 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
61 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
62 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
63 "\x03\x00" /* Hello Version : 0x0300 = v3 */
64 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
65 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
66 "\x00" /* Session ID length : empty (no session ID) */
67 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
68 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
69 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
70 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
71 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
72 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
73 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
74 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
75 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
76 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
77 "\x00\x38" "\x00\x39" "\x00\x3A"
78 "\x01" /* Compression Length : 0x01 = 1 byte for types */
79 "\x00" /* Compression Type : 0x00 = NULL compression */
80};
81
Willy Tarreau13943ab2006-12-31 00:24:10 +010082/* some of the most common options which are also the easiest to handle */
83static const struct {
84 const char *name;
85 unsigned int val;
86 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010087 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010088} cfg_opts[] =
89{
Willy Tarreau4fee4e92007-01-06 21:09:17 +010090 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010091 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010092 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010094 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
95 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
96 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
97 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
98 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
99 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
100 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
101 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100102 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100103 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
104 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100105#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100106 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
107#endif
108#ifdef TPROXY
109 { "transparent", PR_O_TRANSP, PR_CAP_FE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100110#endif
111
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100112 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113};
114
Willy Tarreaubaaee002006-06-26 02:48:02 +0200115
Willy Tarreau6daf3432008-01-22 16:44:08 +0100116static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200117static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
118int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
119int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
120
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200121/* List head of all known configuration keywords */
122static struct cfg_kw_list cfg_keywords = {
123 .list = LIST_HEAD_INIT(cfg_keywords.list)
124};
125
Willy Tarreaubaaee002006-06-26 02:48:02 +0200126/*
127 * converts <str> to a list of listeners which are dynamically allocated.
128 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
129 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
130 * - <port> is a numerical port from 1 to 65535 ;
131 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
132 * This can be repeated as many times as necessary, separated by a coma.
133 * The <tail> argument is a pointer to a current list which should be appended
134 * to the tail of the new list. The pointer to the new list is returned.
135 */
136static struct listener *str2listener(char *str, struct listener *tail)
137{
138 struct listener *l;
139 char *c, *next, *range, *dupstr;
140 int port, end;
141
142 next = dupstr = strdup(str);
143
144 while (next && *next) {
145 struct sockaddr_storage ss;
146
147 str = next;
148 /* 1) look for the end of the first address */
149 if ((next = strrchr(str, ',')) != NULL) {
150 *next++ = 0;
151 }
152
153 /* 2) look for the addr/port delimiter, it's the last colon. */
154 if ((range = strrchr(str, ':')) == NULL) {
155 Alert("Missing port number: '%s'\n", str);
156 goto fail;
157 }
158
159 *range++ = 0;
160
161 if (strrchr(str, ':') != NULL) {
162 /* IPv6 address contains ':' */
163 memset(&ss, 0, sizeof(ss));
164 ss.ss_family = AF_INET6;
165
166 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
167 Alert("Invalid server address: '%s'\n", str);
168 goto fail;
169 }
170 }
171 else {
172 memset(&ss, 0, sizeof(ss));
173 ss.ss_family = AF_INET;
174
175 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
176 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
177 }
178 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
179 struct hostent *he;
180
181 if ((he = gethostbyname(str)) == NULL) {
182 Alert("Invalid server name: '%s'\n", str);
183 goto fail;
184 }
185 else
186 ((struct sockaddr_in *)&ss)->sin_addr =
187 *(struct in_addr *) *(he->h_addr_list);
188 }
189 }
190
191 /* 3) look for the port-end delimiter */
192 if ((c = strchr(range, '-')) != NULL) {
193 *c++ = 0;
194 end = atol(c);
195 }
196 else {
197 end = atol(range);
198 }
199
200 port = atol(range);
201
202 if (port < 1 || port > 65535) {
203 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
204 goto fail;
205 }
206
207 if (end < 1 || end > 65535) {
208 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
209 goto fail;
210 }
211
212 for (; port <= end; port++) {
213 l = (struct listener *)calloc(1, sizeof(struct listener));
214 l->next = tail;
215 tail = l;
216
217 l->fd = -1;
218 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100219 l->state = LI_INIT;
220
221 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100223 tcpv6_add_listener(l);
224 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100226 tcpv4_add_listener(l);
227 }
228 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229 } /* end for(port) */
230 } /* end while(next) */
231 free(dupstr);
232 return tail;
233 fail:
234 free(dupstr);
235 return NULL;
236}
237
Willy Tarreau977b8e42006-12-29 14:19:17 +0100238/*
239 * Sends a warning if proxy <proxy> does not have at least one of the
240 * capabilities in <cap>. An optionnal <hint> may be added at the end
241 * of the warning to help the user. Returns 1 if a warning was emitted
242 * or 0 if the condition is valid.
243 */
244int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
245{
246 char *msg;
247
248 switch (cap) {
249 case PR_CAP_BE: msg = "no backend"; break;
250 case PR_CAP_FE: msg = "no frontend"; break;
251 case PR_CAP_RS: msg = "no ruleset"; break;
252 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
253 default: msg = "not enough"; break;
254 }
255
256 if (!(proxy->cap & cap)) {
257 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100258 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100259 return 1;
260 }
261 return 0;
262}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
264/*
265 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
266 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100267int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268{
269
270 if (!strcmp(args[0], "global")) { /* new section */
271 /* no option, nothing special to do */
272 return 0;
273 }
274 else if (!strcmp(args[0], "daemon")) {
275 global.mode |= MODE_DAEMON;
276 }
277 else if (!strcmp(args[0], "debug")) {
278 global.mode |= MODE_DEBUG;
279 }
280 else if (!strcmp(args[0], "noepoll")) {
281 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
282 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200283 else if (!strcmp(args[0], "nosepoll")) {
284 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
285 }
286 else if (!strcmp(args[0], "nokqueue")) {
287 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 else if (!strcmp(args[0], "nopoll")) {
290 cfg_polling_mechanism &= ~POLL_USE_POLL;
291 }
292 else if (!strcmp(args[0], "quiet")) {
293 global.mode |= MODE_QUIET;
294 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200295 else if (!strcmp(args[0], "tune.maxpollevents")) {
296 if (global.tune.maxpollevents != 0) {
297 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
298 return 0;
299 }
300 if (*(args[1]) == 0) {
301 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
302 return -1;
303 }
304 global.tune.maxpollevents = atol(args[1]);
305 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100306 else if (!strcmp(args[0], "tune.maxaccept")) {
307 if (global.tune.maxaccept != 0) {
308 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
309 return 0;
310 }
311 if (*(args[1]) == 0) {
312 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
313 return -1;
314 }
315 global.tune.maxaccept = atol(args[1]);
316 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317 else if (!strcmp(args[0], "uid")) {
318 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200319 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200320 return 0;
321 }
322 if (*(args[1]) == 0) {
323 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
324 return -1;
325 }
326 global.uid = atol(args[1]);
327 }
328 else if (!strcmp(args[0], "gid")) {
329 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200330 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200331 return 0;
332 }
333 if (*(args[1]) == 0) {
334 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
335 return -1;
336 }
337 global.gid = atol(args[1]);
338 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200339 /* user/group name handling */
340 else if (!strcmp(args[0], "user")) {
341 struct passwd *ha_user;
342 if (global.uid != 0) {
343 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
344 return 0;
345 }
346 errno = 0;
347 ha_user = getpwnam(args[1]);
348 if (ha_user != NULL) {
349 global.uid = (int)ha_user->pw_uid;
350 }
351 else {
352 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
353 exit(1);
354 }
355 }
356 else if (!strcmp(args[0], "group")) {
357 struct group *ha_group;
358 if (global.gid != 0) {
359 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
360 return 0;
361 }
362 errno = 0;
363 ha_group = getgrnam(args[1]);
364 if (ha_group != NULL) {
365 global.gid = (int)ha_group->gr_gid;
366 }
367 else {
368 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
369 exit(1);
370 }
371 }
372 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200373 else if (!strcmp(args[0], "nbproc")) {
374 if (global.nbproc != 0) {
375 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
376 return 0;
377 }
378 if (*(args[1]) == 0) {
379 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
380 return -1;
381 }
382 global.nbproc = atol(args[1]);
383 }
384 else if (!strcmp(args[0], "maxconn")) {
385 if (global.maxconn != 0) {
386 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
387 return 0;
388 }
389 if (*(args[1]) == 0) {
390 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
391 return -1;
392 }
393 global.maxconn = atol(args[1]);
394#ifdef SYSTEM_MAXCONN
395 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
396 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
397 global.maxconn = DEFAULT_MAXCONN;
398 }
399#endif /* SYSTEM_MAXCONN */
400 }
401 else if (!strcmp(args[0], "ulimit-n")) {
402 if (global.rlimit_nofile != 0) {
403 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
404 return 0;
405 }
406 if (*(args[1]) == 0) {
407 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
408 return -1;
409 }
410 global.rlimit_nofile = atol(args[1]);
411 }
412 else if (!strcmp(args[0], "chroot")) {
413 if (global.chroot != NULL) {
414 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
415 return 0;
416 }
417 if (*(args[1]) == 0) {
418 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
419 return -1;
420 }
421 global.chroot = strdup(args[1]);
422 }
423 else if (!strcmp(args[0], "pidfile")) {
424 if (global.pidfile != NULL) {
425 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
426 return 0;
427 }
428 if (*(args[1]) == 0) {
429 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
430 return -1;
431 }
432 global.pidfile = strdup(args[1]);
433 }
434 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100435 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200436 int facility, level;
437
438 if (*(args[1]) == 0 || *(args[2]) == 0) {
439 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
440 return -1;
441 }
442
443 facility = get_log_facility(args[2]);
444 if (facility < 0) {
445 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
446 exit(1);
447 }
448
449 level = 7; /* max syslog level = debug */
450 if (*(args[3])) {
451 level = get_log_level(args[3]);
452 if (level < 0) {
453 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
454 exit(1);
455 }
456 }
457
Robert Tsai81ae1952007-12-05 10:47:29 +0100458 if (args[1][0] == '/') {
459 logsrv.u.addr.sa_family = AF_UNIX;
460 logsrv.u.un = *str2sun(args[1]);
461 } else {
462 logsrv.u.addr.sa_family = AF_INET;
463 logsrv.u.in = *str2sa(args[1]);
464 if (!logsrv.u.in.sin_port)
465 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
466 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467
468 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100469 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 global.logfac1 = facility;
471 global.loglev1 = level;
472 }
473 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100474 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 global.logfac2 = facility;
476 global.loglev2 = level;
477 }
478 else {
479 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
480 return -1;
481 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200482 }
483 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
484 if (global.spread_checks != 0) {
485 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
486 return 0;
487 }
488 if (*(args[1]) == 0) {
489 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
490 return -1;
491 }
492 global.spread_checks = atol(args[1]);
493 if (global.spread_checks < 0 || global.spread_checks > 50) {
494 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
495 return -1;
496 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200497 }
498 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200499 struct cfg_kw_list *kwl;
500 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200501 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200502
503 list_for_each_entry(kwl, &cfg_keywords.list, list) {
504 for (index = 0; kwl->kw[index].kw != NULL; index++) {
505 if (kwl->kw[index].section != CFG_GLOBAL)
506 continue;
507 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
508 /* prepare error message just in case */
509 snprintf(trash, sizeof(trash),
510 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200511 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
512 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200513 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
514 return -1;
515 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200516 else if (rc > 0) {
517 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
518 return 0;
519 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200520 return 0;
521 }
522 }
523 }
524
Willy Tarreaubaaee002006-06-26 02:48:02 +0200525 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
526 return -1;
527 }
528 return 0;
529}
530
531
532static void init_default_instance()
533{
534 memset(&defproxy, 0, sizeof(defproxy));
535 defproxy.mode = PR_MODE_TCP;
536 defproxy.state = PR_STNEW;
537 defproxy.maxconn = cfg_maxpconn;
538 defproxy.conn_retries = CONN_RETRIES;
539 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100540 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541}
542
543/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100544 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
545 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100547int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548{
549 static struct proxy *curproxy = NULL;
550 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200551 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100552 int rc;
553 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200554
Willy Tarreau977b8e42006-12-29 14:19:17 +0100555 if (!strcmp(args[0], "listen"))
556 rc = PR_CAP_LISTEN;
557 else if (!strcmp(args[0], "frontend"))
558 rc = PR_CAP_FE | PR_CAP_RS;
559 else if (!strcmp(args[0], "backend"))
560 rc = PR_CAP_BE | PR_CAP_RS;
561 else if (!strcmp(args[0], "ruleset"))
562 rc = PR_CAP_RS;
563 else
564 rc = PR_CAP_NONE;
565
566 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 if (!*args[1]) {
568 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
569 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
570 file, linenum, args[0]);
571 return -1;
572 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200573
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100574 err = invalid_char(args[1]);
575 if (err) {
576 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
577 file, linenum, *err, args[0], args[1]);
578 return -1;
579 }
580
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200581 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
582 /*
583 * If there are two proxies with the same name only following
584 * combinations are allowed:
585 *
586 * listen backend frontend ruleset
587 * listen - - - -
588 * backend - - OK -
589 * frontend - OK - -
590 * ruleset - - - -
591 */
592
593 if (!strcmp(curproxy->id, args[1]) &&
594 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
595 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100596 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
597 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200598 }
599 }
600
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
602 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
603 return -1;
604 }
605
606 curproxy->next = proxy;
607 proxy = curproxy;
608 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200609 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200610 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200611 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100612 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200613 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200614 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615
Willy Tarreauee991362007-05-14 14:37:50 +0200616 /* Timeouts are defined as -1, so we cannot use the zeroed area
617 * as a default value.
618 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100619 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200620
621 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100623 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200624
625 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100626 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200627 curproxy->listen = str2listener(args[2], curproxy->listen);
628 if (!curproxy->listen)
629 return -1;
630 global.maxsock++;
631 }
632
633 /* set default values */
634 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100636 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200637 curproxy->except_net = defproxy.except_net;
638 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639
Willy Tarreau977b8e42006-12-29 14:19:17 +0100640 if (curproxy->cap & PR_CAP_FE) {
641 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100642 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100643
644 /* initialize error relocations */
645 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
646 if (defproxy.errmsg[rc].str)
647 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
648 }
649
650 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652
Willy Tarreau977b8e42006-12-29 14:19:17 +0100653 if (curproxy->cap & PR_CAP_BE) {
654 curproxy->fullconn = defproxy.fullconn;
655 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656
Willy Tarreau977b8e42006-12-29 14:19:17 +0100657 if (defproxy.check_req)
658 curproxy->check_req = strdup(defproxy.check_req);
659 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200660
Willy Tarreau977b8e42006-12-29 14:19:17 +0100661 if (defproxy.cookie_name)
662 curproxy->cookie_name = strdup(defproxy.cookie_name);
663 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100664
665 if (defproxy.url_param_name)
666 curproxy->url_param_name = strdup(defproxy.url_param_name);
667 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669
Willy Tarreau977b8e42006-12-29 14:19:17 +0100670 if (curproxy->cap & PR_CAP_RS) {
671 if (defproxy.capture_name)
672 curproxy->capture_name = strdup(defproxy.capture_name);
673 curproxy->capture_namelen = defproxy.capture_namelen;
674 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676
Willy Tarreau977b8e42006-12-29 14:19:17 +0100677 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100678 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100679 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100680 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100681 curproxy->uri_auth = defproxy.uri_auth;
682 curproxy->mon_net = defproxy.mon_net;
683 curproxy->mon_mask = defproxy.mon_mask;
684 if (defproxy.monitor_uri)
685 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
686 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100687 if (defproxy.defbe.name)
688 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100689 }
690
691 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100692 curproxy->timeout.connect = defproxy.timeout.connect;
693 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100694 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100695 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100696 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100697 curproxy->source_addr = defproxy.source_addr;
698 }
699
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700 curproxy->mode = defproxy.mode;
701 curproxy->logfac1 = defproxy.logfac1;
702 curproxy->logsrv1 = defproxy.logsrv1;
703 curproxy->loglev1 = defproxy.loglev1;
704 curproxy->logfac2 = defproxy.logfac2;
705 curproxy->logsrv2 = defproxy.logsrv2;
706 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200707 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100708 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
709 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200710
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 return 0;
712 }
713 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
714 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100715 /* FIXME-20070101: we should do this too at the end of the
716 * config parsing to free all default values.
717 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200718 free(defproxy.check_req);
719 free(defproxy.cookie_name);
720 free(defproxy.url_param_name);
721 free(defproxy.capture_name);
722 free(defproxy.monitor_uri);
723 free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100724
Willy Tarreaua534fea2008-08-03 12:19:50 +0200725 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
726 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100727
Willy Tarreaubaaee002006-06-26 02:48:02 +0200728 /* we cannot free uri_auth because it might already be used */
729 init_default_instance();
730 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100731 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200732 return 0;
733 }
734 else if (curproxy == NULL) {
735 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
736 return -1;
737 }
738
Willy Tarreau977b8e42006-12-29 14:19:17 +0100739
740 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200741 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100742 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200743 if (curproxy == &defproxy) {
744 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
745 return -1;
746 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100747 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
748 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749
750 if (strchr(args[1], ':') == NULL) {
751 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
752 file, linenum, args[0]);
753 return -1;
754 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100755
756 last_listen = curproxy->listen;
757 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200758 if (!curproxy->listen)
759 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100760 if (*args[2]) {
761#ifdef CONFIG_HAP_LINUX_TPROXY
762 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
763 struct listener *l;
764
765 for (l = curproxy->listen; l != last_listen; l = l->next)
766 l->options |= LI_O_FOREIGN;
767 }
768 else {
769 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
770 file, linenum, args[0]);
771 return -1;
772 }
773#else
774 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
775 file, linenum, args[0]);
776 return -1;
777#endif
778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200779 global.maxsock++;
780 return 0;
781 }
782 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
783 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
784 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
785 file, linenum, args[0]);
786 return -1;
787 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100788 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
789 return 0;
790
Willy Tarreaubaaee002006-06-26 02:48:02 +0200791 /* flush useless bits */
792 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
793 return 0;
794 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200795 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100796 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
797 return 0;
798
Willy Tarreau1c47f852006-07-09 08:22:27 +0200799 if (!*args[1]) {
800 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
801 file, linenum, args[0]);
802 return -1;
803 }
804
Willy Tarreaua534fea2008-08-03 12:19:50 +0200805 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100806 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200807 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100808 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200809 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
810
811 return 0;
812 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200813 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
814 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
815 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
816 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
817 else {
818 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
819 return -1;
820 }
821 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100822 else if (!strcmp(args[0], "id")) {
823 struct proxy *target;
824
825 if (curproxy == &defproxy) {
826 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
827 file, linenum, args[0]);
828 return -1;
829 }
830
831 if (!*args[1]) {
832 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
833 file, linenum, args[0]);
834 return -1;
835 }
836
837 curproxy->uuid = atol(args[1]);
838
839 if (curproxy->uuid < 1001) {
840 Alert("parsing [%s:%d]: custom id has to be > 1000",
841 file, linenum);
842 return -1;
843 }
844
845 for (target = proxy; target; target = target->next)
846 if (curproxy != target && curproxy->uuid == target->uuid) {
847 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
848 file, linenum, curproxy->id, target->id);
849 return -1;
850 }
851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200852 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
853 curproxy->state = PR_STSTOPPED;
854 }
855 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
856 curproxy->state = PR_STNEW;
857 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200858 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100859 err = invalid_char(args[1]);
860 if (err) {
861 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
862 file, linenum, *err, args[1]);
863 return -1;
864 }
865
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200866 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
867 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
868 file, linenum, args[1]);
869 return -1;
870 }
871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872 else if (!strcmp(args[0], "cookie")) { /* cookie name */
873 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200874
Willy Tarreau977b8e42006-12-29 14:19:17 +0100875 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
876 return 0;
877
Willy Tarreaubaaee002006-06-26 02:48:02 +0200878 if (*(args[1]) == 0) {
879 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
880 file, linenum, args[0]);
881 return -1;
882 }
Willy Tarreaua534fea2008-08-03 12:19:50 +0200883
884 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885 curproxy->cookie_name = strdup(args[1]);
886 curproxy->cookie_len = strlen(curproxy->cookie_name);
887
888 cur_arg = 2;
889 while (*(args[cur_arg])) {
890 if (!strcmp(args[cur_arg], "rewrite")) {
891 curproxy->options |= PR_O_COOK_RW;
892 }
893 else if (!strcmp(args[cur_arg], "indirect")) {
894 curproxy->options |= PR_O_COOK_IND;
895 }
896 else if (!strcmp(args[cur_arg], "insert")) {
897 curproxy->options |= PR_O_COOK_INS;
898 }
899 else if (!strcmp(args[cur_arg], "nocache")) {
900 curproxy->options |= PR_O_COOK_NOC;
901 }
902 else if (!strcmp(args[cur_arg], "postonly")) {
903 curproxy->options |= PR_O_COOK_POST;
904 }
905 else if (!strcmp(args[cur_arg], "prefix")) {
906 curproxy->options |= PR_O_COOK_PFX;
907 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200908 else if (!strcmp(args[cur_arg], "domain")) {
909 if (!*args[cur_arg + 1]) {
910 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
911 file, linenum, args[cur_arg]);
912 return -1;
913 }
914
915 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
916 /* rfc2109, 4.3.2 Rejecting Cookies */
917 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
918 " dots or does not start with a dot.\n",
919 file, linenum, args[cur_arg + 1]);
920 return -1;
921 }
922
923 err = invalid_domainchar(args[cur_arg + 1]);
924 if (err) {
925 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
926 file, linenum, *err, args[cur_arg + 1]);
927 return -1;
928 }
929
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +0200930 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200931 cur_arg++;
932 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200934 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 file, linenum, args[0]);
936 return -1;
937 }
938 cur_arg++;
939 }
940 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
941 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
942 file, linenum);
943 return -1;
944 }
945
946 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
947 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
948 file, linenum);
949 return -1;
950 }
951 }/* end else if (!strcmp(args[0], "cookie")) */
952 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953
Willy Tarreau977b8e42006-12-29 14:19:17 +0100954 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
955 return 0;
956
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 if (*(args[5]) == 0) {
958 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
959 file, linenum, args[0]);
960 return -1;
961 }
962 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +0200963 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 curproxy->appsession_name = strdup(args[1]);
965 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
966 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100967 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
968 if (err) {
969 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
970 file, linenum, *err, args[0]);
971 return -1;
972 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200973 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +0200974
Willy Tarreau51041c72007-09-09 21:56:53 +0200975 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
976 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977 return -1;
978 }
979 } /* Url App Session */
980 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100981 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
982 return 0;
983
Willy Tarreaubaaee002006-06-26 02:48:02 +0200984 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 if (*(args[4]) == 0) {
986 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
987 file, linenum, args[0]);
988 return -1;
989 }
Willy Tarreaua534fea2008-08-03 12:19:50 +0200990 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200991 curproxy->capture_name = strdup(args[2]);
992 curproxy->capture_namelen = strlen(curproxy->capture_name);
993 curproxy->capture_len = atol(args[4]);
994 if (curproxy->capture_len >= CAPTURE_LEN) {
995 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
996 file, linenum, CAPTURE_LEN - 1);
997 curproxy->capture_len = CAPTURE_LEN - 1;
998 }
999 curproxy->to_log |= LW_COOKIE;
1000 }
1001 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1002 struct cap_hdr *hdr;
1003
1004 if (curproxy == &defproxy) {
1005 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1006 return -1;
1007 }
1008
1009 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1010 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1011 file, linenum, args[0], args[1]);
1012 return -1;
1013 }
1014
1015 hdr = calloc(sizeof(struct cap_hdr), 1);
1016 hdr->next = curproxy->req_cap;
1017 hdr->name = strdup(args[3]);
1018 hdr->namelen = strlen(args[3]);
1019 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001020 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021 hdr->index = curproxy->nb_req_cap++;
1022 curproxy->req_cap = hdr;
1023 curproxy->to_log |= LW_REQHDR;
1024 }
1025 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1026 struct cap_hdr *hdr;
1027
1028 if (curproxy == &defproxy) {
1029 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1030 return -1;
1031 }
1032
1033 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1034 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1035 file, linenum, args[0], args[1]);
1036 return -1;
1037 }
1038 hdr = calloc(sizeof(struct cap_hdr), 1);
1039 hdr->next = curproxy->rsp_cap;
1040 hdr->name = strdup(args[3]);
1041 hdr->namelen = strlen(args[3]);
1042 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001043 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001044 hdr->index = curproxy->nb_rsp_cap++;
1045 curproxy->rsp_cap = hdr;
1046 curproxy->to_log |= LW_RSPHDR;
1047 }
1048 else {
1049 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1050 file, linenum, args[0]);
1051 return -1;
1052 }
1053 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001055 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1056 return 0;
1057
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 if (*(args[1]) == 0) {
1059 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1060 file, linenum, args[0]);
1061 return -1;
1062 }
1063 curproxy->conn_retries = atol(args[1]);
1064 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001065 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1066 int pol = ACL_COND_NONE;
1067 struct acl_cond *cond;
1068
1069 if (!strcmp(args[1], "if"))
1070 pol = ACL_COND_IF;
1071 else if (!strcmp(args[1], "unless"))
1072 pol = ACL_COND_UNLESS;
1073
1074 if (pol == ACL_COND_NONE) {
1075 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1076 file, linenum, args[0]);
1077 return -1;
1078 }
1079
1080 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1081 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1082 file, linenum);
1083 return -1;
1084 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001085 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001086 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1087 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001088 else if (!strcmp(args[0], "redirect")) {
1089 int pol = ACL_COND_NONE;
1090 struct acl_cond *cond;
1091 struct redirect_rule *rule;
1092 int cur_arg;
1093 int type = REDIRECT_TYPE_NONE;
1094 int code = 302;
1095 char *destination = NULL;
1096
1097 cur_arg = 1;
1098 while (*(args[cur_arg])) {
1099 if (!strcmp(args[cur_arg], "location")) {
1100 if (!*args[cur_arg + 1]) {
1101 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1102 file, linenum, args[0], args[cur_arg]);
1103 return -1;
1104 }
1105
1106 type = REDIRECT_TYPE_LOCATION;
1107 cur_arg++;
1108 destination = args[cur_arg];
1109 }
1110 else if (!strcmp(args[cur_arg], "prefix")) {
1111 if (!*args[cur_arg + 1]) {
1112 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1113 file, linenum, args[0], args[cur_arg]);
1114 return -1;
1115 }
1116
1117 type = REDIRECT_TYPE_PREFIX;
1118 cur_arg++;
1119 destination = args[cur_arg];
1120 }
1121 else if (!strcmp(args[cur_arg],"code")) {
1122 if (!*args[cur_arg + 1]) {
1123 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1124 file, linenum, args[0]);
1125 return -1;
1126 }
1127 cur_arg++;
1128 code = atol(args[cur_arg]);
1129 if (code < 301 || code > 303) {
1130 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1131 file, linenum, args[0], code);
1132 return -1;
1133 }
1134 }
1135 else if (!strcmp(args[cur_arg], "if")) {
1136 pol = ACL_COND_IF;
1137 cur_arg++;
1138 break;
1139 }
1140 else if (!strcmp(args[cur_arg], "unless")) {
1141 pol = ACL_COND_UNLESS;
1142 cur_arg++;
1143 break;
1144 }
1145 else {
1146 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1147 file, linenum, args[0], args[cur_arg]);
1148 return -1;
1149 }
1150 cur_arg++;
1151 }
1152
1153 if (type == REDIRECT_TYPE_NONE) {
1154 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1155 file, linenum, args[0]);
1156 return -1;
1157 }
1158
1159 if (pol == ACL_COND_NONE) {
1160 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1161 file, linenum, args[0]);
1162 return -1;
1163 }
1164
1165 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1166 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1167 file, linenum, args[0]);
1168 return -1;
1169 }
1170
Willy Tarreaua9802632008-07-25 19:13:19 +02001171 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001172 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1173 rule->cond = cond;
1174 rule->rdr_str = strdup(destination);
1175 rule->rdr_len = strlen(destination);
1176 rule->type = type;
1177 rule->code = code;
1178 LIST_INIT(&rule->list);
1179 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1180 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001181 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1182 int pol = ACL_COND_NONE;
1183 struct acl_cond *cond;
1184 struct switching_rule *rule;
1185
1186 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1187 return 0;
1188
1189 if (*(args[1]) == 0) {
1190 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1191 return -1;
1192 }
1193
1194 if (!strcmp(args[2], "if"))
1195 pol = ACL_COND_IF;
1196 else if (!strcmp(args[2], "unless"))
1197 pol = ACL_COND_UNLESS;
1198
1199 if (pol == ACL_COND_NONE) {
1200 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1201 file, linenum, args[0]);
1202 return -1;
1203 }
1204
1205 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001206 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001207 file, linenum);
1208 return -1;
1209 }
1210
Willy Tarreaua9802632008-07-25 19:13:19 +02001211 cond->line = linenum;
1212 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001213 struct acl *acl;
1214 const char *name;
1215
1216 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1217 name = acl ? acl->name : "(unknown)";
1218 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1219 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001220 }
1221
Willy Tarreau55ea7572007-06-17 19:56:27 +02001222 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1223 rule->cond = cond;
1224 rule->be.name = strdup(args[1]);
1225 LIST_INIT(&rule->list);
1226 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001229 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1230 return 0;
1231
Willy Tarreaubaaee002006-06-26 02:48:02 +02001232 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1233 curproxy->uri_auth = NULL; /* we must detach from the default config */
1234
1235 if (*(args[1]) == 0) {
1236 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1237 return -1;
1238 } else if (!strcmp(args[1], "uri")) {
1239 if (*(args[2]) == 0) {
1240 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1241 return -1;
1242 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1243 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1244 return -1;
1245 }
1246 } else if (!strcmp(args[1], "realm")) {
1247 if (*(args[2]) == 0) {
1248 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1249 return -1;
1250 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1251 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1252 return -1;
1253 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001254 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001255 unsigned interval;
1256
1257 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1258 if (err) {
1259 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1260 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001261 return -1;
1262 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1263 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1264 return -1;
1265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001266 } else if (!strcmp(args[1], "auth")) {
1267 if (*(args[2]) == 0) {
1268 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1269 return -1;
1270 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1271 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1272 return -1;
1273 }
1274 } else if (!strcmp(args[1], "scope")) {
1275 if (*(args[2]) == 0) {
1276 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1277 return -1;
1278 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1279 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1280 return -1;
1281 }
1282 } else if (!strcmp(args[1], "enable")) {
1283 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1284 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1285 return -1;
1286 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001287 } else if (!strcmp(args[1], "hide-version")) {
1288 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1289 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1290 return -1;
1291 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001292 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001293 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001294 file, linenum, args[0]);
1295 return -1;
1296 }
1297 }
1298 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001299 int optnum;
1300
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001301 if (*(args[1]) == '\0') {
1302 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1303 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304 return -1;
1305 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001306
1307 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1308 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1309 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1310 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001311
1312 if (!inv)
1313 curproxy->options |= cfg_opts[optnum].val;
1314 else
1315 curproxy->options &= ~cfg_opts[optnum].val;
1316
Willy Tarreau13943ab2006-12-31 00:24:10 +01001317 return 0;
1318 }
1319 }
1320
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001321 if (inv) {
1322 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1323 file, linenum, args[1]);
1324 return -1;
1325 }
1326
Willy Tarreau13943ab2006-12-31 00:24:10 +01001327 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001328 /* generate a complete HTTP log */
1329 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1330 else if (!strcmp(args[1], "tcplog"))
1331 /* generate a detailed TCP log */
1332 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001333 else if (!strcmp(args[1], "tcpka")) {
1334 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001335 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1336 return 0;
1337
1338 if (curproxy->cap & PR_CAP_FE)
1339 curproxy->options |= PR_O_TCP_CLI_KA;
1340 if (curproxy->cap & PR_CAP_BE)
1341 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001342 }
1343 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001344 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1345 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001346 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001347 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001348 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001349 curproxy->options &= ~PR_O_SMTP_CHK;
1350 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001351 if (!*args[2]) { /* no argument */
1352 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1353 curproxy->check_len = strlen(DEF_CHECK_REQ);
1354 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001355 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001356 curproxy->check_req = (char *)malloc(reqlen);
1357 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1358 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1359 } else { /* more arguments : METHOD URI [HTTP_VER] */
1360 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1361 if (*args[4])
1362 reqlen += strlen(args[4]);
1363 else
1364 reqlen += strlen("HTTP/1.0");
1365
1366 curproxy->check_req = (char *)malloc(reqlen);
1367 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1368 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1369 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001370 }
1371 else if (!strcmp(args[1], "ssl-hello-chk")) {
1372 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001373 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1374 return 0;
1375
Willy Tarreaua534fea2008-08-03 12:19:50 +02001376 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001377 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001378 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001379 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 }
Willy Tarreau23677902007-05-08 23:50:35 +02001381 else if (!strcmp(args[1], "smtpchk")) {
1382 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001383 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001384 curproxy->options &= ~PR_O_HTTP_CHK;
1385 curproxy->options &= ~PR_O_SSL3_CHK;
1386 curproxy->options |= PR_O_SMTP_CHK;
1387
1388 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1389 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1390 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1391 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1392 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1393 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1394 curproxy->check_req = (char *)malloc(reqlen);
1395 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1396 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1397 } else {
1398 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1399 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1400 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1401 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1402 }
1403 }
1404 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001405 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001406 int cur_arg;
1407
1408 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1409 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001410 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001411
1412 curproxy->options |= PR_O_FWDFOR;
1413
1414 free(curproxy->fwdfor_hdr_name);
1415 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1416 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1417
1418 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1419 cur_arg = 2;
1420 while (*(args[cur_arg])) {
1421 if (!strcmp(args[cur_arg], "except")) {
1422 /* suboption except - needs additional argument for it */
1423 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1424 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1425 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001426 return -1;
1427 }
1428 /* flush useless bits */
1429 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001430 cur_arg += 2;
1431 } else if (!strcmp(args[cur_arg], "header")) {
1432 /* suboption header - needs additional argument for it */
1433 if (*(args[cur_arg+1]) == 0) {
1434 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1435 file, linenum, args[0], args[1], args[cur_arg]);
1436 return -1;
1437 }
1438 free(curproxy->fwdfor_hdr_name);
1439 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1440 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1441 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001442 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001443 /* unknown suboption - catchall */
1444 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1445 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001446 return -1;
1447 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001448 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001449 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 else {
1451 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1452 return -1;
1453 }
1454 return 0;
1455 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001456 else if (!strcmp(args[0], "default_backend")) {
1457 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1458 return 0;
1459
1460 if (*(args[1]) == 0) {
1461 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1462 return -1;
1463 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001464 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001465 curproxy->defbe.name = strdup(args[1]);
1466 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001468 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1469 return 0;
1470
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001471 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1472 file, linenum, args[0]);
1473
Willy Tarreaubaaee002006-06-26 02:48:02 +02001474 /* enable reconnections to dispatch */
1475 curproxy->options |= PR_O_REDISP;
1476 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001477 else if (!strcmp(args[0], "http-check")) {
1478 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1479 return 0;
1480
1481 if (strcmp(args[1], "disable-on-404") == 0) {
1482 /* enable a graceful server shutdown on an HTTP 404 response */
1483 curproxy->options |= PR_O_DISABLE404;
1484 }
1485 else {
1486 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1487 return -1;
1488 }
1489 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001490 else if (!strcmp(args[0], "monitor")) {
1491 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1492 return 0;
1493
1494 if (strcmp(args[1], "fail") == 0) {
1495 /* add a condition to fail monitor requests */
1496 int pol = ACL_COND_NONE;
1497 struct acl_cond *cond;
1498
1499 if (!strcmp(args[2], "if"))
1500 pol = ACL_COND_IF;
1501 else if (!strcmp(args[2], "unless"))
1502 pol = ACL_COND_UNLESS;
1503
1504 if (pol == ACL_COND_NONE) {
1505 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1506 file, linenum, args[0], args[1]);
1507 return -1;
1508 }
1509
1510 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1511 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1512 file, linenum, args[0], args[1]);
1513 return -1;
1514 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001515 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001516 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1517 }
1518 else {
1519 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1520 return -1;
1521 }
1522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523#ifdef TPROXY
1524 else if (!strcmp(args[0], "transparent")) {
1525 /* enable transparent proxy connections */
1526 curproxy->options |= PR_O_TRANSP;
1527 }
1528#endif
1529 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001530 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1531 return 0;
1532
Willy Tarreaubaaee002006-06-26 02:48:02 +02001533 if (*(args[1]) == 0) {
1534 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1535 return -1;
1536 }
1537 curproxy->maxconn = atol(args[1]);
1538 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001539 else if (!strcmp(args[0], "backlog")) { /* backlog */
1540 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1541 return 0;
1542
1543 if (*(args[1]) == 0) {
1544 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1545 return -1;
1546 }
1547 curproxy->backlog = atol(args[1]);
1548 }
Willy Tarreau86034312006-12-29 00:10:33 +01001549 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001550 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1551 return 0;
1552
Willy Tarreau86034312006-12-29 00:10:33 +01001553 if (*(args[1]) == 0) {
1554 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1555 return -1;
1556 }
1557 curproxy->fullconn = atol(args[1]);
1558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1560 if (*(args[1]) == 0) {
1561 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1562 return -1;
1563 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001564 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1565 if (err) {
1566 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1567 file, linenum, *err);
1568 return -1;
1569 }
1570 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 }
1572 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1573 if (curproxy == &defproxy) {
1574 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1575 return -1;
1576 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001577 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1578 return 0;
1579
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580 if (strchr(args[1], ':') == NULL) {
1581 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1582 return -1;
1583 }
1584 curproxy->dispatch_addr = *str2sa(args[1]);
1585 }
1586 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001587 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1588 return 0;
1589
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001590 memcpy(trash, "error near 'balance'", 19);
1591 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1592 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1593 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001594 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001595 }
1596 else if (!strcmp(args[0], "server")) { /* server address */
1597 int cur_arg;
1598 char *rport;
1599 char *raddr;
1600 short realport;
1601 int do_check;
1602
1603 if (curproxy == &defproxy) {
1604 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1605 return -1;
1606 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001607 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1608 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609
1610 if (!*args[2]) {
1611 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1612 file, linenum, args[0]);
1613 return -1;
1614 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001615
1616 err = invalid_char(args[1]);
1617 if (err) {
1618 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1619 file, linenum, *err, args[1]);
1620 return -1;
1621 }
1622
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1624 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1625 return -1;
1626 }
1627
1628 /* the servers are linked backwards first */
1629 newsrv->next = curproxy->srv;
1630 curproxy->srv = newsrv;
1631 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001632 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633
1634 LIST_INIT(&newsrv->pendconns);
1635 do_check = 0;
1636 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001637 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638 newsrv->id = strdup(args[1]);
1639
1640 /* several ways to check the port component :
1641 * - IP => port=+0, relative
1642 * - IP: => port=+0, relative
1643 * - IP:N => port=N, absolute
1644 * - IP:+N => port=+N, relative
1645 * - IP:-N => port=-N, relative
1646 */
1647 raddr = strdup(args[2]);
1648 rport = strchr(raddr, ':');
1649 if (rport) {
1650 *rport++ = 0;
1651 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001652 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001653 newsrv->state |= SRV_MAPPORTS;
1654 } else {
1655 realport = 0;
1656 newsrv->state |= SRV_MAPPORTS;
1657 }
1658
1659 newsrv->addr = *str2sa(raddr);
1660 newsrv->addr.sin_port = htons(realport);
1661 free(raddr);
1662
1663 newsrv->curfd = -1; /* no health-check in progress */
1664 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001665 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1666 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 newsrv->rise = DEF_RISETIME;
1668 newsrv->fall = DEF_FALLTIME;
1669 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001670 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001671 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001672 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001673
Willy Tarreaubaaee002006-06-26 02:48:02 +02001674 cur_arg = 3;
1675 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001676 if (!strcmp(args[cur_arg], "id")) {
1677 struct server *target;
1678
1679 if (!*args[cur_arg + 1]) {
1680 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1681 file, linenum, args[cur_arg]);
1682 return -1;
1683 }
1684
1685 newsrv->puid = atol(args[cur_arg + 1]);
1686
1687 if (newsrv->puid< 1001) {
1688 Alert("parsing [%s:%d]: custom id has to be > 1000",
1689 file, linenum);
1690 return -1;
1691 }
1692
1693 for (target = proxy->srv; target; target = target->next)
1694 if (newsrv != target && newsrv->puid == target->puid) {
1695 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1696 file, linenum, newsrv->id, target->id);
1697 return -1;
1698 }
1699 cur_arg += 2;
1700 }
1701 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001702 newsrv->cookie = strdup(args[cur_arg + 1]);
1703 newsrv->cklen = strlen(args[cur_arg + 1]);
1704 cur_arg += 2;
1705 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001706 else if (!strcmp(args[cur_arg], "redir")) {
1707 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1708 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1709 cur_arg += 2;
1710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001711 else if (!strcmp(args[cur_arg], "rise")) {
1712 newsrv->rise = atol(args[cur_arg + 1]);
1713 newsrv->health = newsrv->rise;
1714 cur_arg += 2;
1715 }
1716 else if (!strcmp(args[cur_arg], "fall")) {
1717 newsrv->fall = atol(args[cur_arg + 1]);
1718 cur_arg += 2;
1719 }
1720 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001721 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1722 if (err) {
1723 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1724 file, linenum, *err, newsrv->id);
1725 return -1;
1726 }
1727 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 cur_arg += 2;
1729 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001730 else if (!strcmp(args[cur_arg], "fastinter")) {
1731 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1732 if (err) {
1733 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1734 file, linenum, *err, newsrv->id);
1735 return -1;
1736 }
1737 newsrv->fastinter = val;
1738 cur_arg += 2;
1739 }
1740 else if (!strcmp(args[cur_arg], "downinter")) {
1741 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1742 if (err) {
1743 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1744 file, linenum, *err, newsrv->id);
1745 return -1;
1746 }
1747 newsrv->downinter = val;
1748 cur_arg += 2;
1749 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001750 else if (!strcmp(args[cur_arg], "addr")) {
1751 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001752 cur_arg += 2;
1753 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754 else if (!strcmp(args[cur_arg], "port")) {
1755 newsrv->check_port = atol(args[cur_arg + 1]);
1756 cur_arg += 2;
1757 }
1758 else if (!strcmp(args[cur_arg], "backup")) {
1759 newsrv->state |= SRV_BACKUP;
1760 cur_arg ++;
1761 }
1762 else if (!strcmp(args[cur_arg], "weight")) {
1763 int w;
1764 w = atol(args[cur_arg + 1]);
1765 if (w < 1 || w > 256) {
1766 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1767 file, linenum, newsrv->id, w);
1768 return -1;
1769 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001770 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771 cur_arg += 2;
1772 }
1773 else if (!strcmp(args[cur_arg], "minconn")) {
1774 newsrv->minconn = atol(args[cur_arg + 1]);
1775 cur_arg += 2;
1776 }
1777 else if (!strcmp(args[cur_arg], "maxconn")) {
1778 newsrv->maxconn = atol(args[cur_arg + 1]);
1779 cur_arg += 2;
1780 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001781 else if (!strcmp(args[cur_arg], "maxqueue")) {
1782 newsrv->maxqueue = atol(args[cur_arg + 1]);
1783 cur_arg += 2;
1784 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001785 else if (!strcmp(args[cur_arg], "slowstart")) {
1786 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001787 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001788 if (err) {
1789 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1790 file, linenum, *err, newsrv->id);
1791 return -1;
1792 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001793 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001794 cur_arg += 2;
1795 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001796 else if (!strcmp(args[cur_arg], "track")) {
1797
1798 if (!*args[cur_arg + 1]) {
1799 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1800 file, linenum);
1801 return -1;
1802 }
1803
1804 newsrv->trackit = strdup(args[cur_arg + 1]);
1805
1806 cur_arg += 2;
1807 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001808 else if (!strcmp(args[cur_arg], "check")) {
1809 global.maxsock++;
1810 do_check = 1;
1811 cur_arg += 1;
1812 }
1813 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1814 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001815#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001816 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1817 file, linenum, "source", "usesrc");
1818#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001819 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1820 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001821#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001822 return -1;
1823 }
1824 newsrv->state |= SRV_BIND_SRC;
1825 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1826 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001827 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001828#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1829#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001830 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001831 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1832 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001833 return -1;
1834 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001835#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001836 if (!*args[cur_arg + 1]) {
1837 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1838 file, linenum, "usesrc");
1839 return -1;
1840 }
1841 if (!strcmp(args[cur_arg + 1], "client")) {
1842 newsrv->state |= SRV_TPROXY_CLI;
1843 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1844 newsrv->state |= SRV_TPROXY_CIP;
1845 } else {
1846 newsrv->state |= SRV_TPROXY_ADDR;
1847 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1848 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001849 global.last_checks |= LSTCHK_NETADM;
1850#if !defined(CONFIG_HAP_LINUX_TPROXY)
1851 global.last_checks |= LSTCHK_CTTPROXY;
1852#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001853 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001854#else /* no TPROXY support */
1855 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001856 file, linenum, "usesrc");
1857 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001858#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001859 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001860 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001861 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1862 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1863 file, linenum, "usesrc", "source");
1864 return -1;
1865 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001866 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001867 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 +02001868 file, linenum, newsrv->id);
1869 return -1;
1870 }
1871 }
1872
1873 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001874 if (newsrv->trackit) {
1875 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1876 file, linenum);
1877 return -1;
1878 }
1879
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001880 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1881 newsrv->check_port = newsrv->check_addr.sin_port;
1882
Willy Tarreaubaaee002006-06-26 02:48:02 +02001883 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1884 newsrv->check_port = realport; /* by default */
1885 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001886 /* not yet valid, because no port was set on
1887 * the server either. We'll check if we have
1888 * a known port on the first listener.
1889 */
1890 struct listener *l;
1891 l = curproxy->listen;
1892 if (l) {
1893 int port;
1894 port = (l->addr.ss_family == AF_INET6)
1895 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1896 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1897 newsrv->check_port = port;
1898 }
1899 }
1900 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1902 file, linenum, newsrv->id);
1903 return -1;
1904 }
1905 newsrv->state |= SRV_CHECKED;
1906 }
1907
1908 if (newsrv->state & SRV_BACKUP)
1909 curproxy->srv_bck++;
1910 else
1911 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001912
1913 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914 }
1915 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001916 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001917 int facility;
1918
1919 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1920 curproxy->logfac1 = global.logfac1;
1921 curproxy->logsrv1 = global.logsrv1;
1922 curproxy->loglev1 = global.loglev1;
1923 curproxy->logfac2 = global.logfac2;
1924 curproxy->logsrv2 = global.logsrv2;
1925 curproxy->loglev2 = global.loglev2;
1926 }
1927 else if (*(args[1]) && *(args[2])) {
1928 int level;
1929
1930 facility = get_log_facility(args[2]);
1931 if (facility < 0) {
1932 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1933 exit(1);
1934 }
1935
1936 level = 7; /* max syslog level = debug */
1937 if (*(args[3])) {
1938 level = get_log_level(args[3]);
1939 if (level < 0) {
1940 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1941 exit(1);
1942 }
1943 }
1944
Robert Tsai81ae1952007-12-05 10:47:29 +01001945 if (args[1][0] == '/') {
1946 logsrv.u.addr.sa_family = AF_UNIX;
1947 logsrv.u.un = *str2sun(args[1]);
1948 } else {
1949 logsrv.u.addr.sa_family = AF_INET;
1950 logsrv.u.in = *str2sa(args[1]);
1951 if (!logsrv.u.in.sin_port) {
1952 logsrv.u.in.sin_port =
1953 htons(SYSLOG_PORT);
1954 }
1955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001956
1957 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001958 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001959 curproxy->logfac1 = facility;
1960 curproxy->loglev1 = level;
1961 }
1962 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001963 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001964 curproxy->logfac2 = facility;
1965 curproxy->loglev2 = level;
1966 }
1967 else {
1968 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1969 return -1;
1970 }
1971 }
1972 else {
1973 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1974 file, linenum);
1975 return -1;
1976 }
1977 }
1978 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001979 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1980 return 0;
1981
Willy Tarreaubaaee002006-06-26 02:48:02 +02001982 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001983#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001984 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1985 file, linenum, "source", "usesrc");
1986#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001987 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1988 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001989#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001990 return -1;
1991 }
1992
1993 curproxy->source_addr = *str2sa(args[1]);
1994 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001995 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001996#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1997#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001998 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1999 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2000 file, linenum, "usesrc");
2001 return -1;
2002 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002003#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002004 if (!*args[3]) {
2005 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2006 file, linenum, "usesrc");
2007 return -1;
2008 }
2009
2010 if (!strcmp(args[3], "client")) {
2011 curproxy->options |= PR_O_TPXY_CLI;
2012 } else if (!strcmp(args[3], "clientip")) {
2013 curproxy->options |= PR_O_TPXY_CIP;
2014 } else {
2015 curproxy->options |= PR_O_TPXY_ADDR;
2016 curproxy->tproxy_addr = *str2sa(args[3]);
2017 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002018 global.last_checks |= LSTCHK_NETADM;
2019#if !defined(CONFIG_HAP_LINUX_TPROXY)
2020 global.last_checks |= LSTCHK_CTTPROXY;
2021#endif
2022#else /* no TPROXY support */
2023 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002024 file, linenum, "usesrc");
2025 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002026#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002027 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002029 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2030 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2031 file, linenum, "usesrc", "source");
2032 return -1;
2033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002034 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2035 regex_t *preg;
2036 if (curproxy == &defproxy) {
2037 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2038 return -1;
2039 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002040 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2041 return 0;
2042
Willy Tarreaubaaee002006-06-26 02:48:02 +02002043 if (*(args[1]) == 0 || *(args[2]) == 0) {
2044 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2045 file, linenum, args[0]);
2046 return -1;
2047 }
2048
2049 preg = calloc(1, sizeof(regex_t));
2050 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2051 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2052 return -1;
2053 }
2054
2055 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2056 if (err) {
2057 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2058 file, linenum, *err);
2059 return -1;
2060 }
2061 }
2062 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2063 regex_t *preg;
2064 if (curproxy == &defproxy) {
2065 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2066 return -1;
2067 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002068 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2069 return 0;
2070
Willy Tarreaubaaee002006-06-26 02:48:02 +02002071 if (*(args[1]) == 0) {
2072 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2073 return -1;
2074 }
2075
2076 preg = calloc(1, sizeof(regex_t));
2077 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2078 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2079 return -1;
2080 }
2081
2082 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2083 }
2084 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2085 regex_t *preg;
2086 if (curproxy == &defproxy) {
2087 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2088 return -1;
2089 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002090 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2091 return 0;
2092
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093 if (*(args[1]) == 0) {
2094 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2095 return -1;
2096 }
2097
2098 preg = calloc(1, sizeof(regex_t));
2099 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2100 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2101 return -1;
2102 }
2103
2104 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2105 }
2106 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2107 regex_t *preg;
2108 if (curproxy == &defproxy) {
2109 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2110 return -1;
2111 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002112 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2113 return 0;
2114
Willy Tarreaubaaee002006-06-26 02:48:02 +02002115 if (*(args[1]) == 0) {
2116 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2117 return -1;
2118 }
2119
2120 preg = calloc(1, sizeof(regex_t));
2121 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2122 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2123 return -1;
2124 }
2125
2126 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2127 }
2128 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2129 regex_t *preg;
2130 if (curproxy == &defproxy) {
2131 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2132 return -1;
2133 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002134 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2135 return 0;
2136
Willy Tarreaubaaee002006-06-26 02:48:02 +02002137 if (*(args[1]) == 0) {
2138 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2139 return -1;
2140 }
2141
2142 preg = calloc(1, sizeof(regex_t));
2143 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2144 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2145 return -1;
2146 }
2147
2148 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2149 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002150 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2151 regex_t *preg;
2152 if (curproxy == &defproxy) {
2153 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2154 return -1;
2155 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002156 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2157 return 0;
2158
Willy Tarreaub8750a82006-09-03 09:56:00 +02002159 if (*(args[1]) == 0) {
2160 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2161 return -1;
2162 }
2163
2164 preg = calloc(1, sizeof(regex_t));
2165 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2166 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2167 return -1;
2168 }
2169
2170 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2171 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002172 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2173 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002174 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002175 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2176 return -1;
2177 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002178 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2179 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002180
Willy Tarreau977b8e42006-12-29 14:19:17 +01002181 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002182 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2183 file, linenum, args[0]);
2184 return -1;
2185 }
2186
2187 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002188 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002189 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2190 }
2191
2192 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2193 }
2194 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2195 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002196 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002197 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2198 return -1;
2199 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002200 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2201 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002202
Willy Tarreau977b8e42006-12-29 14:19:17 +01002203 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002204 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2205 file, linenum, args[0]);
2206 return -1;
2207 }
2208
2209 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002210 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002211 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2212 }
2213
2214 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002216 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2217 regex_t *preg;
2218 if (curproxy == &defproxy) {
2219 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2220 return -1;
2221 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002222 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2223 return 0;
2224
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225 if (*(args[1]) == 0 || *(args[2]) == 0) {
2226 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2227 file, linenum, args[0]);
2228 return -1;
2229 }
2230
2231 preg = calloc(1, sizeof(regex_t));
2232 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2233 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2234 return -1;
2235 }
2236
2237 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2238 if (err) {
2239 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2240 file, linenum, *err);
2241 return -1;
2242 }
2243 }
2244 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2245 regex_t *preg;
2246 if (curproxy == &defproxy) {
2247 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2248 return -1;
2249 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002250 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2251 return 0;
2252
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253 if (*(args[1]) == 0) {
2254 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2255 return -1;
2256 }
2257
2258 preg = calloc(1, sizeof(regex_t));
2259 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2260 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2261 return -1;
2262 }
2263
2264 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2265 }
2266 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2267 regex_t *preg;
2268 if (curproxy == &defproxy) {
2269 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2270 return -1;
2271 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002272 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2273 return 0;
2274
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 if (*(args[1]) == 0) {
2276 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2277 return -1;
2278 }
2279
2280 preg = calloc(1, sizeof(regex_t));
2281 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2282 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2283 return -1;
2284 }
2285
2286 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2287 }
2288 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2289 regex_t *preg;
2290 if (curproxy == &defproxy) {
2291 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2292 return -1;
2293 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002294 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2295 return 0;
2296
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297 if (*(args[1]) == 0) {
2298 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2299 return -1;
2300 }
2301
2302 preg = calloc(1, sizeof(regex_t));
2303 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2304 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2305 return -1;
2306 }
2307
2308 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2309 }
2310 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2311 regex_t *preg;
2312 if (curproxy == &defproxy) {
2313 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2314 return -1;
2315 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002316 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2317 return 0;
2318
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 if (*(args[1]) == 0) {
2320 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2321 return -1;
2322 }
2323
2324 preg = calloc(1, sizeof(regex_t));
2325 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2326 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2327 return -1;
2328 }
2329
2330 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2331 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002332 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2333 regex_t *preg;
2334 if (curproxy == &defproxy) {
2335 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2336 return -1;
2337 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002338 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2339 return 0;
2340
Willy Tarreaub8750a82006-09-03 09:56:00 +02002341 if (*(args[1]) == 0) {
2342 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2343 return -1;
2344 }
2345
2346 preg = calloc(1, sizeof(regex_t));
2347 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2348 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2349 return -1;
2350 }
2351
2352 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2353 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2355 if (curproxy == &defproxy) {
2356 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2357 return -1;
2358 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002359 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2360 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361
2362 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2363 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2364 return 0;
2365 }
2366
2367 if (*(args[1]) == 0) {
2368 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2369 return -1;
2370 }
2371
2372 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2373 }
2374 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2375 regex_t *preg;
2376
2377 if (*(args[1]) == 0 || *(args[2]) == 0) {
2378 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2379 file, linenum, args[0]);
2380 return -1;
2381 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002382 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2383 return 0;
2384
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385 preg = calloc(1, sizeof(regex_t));
2386 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2387 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2388 return -1;
2389 }
2390
2391 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2392 if (err) {
2393 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2394 file, linenum, *err);
2395 return -1;
2396 }
2397 }
2398 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2399 regex_t *preg;
2400 if (curproxy == &defproxy) {
2401 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2402 return -1;
2403 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002404 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2405 return 0;
2406
Willy Tarreaubaaee002006-06-26 02:48:02 +02002407 if (*(args[1]) == 0) {
2408 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2409 return -1;
2410 }
2411
2412 preg = calloc(1, sizeof(regex_t));
2413 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2414 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2415 return -1;
2416 }
2417
2418 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2419 if (err) {
2420 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2421 file, linenum, *err);
2422 return -1;
2423 }
2424 }
2425 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2426 regex_t *preg;
2427 if (curproxy == &defproxy) {
2428 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2429 return -1;
2430 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002431 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2432 return 0;
2433
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 if (*(args[1]) == 0) {
2435 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2436 return -1;
2437 }
2438
2439 preg = calloc(1, sizeof(regex_t));
2440 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2441 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2442 return -1;
2443 }
2444
2445 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2446 if (err) {
2447 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2448 file, linenum, *err);
2449 return -1;
2450 }
2451 }
2452 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2453 regex_t *preg;
2454 if (curproxy == &defproxy) {
2455 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2456 return -1;
2457 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002458 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2459 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460
2461 if (*(args[1]) == 0 || *(args[2]) == 0) {
2462 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2463 file, linenum, args[0]);
2464 return -1;
2465 }
2466
2467 preg = calloc(1, sizeof(regex_t));
2468 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2469 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2470 return -1;
2471 }
2472
2473 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2474 if (err) {
2475 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2476 file, linenum, *err);
2477 return -1;
2478 }
2479 }
2480 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2481 regex_t *preg;
2482 if (curproxy == &defproxy) {
2483 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2484 return -1;
2485 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002486 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2487 return 0;
2488
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 if (*(args[1]) == 0) {
2490 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2491 return -1;
2492 }
2493
2494 preg = calloc(1, sizeof(regex_t));
2495 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2496 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2497 return -1;
2498 }
2499
2500 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2501 if (err) {
2502 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2503 file, linenum, *err);
2504 return -1;
2505 }
2506 }
2507 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2508 regex_t *preg;
2509 if (curproxy == &defproxy) {
2510 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2511 return -1;
2512 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002513 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2514 return 0;
2515
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 if (*(args[1]) == 0) {
2517 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2518 return -1;
2519 }
2520
2521 preg = calloc(1, sizeof(regex_t));
2522 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2523 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2524 return -1;
2525 }
2526
2527 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2528 if (err) {
2529 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2530 file, linenum, *err);
2531 return -1;
2532 }
2533 }
2534 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2535 if (curproxy == &defproxy) {
2536 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2537 return -1;
2538 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002539 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2540 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002541
2542 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2543 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2544 return 0;
2545 }
2546
2547 if (*(args[1]) == 0) {
2548 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2549 return -1;
2550 }
2551
2552 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2553 }
2554 else if (!strcmp(args[0], "errorloc") ||
2555 !strcmp(args[0], "errorloc302") ||
2556 !strcmp(args[0], "errorloc303")) { /* error location */
2557 int errnum, errlen;
2558 char *err;
2559
Willy Tarreau977b8e42006-12-29 14:19:17 +01002560 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2561 return 0;
2562
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002564 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 return -1;
2566 }
2567
2568 errnum = atol(args[1]);
2569 if (!strcmp(args[0], "errorloc303")) {
2570 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2571 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2572 } else {
2573 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2574 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2575 }
2576
Willy Tarreau0f772532006-12-23 20:51:41 +01002577 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2578 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002579 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002580 curproxy->errmsg[rc].str = err;
2581 curproxy->errmsg[rc].len = errlen;
2582 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002585
2586 if (rc >= HTTP_ERR_SIZE) {
2587 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2588 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 free(err);
2590 }
2591 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002592 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2593 int errnum, errlen, fd;
2594 char *err;
2595 struct stat stat;
2596
2597 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2598 return 0;
2599
2600 if (*(args[2]) == 0) {
2601 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2602 return -1;
2603 }
2604
2605 fd = open(args[2], O_RDONLY);
2606 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2607 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2608 file, linenum, args[2], args[1]);
2609 if (fd >= 0)
2610 close(fd);
2611 return -1;
2612 }
2613
2614 if (stat.st_size <= BUFSIZE) {
2615 errlen = stat.st_size;
2616 } else {
2617 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2618 file, linenum, args[2], BUFSIZE);
2619 errlen = BUFSIZE;
2620 }
2621
2622 err = malloc(errlen); /* malloc() must succeed during parsing */
2623 errnum = read(fd, err, errlen);
2624 if (errnum != errlen) {
2625 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2626 file, linenum, args[2], args[1]);
2627 close(fd);
2628 free(err);
2629 return -1;
2630 }
2631 close(fd);
2632
2633 errnum = atol(args[1]);
2634 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2635 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002636 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002637 curproxy->errmsg[rc].str = err;
2638 curproxy->errmsg[rc].len = errlen;
2639 break;
2640 }
2641 }
2642
2643 if (rc >= HTTP_ERR_SIZE) {
2644 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2645 file, linenum, errnum);
2646 free(err);
2647 }
2648 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002650 struct cfg_kw_list *kwl;
2651 int index;
2652
2653 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2654 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2655 if (kwl->kw[index].section != CFG_LISTEN)
2656 continue;
2657 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2658 /* prepare error message just in case */
2659 snprintf(trash, sizeof(trash),
2660 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002661 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2662 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002663 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2664 return -1;
2665 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002666 else if (rc > 0) {
2667 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2668 return 0;
2669 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002670 return 0;
2671 }
2672 }
2673 }
2674
Willy Tarreau6daf3432008-01-22 16:44:08 +01002675 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676 return -1;
2677 }
2678 return 0;
2679}
2680
2681
2682/*
2683 * This function reads and parses the configuration file given in the argument.
2684 * returns 0 if OK, -1 if error.
2685 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002686int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002688 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 FILE *f;
2690 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 int confsect = CFG_NONE;
2693
2694 struct proxy *curproxy = NULL;
2695 struct server *newsrv = NULL;
2696
2697 if ((f=fopen(file,"r")) == NULL)
2698 return -1;
2699
2700 init_default_instance();
2701
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002702 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002703 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002704 char *end;
2705 char *args[MAX_LINE_ARGS + 1];
2706 char *line = thisline;
2707
Willy Tarreaubaaee002006-06-26 02:48:02 +02002708 linenum++;
2709
2710 end = line + strlen(line);
2711
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002712 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2713 /* Check if we reached the limit and the last char is not \n.
2714 * Watch out for the last line without the terminating '\n'!
2715 */
2716 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2717 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002718 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002719 }
2720
Willy Tarreaubaaee002006-06-26 02:48:02 +02002721 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002722 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002723 line++;
2724
2725 arg = 0;
2726 args[arg] = line;
2727
2728 while (*line && arg < MAX_LINE_ARGS) {
2729 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2730 * C equivalent value. Other combinations left unchanged (eg: \1).
2731 */
2732 if (*line == '\\') {
2733 int skip = 0;
2734 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2735 *line = line[1];
2736 skip = 1;
2737 }
2738 else if (line[1] == 'r') {
2739 *line = '\r';
2740 skip = 1;
2741 }
2742 else if (line[1] == 'n') {
2743 *line = '\n';
2744 skip = 1;
2745 }
2746 else if (line[1] == 't') {
2747 *line = '\t';
2748 skip = 1;
2749 }
2750 else if (line[1] == 'x') {
2751 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2752 unsigned char hex1, hex2;
2753 hex1 = toupper(line[2]) - '0';
2754 hex2 = toupper(line[3]) - '0';
2755 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2756 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2757 *line = (hex1<<4) + hex2;
2758 skip = 3;
2759 }
2760 else {
2761 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002762 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 }
2764 }
2765 if (skip) {
2766 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2767 end -= skip;
2768 }
2769 line++;
2770 }
2771 else if (*line == '#' || *line == '\n' || *line == '\r') {
2772 /* end of string, end of loop */
2773 *line = 0;
2774 break;
2775 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002776 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002777 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002778 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002779 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780 line++;
2781 args[++arg] = line;
2782 }
2783 else {
2784 line++;
2785 }
2786 }
2787
2788 /* empty line */
2789 if (!**args)
2790 continue;
2791
Willy Tarreau540abe42007-05-02 20:50:16 +02002792 /* zero out remaining args and ensure that at least one entry
2793 * is zeroed out.
2794 */
2795 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002796 args[arg] = line;
2797 }
2798
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002799 if (!strcmp(args[0], "no")) {
2800 inv = 1;
2801 for (arg=0; *args[arg+1]; arg++)
2802 args[arg] = args[arg+1]; // shift args after inversion
2803 }
2804
2805 if (inv && strcmp(args[0], "option")) {
2806 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002807 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002808 }
2809
Willy Tarreau977b8e42006-12-29 14:19:17 +01002810 if (!strcmp(args[0], "listen") ||
2811 !strcmp(args[0], "frontend") ||
2812 !strcmp(args[0], "backend") ||
2813 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002814 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002816 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002817 cursection = strdup(args[0]);
2818 }
2819 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002820 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002821 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002822 cursection = strdup(args[0]);
2823 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002824 /* else it's a section keyword */
2825
2826 switch (confsect) {
2827 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002828 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002829 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002830 break;
2831 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002832 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002833 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834 break;
2835 default:
2836 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002837 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002840 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002841 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002842 fclose(f);
2843
2844 /*
2845 * Now, check for the integrity of all that we have collected.
2846 */
2847
2848 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002849 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002850
2851 if ((curproxy = proxy) == NULL) {
2852 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2853 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002854 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 }
2856
2857 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002858 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002859 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002860
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861 if (curproxy->state == PR_STSTOPPED) {
2862 curproxy = curproxy->next;
2863 continue;
2864 }
2865
Willy Tarreau977b8e42006-12-29 14:19:17 +01002866 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2867 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 +01002868 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869 cfgerr++;
2870 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002871 else if (curproxy->cap & PR_CAP_BE &&
2872 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002873 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002874 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002875 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2876 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 +01002877 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002878 cfgerr++;
2879 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002880
Willy Tarreau31682232007-11-29 15:38:04 +01002881 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002883 Alert("parsing %s : %s '%s' cannot use both transparent and 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 }
2887#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2888 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002889 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002890 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 cfgerr++;
2892 }
2893#endif
2894 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002895 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002896 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 }
2898 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002899
2900 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002902 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002903 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002905 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002906 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002907 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002908 }
2909 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002910 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002911 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002913 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002914 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002915 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002916 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002917 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002918 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2919 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002920
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002921 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002922 file, proxy_type_str(curproxy), curproxy->id);
2923 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002924 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002925
2926 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2927 if ((newsrv = curproxy->srv) != NULL) {
2928 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2929 file, proxy_type_str(curproxy), curproxy->id);
2930 }
2931 }
2932
2933 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2935 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2936 file, curproxy->id);
2937 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002938 }
2939 }
2940
Willy Tarreau82936582007-11-30 15:20:09 +01002941 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2942 curproxy->options &= ~PR_O_DISABLE404;
2943 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2944 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2945 }
2946
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002947 /* if a default backend was specified, let's find it */
2948 if (curproxy->defbe.name) {
2949 struct proxy *target;
2950
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002951 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2952 if (!target) {
2953 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2954 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002955 cfgerr++;
2956 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002957 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2958 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002959 } else {
2960 free(curproxy->defbe.name);
2961 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002962 }
2963 }
2964
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002965 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002966 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2967 /* map jump target for ACT_SETBE in req_rep chain */
2968 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002969 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002970 struct proxy *target;
2971
Willy Tarreaua496b602006-12-17 23:15:24 +01002972 if (exp->action != ACT_SETBE)
2973 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002974
2975 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2976 if (!target) {
2977 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2978 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002979 cfgerr++;
2980 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002981 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2982 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002983 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002984 } else {
2985 free((void *)exp->replace);
2986 exp->replace = (const char *)target;
2987 }
2988 }
2989 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002990
2991 /* find the target proxy for 'use_backend' rules */
2992 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002993 struct proxy *target;
2994
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002995 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002996
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002997 if (!target) {
2998 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2999 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003000 cfgerr++;
3001 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003002 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3003 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003004 cfgerr++;
3005 } else {
3006 free((void *)rule->be.name);
3007 rule->be.backend = target;
3008 }
3009 }
3010
Willy Tarreau2738a142006-07-08 17:28:09 +02003011 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003012 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003013 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003014 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003015 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003016 " | While not properly invalid, you will certainly encounter various problems\n"
3017 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003018 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003019 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003020 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003021
Willy Tarreau1fa31262007-12-03 00:36:16 +01003022 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3023 * We must still support older configurations, so let's find out whether those
3024 * parameters have been set or must be copied from contimeouts.
3025 */
3026 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003027 if (!curproxy->timeout.tarpit ||
3028 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003029 /* tarpit timeout not set. We search in the following order:
3030 * default.tarpit, curr.connect, default.connect.
3031 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003032 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003033 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003034 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003035 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003036 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003037 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003038 }
3039 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003040 (!curproxy->timeout.queue ||
3041 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003042 /* queue timeout not set. We search in the following order:
3043 * default.queue, curr.connect, default.connect.
3044 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003045 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003046 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003047 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003048 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003049 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003050 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003051 }
3052 }
3053
Willy Tarreauf3c69202006-07-09 16:42:34 +02003054 if (curproxy->options & PR_O_SSL3_CHK) {
3055 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3056 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3057 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3058 }
3059
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003060 /* The small pools required for the capture lists */
3061 if (curproxy->nb_req_cap)
3062 curproxy->req_cap_pool = create_pool("ptrcap",
3063 curproxy->nb_req_cap * sizeof(char *),
3064 MEM_F_SHARED);
3065 if (curproxy->nb_rsp_cap)
3066 curproxy->rsp_cap_pool = create_pool("ptrcap",
3067 curproxy->nb_rsp_cap * sizeof(char *),
3068 MEM_F_SHARED);
3069
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003070 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3071 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3072 MEM_F_SHARED);
3073
Willy Tarreau86034312006-12-29 00:10:33 +01003074 /* for backwards compatibility with "listen" instances, if
3075 * fullconn is not set but maxconn is set, then maxconn
3076 * is used.
3077 */
3078 if (!curproxy->fullconn)
3079 curproxy->fullconn = curproxy->maxconn;
3080
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 /* first, we will invert the servers list order */
3082 newsrv = NULL;
3083 while (curproxy->srv) {
3084 struct server *next;
3085
3086 next = curproxy->srv->next;
3087 curproxy->srv->next = newsrv;
3088 newsrv = curproxy->srv;
3089 if (!next)
3090 break;
3091 curproxy->srv = next;
3092 }
3093
Willy Tarreau20697042007-11-15 23:26:18 +01003094 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003095 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096
Willy Tarreaub625a082007-11-26 01:15:43 +01003097 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003098 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003099 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003100 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3101 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003102 else
3103 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104
3105 if (curproxy->options & PR_O_LOGASAP)
3106 curproxy->to_log &= ~LW_BYTES;
3107
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003109 * ensure that we're not cross-dressing a TCP server into HTTP.
3110 */
3111 newsrv = curproxy->srv;
3112 while (newsrv != NULL) {
3113 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3114 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3115 file, proxy_type_str(curproxy), curproxy->id, linenum);
3116 goto err;
3117 }
3118 newsrv = newsrv->next;
3119 }
3120
3121 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 * If this server supports a maxconn parameter, it needs a dedicated
3123 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003124 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 */
3126 newsrv = curproxy->srv;
3127 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003128 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 /* Only 'minconn' was specified, or it was higher than or equal
3130 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3131 * this will avoid further useless expensive computations.
3132 */
3133 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003134 } else if (newsrv->maxconn && !newsrv->minconn) {
3135 /* minconn was not specified, so we set it to maxconn */
3136 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003137 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3138 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003139 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003140 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141 }
3142
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003143 if (newsrv->trackit) {
3144 struct proxy *px;
3145 struct server *srv;
3146 char *pname, *sname;
3147
3148 pname = newsrv->trackit;
3149 sname = strrchr(pname, '/');
3150
3151 if (sname)
3152 *sname++ = '\0';
3153 else {
3154 sname = pname;
3155 pname = NULL;
3156 }
3157
3158 if (pname) {
3159 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3160 if (!px) {
3161 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3162 file, proxy_type_str(curproxy), curproxy->id,
3163 newsrv->id, pname);
3164 return -1;
3165 }
3166 } else
3167 px = curproxy;
3168
3169 srv = findserver(px, sname);
3170 if (!srv) {
3171 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3172 file, proxy_type_str(curproxy), curproxy->id,
3173 newsrv->id, sname);
3174 return -1;
3175 }
3176
3177 if (!(srv->state & SRV_CHECKED)) {
3178 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3179 "tracing as it does not have checks enabled.\n",
3180 file, proxy_type_str(curproxy), curproxy->id,
3181 newsrv->id, px->id, srv->id);
3182 return -1;
3183 }
3184
3185 if (curproxy != px &&
3186 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3187 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3188 "tracing: disable-on-404 option inconsistency.\n",
3189 file, proxy_type_str(curproxy), curproxy->id,
3190 newsrv->id, px->id, srv->id);
3191 return -1;
3192 }
3193
3194 newsrv->tracked = srv;
3195 newsrv->tracknext = srv->tracknext;
3196 srv->tracknext = newsrv;
3197
3198 free(newsrv->trackit);
3199 }
3200
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 newsrv = newsrv->next;
3202 }
3203
Willy Tarreaue6b98942007-10-29 01:09:36 +01003204 /* adjust this proxy's listeners */
3205 listener = curproxy->listen;
3206 while (listener) {
3207 if (curproxy->options & PR_O_TCP_NOLING)
3208 listener->options |= LI_O_NOLINGER;
3209 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003210 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003211 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003212 listener->accept = event_accept;
3213 listener->private = curproxy;
3214
3215 listener = listener->next;
3216 }
3217
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 curproxy = curproxy->next;
3219 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003220
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 if (cfgerr > 0) {
3222 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003223 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003224 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003225
3226 /*
3227 * Recount currently required checks.
3228 */
3229
3230 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3231 int optnum;
3232
3233 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3234 if (!(curproxy->options & cfg_opts[optnum].val))
3235 continue;
3236
3237 global.last_checks |= cfg_opts[optnum].checks;
3238 }
3239 }
3240
Willy Tarreaua534fea2008-08-03 12:19:50 +02003241 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003242 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003243 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003244
3245 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003246 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003247 cursection = NULL;
3248 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003249}
3250
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003251/*
3252 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3253 * parsing sessions.
3254 */
3255void cfg_register_keywords(struct cfg_kw_list *kwl)
3256{
3257 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3258}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003260/*
3261 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3262 */
3263void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3264{
3265 LIST_DEL(&kwl->list);
3266 LIST_INIT(&kwl->list);
3267}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268
3269/*
3270 * Local variables:
3271 * c-indent-level: 8
3272 * c-basic-offset: 8
3273 * End:
3274 */