blob: 893557ad17fa5ba4c2771177bc5680cdebcf4047 [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>
Willy Tarreau3bc13772008-12-07 11:50:35 +010049#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <proto/task.h>
51
52
Willy Tarreauf3c69202006-07-09 16:42:34 +020053/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
54 * ssl-hello-chk option to ensure that the remote server speaks SSL.
55 *
56 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
57 */
58const char sslv3_client_hello_pkt[] = {
59 "\x16" /* ContentType : 0x16 = Hanshake */
60 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
61 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
62 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
63 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
64 "\x03\x00" /* Hello Version : 0x0300 = v3 */
65 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
66 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
67 "\x00" /* Session ID length : empty (no session ID) */
68 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
69 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
70 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
71 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
72 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
73 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
74 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
75 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
76 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
77 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
78 "\x00\x38" "\x00\x39" "\x00\x3A"
79 "\x01" /* Compression Length : 0x01 = 1 byte for types */
80 "\x00" /* Compression Type : 0x00 = NULL compression */
81};
82
Willy Tarreau13943ab2006-12-31 00:24:10 +010083/* some of the most common options which are also the easiest to handle */
84static const struct {
85 const char *name;
86 unsigned int val;
87 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010088 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010089} cfg_opts[] =
90{
Willy Tarreau4fee4e92007-01-06 21:09:17 +010091 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010092 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010094 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010095 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
96 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
97 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
98 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
99 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
100 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
101 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
102 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100103 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100104 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
105 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100106#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100107 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
108#endif
109#ifdef TPROXY
110 { "transparent", PR_O_TRANSP, PR_CAP_FE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100111#endif
112
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100113 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114};
115
Willy Tarreaubaaee002006-06-26 02:48:02 +0200116
Willy Tarreau6daf3432008-01-22 16:44:08 +0100117static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200118static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
119int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
120int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
121
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200122/* List head of all known configuration keywords */
123static struct cfg_kw_list cfg_keywords = {
124 .list = LIST_HEAD_INIT(cfg_keywords.list)
125};
126
Willy Tarreaubaaee002006-06-26 02:48:02 +0200127/*
128 * converts <str> to a list of listeners which are dynamically allocated.
129 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
130 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
131 * - <port> is a numerical port from 1 to 65535 ;
132 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
133 * This can be repeated as many times as necessary, separated by a coma.
134 * The <tail> argument is a pointer to a current list which should be appended
135 * to the tail of the new list. The pointer to the new list is returned.
136 */
137static struct listener *str2listener(char *str, struct listener *tail)
138{
139 struct listener *l;
140 char *c, *next, *range, *dupstr;
141 int port, end;
142
143 next = dupstr = strdup(str);
144
145 while (next && *next) {
146 struct sockaddr_storage ss;
147
148 str = next;
149 /* 1) look for the end of the first address */
150 if ((next = strrchr(str, ',')) != NULL) {
151 *next++ = 0;
152 }
153
154 /* 2) look for the addr/port delimiter, it's the last colon. */
155 if ((range = strrchr(str, ':')) == NULL) {
156 Alert("Missing port number: '%s'\n", str);
157 goto fail;
158 }
159
160 *range++ = 0;
161
162 if (strrchr(str, ':') != NULL) {
163 /* IPv6 address contains ':' */
164 memset(&ss, 0, sizeof(ss));
165 ss.ss_family = AF_INET6;
166
167 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
168 Alert("Invalid server address: '%s'\n", str);
169 goto fail;
170 }
171 }
172 else {
173 memset(&ss, 0, sizeof(ss));
174 ss.ss_family = AF_INET;
175
176 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
177 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
178 }
179 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
180 struct hostent *he;
181
182 if ((he = gethostbyname(str)) == NULL) {
183 Alert("Invalid server name: '%s'\n", str);
184 goto fail;
185 }
186 else
187 ((struct sockaddr_in *)&ss)->sin_addr =
188 *(struct in_addr *) *(he->h_addr_list);
189 }
190 }
191
192 /* 3) look for the port-end delimiter */
193 if ((c = strchr(range, '-')) != NULL) {
194 *c++ = 0;
195 end = atol(c);
196 }
197 else {
198 end = atol(range);
199 }
200
201 port = atol(range);
202
203 if (port < 1 || port > 65535) {
204 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
205 goto fail;
206 }
207
208 if (end < 1 || end > 65535) {
209 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
210 goto fail;
211 }
212
213 for (; port <= end; port++) {
214 l = (struct listener *)calloc(1, sizeof(struct listener));
215 l->next = tail;
216 tail = l;
217
218 l->fd = -1;
219 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100220 l->state = LI_INIT;
221
222 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100224 tcpv6_add_listener(l);
225 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100227 tcpv4_add_listener(l);
228 }
229 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 } /* end for(port) */
231 } /* end while(next) */
232 free(dupstr);
233 return tail;
234 fail:
235 free(dupstr);
236 return NULL;
237}
238
Willy Tarreau977b8e42006-12-29 14:19:17 +0100239/*
240 * Sends a warning if proxy <proxy> does not have at least one of the
241 * capabilities in <cap>. An optionnal <hint> may be added at the end
242 * of the warning to help the user. Returns 1 if a warning was emitted
243 * or 0 if the condition is valid.
244 */
245int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
246{
247 char *msg;
248
249 switch (cap) {
250 case PR_CAP_BE: msg = "no backend"; break;
251 case PR_CAP_FE: msg = "no frontend"; break;
252 case PR_CAP_RS: msg = "no ruleset"; break;
253 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
254 default: msg = "not enough"; break;
255 }
256
257 if (!(proxy->cap & cap)) {
258 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100259 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100260 return 1;
261 }
262 return 0;
263}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264
265/*
266 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
267 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100268int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200269{
270
271 if (!strcmp(args[0], "global")) { /* new section */
272 /* no option, nothing special to do */
273 return 0;
274 }
275 else if (!strcmp(args[0], "daemon")) {
276 global.mode |= MODE_DAEMON;
277 }
278 else if (!strcmp(args[0], "debug")) {
279 global.mode |= MODE_DEBUG;
280 }
281 else if (!strcmp(args[0], "noepoll")) {
282 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
283 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200284 else if (!strcmp(args[0], "nosepoll")) {
285 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
286 }
287 else if (!strcmp(args[0], "nokqueue")) {
288 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 else if (!strcmp(args[0], "nopoll")) {
291 cfg_polling_mechanism &= ~POLL_USE_POLL;
292 }
293 else if (!strcmp(args[0], "quiet")) {
294 global.mode |= MODE_QUIET;
295 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200296 else if (!strcmp(args[0], "tune.maxpollevents")) {
297 if (global.tune.maxpollevents != 0) {
298 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
299 return 0;
300 }
301 if (*(args[1]) == 0) {
302 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
303 return -1;
304 }
305 global.tune.maxpollevents = atol(args[1]);
306 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100307 else if (!strcmp(args[0], "tune.maxaccept")) {
308 if (global.tune.maxaccept != 0) {
309 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
310 return 0;
311 }
312 if (*(args[1]) == 0) {
313 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
314 return -1;
315 }
316 global.tune.maxaccept = atol(args[1]);
317 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318 else if (!strcmp(args[0], "uid")) {
319 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200320 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321 return 0;
322 }
323 if (*(args[1]) == 0) {
324 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
325 return -1;
326 }
327 global.uid = atol(args[1]);
328 }
329 else if (!strcmp(args[0], "gid")) {
330 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200331 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200332 return 0;
333 }
334 if (*(args[1]) == 0) {
335 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
336 return -1;
337 }
338 global.gid = atol(args[1]);
339 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200340 /* user/group name handling */
341 else if (!strcmp(args[0], "user")) {
342 struct passwd *ha_user;
343 if (global.uid != 0) {
344 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
345 return 0;
346 }
347 errno = 0;
348 ha_user = getpwnam(args[1]);
349 if (ha_user != NULL) {
350 global.uid = (int)ha_user->pw_uid;
351 }
352 else {
353 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
354 exit(1);
355 }
356 }
357 else if (!strcmp(args[0], "group")) {
358 struct group *ha_group;
359 if (global.gid != 0) {
360 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
361 return 0;
362 }
363 errno = 0;
364 ha_group = getgrnam(args[1]);
365 if (ha_group != NULL) {
366 global.gid = (int)ha_group->gr_gid;
367 }
368 else {
369 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
370 exit(1);
371 }
372 }
373 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200374 else if (!strcmp(args[0], "nbproc")) {
375 if (global.nbproc != 0) {
376 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
377 return 0;
378 }
379 if (*(args[1]) == 0) {
380 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
381 return -1;
382 }
383 global.nbproc = atol(args[1]);
384 }
385 else if (!strcmp(args[0], "maxconn")) {
386 if (global.maxconn != 0) {
387 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
388 return 0;
389 }
390 if (*(args[1]) == 0) {
391 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
392 return -1;
393 }
394 global.maxconn = atol(args[1]);
395#ifdef SYSTEM_MAXCONN
396 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
397 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);
398 global.maxconn = DEFAULT_MAXCONN;
399 }
400#endif /* SYSTEM_MAXCONN */
401 }
402 else if (!strcmp(args[0], "ulimit-n")) {
403 if (global.rlimit_nofile != 0) {
404 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
405 return 0;
406 }
407 if (*(args[1]) == 0) {
408 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
409 return -1;
410 }
411 global.rlimit_nofile = atol(args[1]);
412 }
413 else if (!strcmp(args[0], "chroot")) {
414 if (global.chroot != NULL) {
415 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
416 return 0;
417 }
418 if (*(args[1]) == 0) {
419 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
420 return -1;
421 }
422 global.chroot = strdup(args[1]);
423 }
424 else if (!strcmp(args[0], "pidfile")) {
425 if (global.pidfile != NULL) {
426 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
427 return 0;
428 }
429 if (*(args[1]) == 0) {
430 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
431 return -1;
432 }
433 global.pidfile = strdup(args[1]);
434 }
435 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100436 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200437 int facility, level;
438
439 if (*(args[1]) == 0 || *(args[2]) == 0) {
440 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
441 return -1;
442 }
443
444 facility = get_log_facility(args[2]);
445 if (facility < 0) {
446 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
447 exit(1);
448 }
449
450 level = 7; /* max syslog level = debug */
451 if (*(args[3])) {
452 level = get_log_level(args[3]);
453 if (level < 0) {
454 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
455 exit(1);
456 }
457 }
458
Robert Tsai81ae1952007-12-05 10:47:29 +0100459 if (args[1][0] == '/') {
460 logsrv.u.addr.sa_family = AF_UNIX;
461 logsrv.u.un = *str2sun(args[1]);
462 } else {
463 logsrv.u.addr.sa_family = AF_INET;
464 logsrv.u.in = *str2sa(args[1]);
465 if (!logsrv.u.in.sin_port)
466 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468
469 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100470 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200471 global.logfac1 = facility;
472 global.loglev1 = level;
473 }
474 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100475 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476 global.logfac2 = facility;
477 global.loglev2 = level;
478 }
479 else {
480 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
481 return -1;
482 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200483 }
484 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
485 if (global.spread_checks != 0) {
486 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
487 return 0;
488 }
489 if (*(args[1]) == 0) {
490 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
491 return -1;
492 }
493 global.spread_checks = atol(args[1]);
494 if (global.spread_checks < 0 || global.spread_checks > 50) {
495 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
496 return -1;
497 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200498 }
499 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200500 struct cfg_kw_list *kwl;
501 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200502 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200503
504 list_for_each_entry(kwl, &cfg_keywords.list, list) {
505 for (index = 0; kwl->kw[index].kw != NULL; index++) {
506 if (kwl->kw[index].section != CFG_GLOBAL)
507 continue;
508 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
509 /* prepare error message just in case */
510 snprintf(trash, sizeof(trash),
511 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200512 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
513 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200514 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
515 return -1;
516 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200517 else if (rc > 0) {
518 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
519 return 0;
520 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200521 return 0;
522 }
523 }
524 }
525
Willy Tarreaubaaee002006-06-26 02:48:02 +0200526 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
527 return -1;
528 }
529 return 0;
530}
531
532
533static void init_default_instance()
534{
535 memset(&defproxy, 0, sizeof(defproxy));
536 defproxy.mode = PR_MODE_TCP;
537 defproxy.state = PR_STNEW;
538 defproxy.maxconn = cfg_maxpconn;
539 defproxy.conn_retries = CONN_RETRIES;
540 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100541 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200542}
543
544/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100545 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
546 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200547 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100548int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200549{
550 static struct proxy *curproxy = NULL;
551 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200552 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100553 int rc;
554 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200555
Willy Tarreau977b8e42006-12-29 14:19:17 +0100556 if (!strcmp(args[0], "listen"))
557 rc = PR_CAP_LISTEN;
558 else if (!strcmp(args[0], "frontend"))
559 rc = PR_CAP_FE | PR_CAP_RS;
560 else if (!strcmp(args[0], "backend"))
561 rc = PR_CAP_BE | PR_CAP_RS;
562 else if (!strcmp(args[0], "ruleset"))
563 rc = PR_CAP_RS;
564 else
565 rc = PR_CAP_NONE;
566
567 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200568 if (!*args[1]) {
569 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
570 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
571 file, linenum, args[0]);
572 return -1;
573 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200574
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100575 err = invalid_char(args[1]);
576 if (err) {
577 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
578 file, linenum, *err, args[0], args[1]);
579 return -1;
580 }
581
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200582 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
583 /*
584 * If there are two proxies with the same name only following
585 * combinations are allowed:
586 *
587 * listen backend frontend ruleset
588 * listen - - - -
589 * backend - - OK -
590 * frontend - OK - -
591 * ruleset - - - -
592 */
593
594 if (!strcmp(curproxy->id, args[1]) &&
595 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
596 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100597 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
598 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200599 }
600 }
601
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
603 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
604 return -1;
605 }
606
607 curproxy->next = proxy;
608 proxy = curproxy;
609 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200610 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200611 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200612 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100613 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200614 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200615 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616
Willy Tarreauee991362007-05-14 14:37:50 +0200617 /* Timeouts are defined as -1, so we cannot use the zeroed area
618 * as a default value.
619 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100620 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200621
622 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100624 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200625
626 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100627 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 curproxy->listen = str2listener(args[2], curproxy->listen);
629 if (!curproxy->listen)
630 return -1;
631 global.maxsock++;
632 }
633
634 /* set default values */
635 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100637 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200638 curproxy->except_net = defproxy.except_net;
639 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200640
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200641 if (defproxy.fwdfor_hdr_len) {
642 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
643 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
644 }
645
Willy Tarreau977b8e42006-12-29 14:19:17 +0100646 if (curproxy->cap & PR_CAP_FE) {
647 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100648 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100649
650 /* initialize error relocations */
651 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
652 if (defproxy.errmsg[rc].str)
653 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
654 }
655
656 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658
Willy Tarreau977b8e42006-12-29 14:19:17 +0100659 if (curproxy->cap & PR_CAP_BE) {
660 curproxy->fullconn = defproxy.fullconn;
661 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662
Willy Tarreau977b8e42006-12-29 14:19:17 +0100663 if (defproxy.check_req)
664 curproxy->check_req = strdup(defproxy.check_req);
665 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666
Willy Tarreau977b8e42006-12-29 14:19:17 +0100667 if (defproxy.cookie_name)
668 curproxy->cookie_name = strdup(defproxy.cookie_name);
669 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100670
671 if (defproxy.url_param_name)
672 curproxy->url_param_name = strdup(defproxy.url_param_name);
673 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675
Willy Tarreau977b8e42006-12-29 14:19:17 +0100676 if (curproxy->cap & PR_CAP_RS) {
677 if (defproxy.capture_name)
678 curproxy->capture_name = strdup(defproxy.capture_name);
679 curproxy->capture_namelen = defproxy.capture_namelen;
680 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100681 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682
Willy Tarreau977b8e42006-12-29 14:19:17 +0100683 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100684 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100685 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100686 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100687 curproxy->uri_auth = defproxy.uri_auth;
688 curproxy->mon_net = defproxy.mon_net;
689 curproxy->mon_mask = defproxy.mon_mask;
690 if (defproxy.monitor_uri)
691 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
692 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100693 if (defproxy.defbe.name)
694 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100695 }
696
697 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100698 curproxy->timeout.connect = defproxy.timeout.connect;
699 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100700 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100701 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100702 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100703 curproxy->source_addr = defproxy.source_addr;
704 }
705
Willy Tarreaubaaee002006-06-26 02:48:02 +0200706 curproxy->mode = defproxy.mode;
707 curproxy->logfac1 = defproxy.logfac1;
708 curproxy->logsrv1 = defproxy.logsrv1;
709 curproxy->loglev1 = defproxy.loglev1;
710 curproxy->logfac2 = defproxy.logfac2;
711 curproxy->logsrv2 = defproxy.logsrv2;
712 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200713 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100714 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
715 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200716
Willy Tarreaubaaee002006-06-26 02:48:02 +0200717 return 0;
718 }
719 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
720 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100721 /* FIXME-20070101: we should do this too at the end of the
722 * config parsing to free all default values.
723 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200724 free(defproxy.check_req);
725 free(defproxy.cookie_name);
726 free(defproxy.url_param_name);
727 free(defproxy.capture_name);
728 free(defproxy.monitor_uri);
729 free(defproxy.defbe.name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200730 free(defproxy.fwdfor_hdr_name);
731 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100732
Willy Tarreaua534fea2008-08-03 12:19:50 +0200733 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
734 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100735
Willy Tarreaubaaee002006-06-26 02:48:02 +0200736 /* we cannot free uri_auth because it might already be used */
737 init_default_instance();
738 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100739 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200740 return 0;
741 }
742 else if (curproxy == NULL) {
743 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
744 return -1;
745 }
746
Willy Tarreau977b8e42006-12-29 14:19:17 +0100747
748 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100750 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751 if (curproxy == &defproxy) {
752 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
753 return -1;
754 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100755 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
756 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757
758 if (strchr(args[1], ':') == NULL) {
759 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
760 file, linenum, args[0]);
761 return -1;
762 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100763
764 last_listen = curproxy->listen;
765 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200766 if (!curproxy->listen)
767 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100768 if (*args[2]) {
769#ifdef CONFIG_HAP_LINUX_TPROXY
770 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
771 struct listener *l;
772
773 for (l = curproxy->listen; l != last_listen; l = l->next)
774 l->options |= LI_O_FOREIGN;
775 }
776 else {
777 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
778 file, linenum, args[0]);
779 return -1;
780 }
781#else
782 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
783 file, linenum, args[0]);
784 return -1;
785#endif
786 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200787 global.maxsock++;
788 return 0;
789 }
790 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
791 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
792 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
793 file, linenum, args[0]);
794 return -1;
795 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100796 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
797 return 0;
798
Willy Tarreaubaaee002006-06-26 02:48:02 +0200799 /* flush useless bits */
800 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
801 return 0;
802 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200803 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100804 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
805 return 0;
806
Willy Tarreau1c47f852006-07-09 08:22:27 +0200807 if (!*args[1]) {
808 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
809 file, linenum, args[0]);
810 return -1;
811 }
812
Willy Tarreaua534fea2008-08-03 12:19:50 +0200813 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100814 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200815 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100816 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200817 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
818
819 return 0;
820 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
822 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
823 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
824 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
825 else {
826 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
827 return -1;
828 }
829 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100830 else if (!strcmp(args[0], "id")) {
831 struct proxy *target;
832
833 if (curproxy == &defproxy) {
834 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
835 file, linenum, args[0]);
836 return -1;
837 }
838
839 if (!*args[1]) {
840 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
841 file, linenum, args[0]);
842 return -1;
843 }
844
845 curproxy->uuid = atol(args[1]);
846
847 if (curproxy->uuid < 1001) {
848 Alert("parsing [%s:%d]: custom id has to be > 1000",
849 file, linenum);
850 return -1;
851 }
852
853 for (target = proxy; target; target = target->next)
854 if (curproxy != target && curproxy->uuid == target->uuid) {
855 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
856 file, linenum, curproxy->id, target->id);
857 return -1;
858 }
859 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200860 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
861 curproxy->state = PR_STSTOPPED;
862 }
863 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
864 curproxy->state = PR_STNEW;
865 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200866 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100867 err = invalid_char(args[1]);
868 if (err) {
869 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
870 file, linenum, *err, args[1]);
871 return -1;
872 }
873
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200874 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
875 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
876 file, linenum, args[1]);
877 return -1;
878 }
879 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200880 else if (!strcmp(args[0], "cookie")) { /* cookie name */
881 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882
Willy Tarreau977b8e42006-12-29 14:19:17 +0100883 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
884 return 0;
885
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886 if (*(args[1]) == 0) {
887 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
888 file, linenum, args[0]);
889 return -1;
890 }
Willy Tarreaua534fea2008-08-03 12:19:50 +0200891
892 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200893 curproxy->cookie_name = strdup(args[1]);
894 curproxy->cookie_len = strlen(curproxy->cookie_name);
895
896 cur_arg = 2;
897 while (*(args[cur_arg])) {
898 if (!strcmp(args[cur_arg], "rewrite")) {
899 curproxy->options |= PR_O_COOK_RW;
900 }
901 else if (!strcmp(args[cur_arg], "indirect")) {
902 curproxy->options |= PR_O_COOK_IND;
903 }
904 else if (!strcmp(args[cur_arg], "insert")) {
905 curproxy->options |= PR_O_COOK_INS;
906 }
907 else if (!strcmp(args[cur_arg], "nocache")) {
908 curproxy->options |= PR_O_COOK_NOC;
909 }
910 else if (!strcmp(args[cur_arg], "postonly")) {
911 curproxy->options |= PR_O_COOK_POST;
912 }
913 else if (!strcmp(args[cur_arg], "prefix")) {
914 curproxy->options |= PR_O_COOK_PFX;
915 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200916 else if (!strcmp(args[cur_arg], "domain")) {
917 if (!*args[cur_arg + 1]) {
918 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
919 file, linenum, args[cur_arg]);
920 return -1;
921 }
922
923 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
924 /* rfc2109, 4.3.2 Rejecting Cookies */
925 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
926 " dots or does not start with a dot.\n",
927 file, linenum, args[cur_arg + 1]);
928 return -1;
929 }
930
931 err = invalid_domainchar(args[cur_arg + 1]);
932 if (err) {
933 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
934 file, linenum, *err, args[cur_arg + 1]);
935 return -1;
936 }
937
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +0200938 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200939 cur_arg++;
940 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200941 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200942 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 file, linenum, args[0]);
944 return -1;
945 }
946 cur_arg++;
947 }
948 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
949 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
950 file, linenum);
951 return -1;
952 }
953
954 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
955 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
956 file, linenum);
957 return -1;
958 }
959 }/* end else if (!strcmp(args[0], "cookie")) */
960 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961
Willy Tarreau977b8e42006-12-29 14:19:17 +0100962 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
963 return 0;
964
Willy Tarreaubaaee002006-06-26 02:48:02 +0200965 if (*(args[5]) == 0) {
966 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
967 file, linenum, args[0]);
968 return -1;
969 }
970 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +0200971 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200972 curproxy->appsession_name = strdup(args[1]);
973 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
974 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100975 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
976 if (err) {
977 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
978 file, linenum, *err, args[0]);
979 return -1;
980 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200981 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +0200982
Willy Tarreau51041c72007-09-09 21:56:53 +0200983 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
984 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 return -1;
986 }
987 } /* Url App Session */
988 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100989 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
990 return 0;
991
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 if (*(args[4]) == 0) {
994 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
995 file, linenum, args[0]);
996 return -1;
997 }
Willy Tarreaua534fea2008-08-03 12:19:50 +0200998 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 curproxy->capture_name = strdup(args[2]);
1000 curproxy->capture_namelen = strlen(curproxy->capture_name);
1001 curproxy->capture_len = atol(args[4]);
1002 if (curproxy->capture_len >= CAPTURE_LEN) {
1003 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1004 file, linenum, CAPTURE_LEN - 1);
1005 curproxy->capture_len = CAPTURE_LEN - 1;
1006 }
1007 curproxy->to_log |= LW_COOKIE;
1008 }
1009 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1010 struct cap_hdr *hdr;
1011
1012 if (curproxy == &defproxy) {
1013 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1014 return -1;
1015 }
1016
1017 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1018 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1019 file, linenum, args[0], args[1]);
1020 return -1;
1021 }
1022
1023 hdr = calloc(sizeof(struct cap_hdr), 1);
1024 hdr->next = curproxy->req_cap;
1025 hdr->name = strdup(args[3]);
1026 hdr->namelen = strlen(args[3]);
1027 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001028 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001029 hdr->index = curproxy->nb_req_cap++;
1030 curproxy->req_cap = hdr;
1031 curproxy->to_log |= LW_REQHDR;
1032 }
1033 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1034 struct cap_hdr *hdr;
1035
1036 if (curproxy == &defproxy) {
1037 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1038 return -1;
1039 }
1040
1041 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1042 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1043 file, linenum, args[0], args[1]);
1044 return -1;
1045 }
1046 hdr = calloc(sizeof(struct cap_hdr), 1);
1047 hdr->next = curproxy->rsp_cap;
1048 hdr->name = strdup(args[3]);
1049 hdr->namelen = strlen(args[3]);
1050 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001051 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 hdr->index = curproxy->nb_rsp_cap++;
1053 curproxy->rsp_cap = hdr;
1054 curproxy->to_log |= LW_RSPHDR;
1055 }
1056 else {
1057 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1058 file, linenum, args[0]);
1059 return -1;
1060 }
1061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001063 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1064 return 0;
1065
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066 if (*(args[1]) == 0) {
1067 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1068 file, linenum, args[0]);
1069 return -1;
1070 }
1071 curproxy->conn_retries = atol(args[1]);
1072 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001073 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1074 int pol = ACL_COND_NONE;
1075 struct acl_cond *cond;
1076
1077 if (!strcmp(args[1], "if"))
1078 pol = ACL_COND_IF;
1079 else if (!strcmp(args[1], "unless"))
1080 pol = ACL_COND_UNLESS;
1081
1082 if (pol == ACL_COND_NONE) {
1083 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1084 file, linenum, args[0]);
1085 return -1;
1086 }
1087
1088 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1089 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1090 file, linenum);
1091 return -1;
1092 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001093 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001094 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1095 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001096 else if (!strcmp(args[0], "redirect")) {
1097 int pol = ACL_COND_NONE;
1098 struct acl_cond *cond;
1099 struct redirect_rule *rule;
1100 int cur_arg;
1101 int type = REDIRECT_TYPE_NONE;
1102 int code = 302;
1103 char *destination = NULL;
1104
1105 cur_arg = 1;
1106 while (*(args[cur_arg])) {
1107 if (!strcmp(args[cur_arg], "location")) {
1108 if (!*args[cur_arg + 1]) {
1109 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1110 file, linenum, args[0], args[cur_arg]);
1111 return -1;
1112 }
1113
1114 type = REDIRECT_TYPE_LOCATION;
1115 cur_arg++;
1116 destination = args[cur_arg];
1117 }
1118 else if (!strcmp(args[cur_arg], "prefix")) {
1119 if (!*args[cur_arg + 1]) {
1120 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1121 file, linenum, args[0], args[cur_arg]);
1122 return -1;
1123 }
1124
1125 type = REDIRECT_TYPE_PREFIX;
1126 cur_arg++;
1127 destination = args[cur_arg];
1128 }
1129 else if (!strcmp(args[cur_arg],"code")) {
1130 if (!*args[cur_arg + 1]) {
1131 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1132 file, linenum, args[0]);
1133 return -1;
1134 }
1135 cur_arg++;
1136 code = atol(args[cur_arg]);
1137 if (code < 301 || code > 303) {
1138 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1139 file, linenum, args[0], code);
1140 return -1;
1141 }
1142 }
1143 else if (!strcmp(args[cur_arg], "if")) {
1144 pol = ACL_COND_IF;
1145 cur_arg++;
1146 break;
1147 }
1148 else if (!strcmp(args[cur_arg], "unless")) {
1149 pol = ACL_COND_UNLESS;
1150 cur_arg++;
1151 break;
1152 }
1153 else {
1154 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1155 file, linenum, args[0], args[cur_arg]);
1156 return -1;
1157 }
1158 cur_arg++;
1159 }
1160
1161 if (type == REDIRECT_TYPE_NONE) {
1162 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1163 file, linenum, args[0]);
1164 return -1;
1165 }
1166
1167 if (pol == ACL_COND_NONE) {
1168 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1169 file, linenum, args[0]);
1170 return -1;
1171 }
1172
1173 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1174 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1175 file, linenum, args[0]);
1176 return -1;
1177 }
1178
Willy Tarreaua9802632008-07-25 19:13:19 +02001179 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001180 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1181 rule->cond = cond;
1182 rule->rdr_str = strdup(destination);
1183 rule->rdr_len = strlen(destination);
1184 rule->type = type;
1185 rule->code = code;
1186 LIST_INIT(&rule->list);
1187 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1188 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001189 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1190 int pol = ACL_COND_NONE;
1191 struct acl_cond *cond;
1192 struct switching_rule *rule;
1193
1194 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1195 return 0;
1196
1197 if (*(args[1]) == 0) {
1198 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1199 return -1;
1200 }
1201
1202 if (!strcmp(args[2], "if"))
1203 pol = ACL_COND_IF;
1204 else if (!strcmp(args[2], "unless"))
1205 pol = ACL_COND_UNLESS;
1206
1207 if (pol == ACL_COND_NONE) {
1208 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1209 file, linenum, args[0]);
1210 return -1;
1211 }
1212
1213 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001214 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001215 file, linenum);
1216 return -1;
1217 }
1218
Willy Tarreaua9802632008-07-25 19:13:19 +02001219 cond->line = linenum;
1220 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001221 struct acl *acl;
1222 const char *name;
1223
1224 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1225 name = acl ? acl->name : "(unknown)";
1226 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1227 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001228 }
1229
Willy Tarreau55ea7572007-06-17 19:56:27 +02001230 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1231 rule->cond = cond;
1232 rule->be.name = strdup(args[1]);
1233 LIST_INIT(&rule->list);
1234 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001236 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001237 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1238 return 0;
1239
Willy Tarreaubaaee002006-06-26 02:48:02 +02001240 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1241 curproxy->uri_auth = NULL; /* we must detach from the default config */
1242
1243 if (*(args[1]) == 0) {
1244 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1245 return -1;
1246 } else if (!strcmp(args[1], "uri")) {
1247 if (*(args[2]) == 0) {
1248 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1249 return -1;
1250 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1251 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1252 return -1;
1253 }
1254 } else if (!strcmp(args[1], "realm")) {
1255 if (*(args[2]) == 0) {
1256 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1257 return -1;
1258 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1259 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1260 return -1;
1261 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001262 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001263 unsigned interval;
1264
1265 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1266 if (err) {
1267 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1268 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001269 return -1;
1270 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1271 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1272 return -1;
1273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 } else if (!strcmp(args[1], "auth")) {
1275 if (*(args[2]) == 0) {
1276 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1277 return -1;
1278 } else if (!stats_add_auth(&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], "scope")) {
1283 if (*(args[2]) == 0) {
1284 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1285 return -1;
1286 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1287 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1288 return -1;
1289 }
1290 } else if (!strcmp(args[1], "enable")) {
1291 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1292 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1293 return -1;
1294 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001295 } else if (!strcmp(args[1], "hide-version")) {
1296 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1297 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1298 return -1;
1299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001300 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001301 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001302 file, linenum, args[0]);
1303 return -1;
1304 }
1305 }
1306 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001307 int optnum;
1308
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001309 if (*(args[1]) == '\0') {
1310 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1311 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001312 return -1;
1313 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001314
1315 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1316 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1317 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1318 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001319
1320 if (!inv)
1321 curproxy->options |= cfg_opts[optnum].val;
1322 else
1323 curproxy->options &= ~cfg_opts[optnum].val;
1324
Willy Tarreau13943ab2006-12-31 00:24:10 +01001325 return 0;
1326 }
1327 }
1328
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001329 if (inv) {
1330 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1331 file, linenum, args[1]);
1332 return -1;
1333 }
1334
Willy Tarreau13943ab2006-12-31 00:24:10 +01001335 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001336 /* generate a complete HTTP log */
1337 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1338 else if (!strcmp(args[1], "tcplog"))
1339 /* generate a detailed TCP log */
1340 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001341 else if (!strcmp(args[1], "tcpka")) {
1342 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001343 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1344 return 0;
1345
1346 if (curproxy->cap & PR_CAP_FE)
1347 curproxy->options |= PR_O_TCP_CLI_KA;
1348 if (curproxy->cap & PR_CAP_BE)
1349 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001350 }
1351 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001352 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1353 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001354 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001355 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001356 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001357 curproxy->options &= ~PR_O_SMTP_CHK;
1358 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001359 if (!*args[2]) { /* no argument */
1360 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1361 curproxy->check_len = strlen(DEF_CHECK_REQ);
1362 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001363 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001364 curproxy->check_req = (char *)malloc(reqlen);
1365 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1366 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1367 } else { /* more arguments : METHOD URI [HTTP_VER] */
1368 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1369 if (*args[4])
1370 reqlen += strlen(args[4]);
1371 else
1372 reqlen += strlen("HTTP/1.0");
1373
1374 curproxy->check_req = (char *)malloc(reqlen);
1375 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1376 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1377 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001378 }
1379 else if (!strcmp(args[1], "ssl-hello-chk")) {
1380 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001381 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1382 return 0;
1383
Willy Tarreaua534fea2008-08-03 12:19:50 +02001384 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001385 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001386 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001387 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388 }
Willy Tarreau23677902007-05-08 23:50:35 +02001389 else if (!strcmp(args[1], "smtpchk")) {
1390 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001391 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001392 curproxy->options &= ~PR_O_HTTP_CHK;
1393 curproxy->options &= ~PR_O_SSL3_CHK;
1394 curproxy->options |= PR_O_SMTP_CHK;
1395
1396 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1397 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1398 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1399 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1400 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1401 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1402 curproxy->check_req = (char *)malloc(reqlen);
1403 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1404 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1405 } else {
1406 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1407 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1408 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1409 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1410 }
1411 }
1412 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001413 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001414 int cur_arg;
1415
1416 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1417 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001418 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001419
1420 curproxy->options |= PR_O_FWDFOR;
1421
1422 free(curproxy->fwdfor_hdr_name);
1423 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1424 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1425
1426 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1427 cur_arg = 2;
1428 while (*(args[cur_arg])) {
1429 if (!strcmp(args[cur_arg], "except")) {
1430 /* suboption except - needs additional argument for it */
1431 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1432 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1433 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001434 return -1;
1435 }
1436 /* flush useless bits */
1437 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001438 cur_arg += 2;
1439 } else if (!strcmp(args[cur_arg], "header")) {
1440 /* suboption header - needs additional argument for it */
1441 if (*(args[cur_arg+1]) == 0) {
1442 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1443 file, linenum, args[0], args[1], args[cur_arg]);
1444 return -1;
1445 }
1446 free(curproxy->fwdfor_hdr_name);
1447 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1448 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1449 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001450 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001451 /* unknown suboption - catchall */
1452 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1453 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001454 return -1;
1455 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001456 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001457 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001458 else {
1459 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1460 return -1;
1461 }
1462 return 0;
1463 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001464 else if (!strcmp(args[0], "default_backend")) {
1465 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1466 return 0;
1467
1468 if (*(args[1]) == 0) {
1469 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1470 return -1;
1471 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001472 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001473 curproxy->defbe.name = strdup(args[1]);
1474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001475 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001476 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1477 return 0;
1478
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001479 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1480 file, linenum, args[0]);
1481
Willy Tarreaubaaee002006-06-26 02:48:02 +02001482 /* enable reconnections to dispatch */
1483 curproxy->options |= PR_O_REDISP;
1484 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001485 else if (!strcmp(args[0], "http-check")) {
1486 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1487 return 0;
1488
1489 if (strcmp(args[1], "disable-on-404") == 0) {
1490 /* enable a graceful server shutdown on an HTTP 404 response */
1491 curproxy->options |= PR_O_DISABLE404;
1492 }
1493 else {
1494 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1495 return -1;
1496 }
1497 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001498 else if (!strcmp(args[0], "monitor")) {
1499 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1500 return 0;
1501
1502 if (strcmp(args[1], "fail") == 0) {
1503 /* add a condition to fail monitor requests */
1504 int pol = ACL_COND_NONE;
1505 struct acl_cond *cond;
1506
1507 if (!strcmp(args[2], "if"))
1508 pol = ACL_COND_IF;
1509 else if (!strcmp(args[2], "unless"))
1510 pol = ACL_COND_UNLESS;
1511
1512 if (pol == ACL_COND_NONE) {
1513 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1514 file, linenum, args[0], args[1]);
1515 return -1;
1516 }
1517
1518 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1519 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1520 file, linenum, args[0], args[1]);
1521 return -1;
1522 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001523 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001524 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1525 }
1526 else {
1527 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1528 return -1;
1529 }
1530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001531#ifdef TPROXY
1532 else if (!strcmp(args[0], "transparent")) {
1533 /* enable transparent proxy connections */
1534 curproxy->options |= PR_O_TRANSP;
1535 }
1536#endif
1537 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001538 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1539 return 0;
1540
Willy Tarreaubaaee002006-06-26 02:48:02 +02001541 if (*(args[1]) == 0) {
1542 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1543 return -1;
1544 }
1545 curproxy->maxconn = atol(args[1]);
1546 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001547 else if (!strcmp(args[0], "backlog")) { /* backlog */
1548 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1549 return 0;
1550
1551 if (*(args[1]) == 0) {
1552 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1553 return -1;
1554 }
1555 curproxy->backlog = atol(args[1]);
1556 }
Willy Tarreau86034312006-12-29 00:10:33 +01001557 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001558 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1559 return 0;
1560
Willy Tarreau86034312006-12-29 00:10:33 +01001561 if (*(args[1]) == 0) {
1562 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1563 return -1;
1564 }
1565 curproxy->fullconn = atol(args[1]);
1566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1568 if (*(args[1]) == 0) {
1569 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1570 return -1;
1571 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001572 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1573 if (err) {
1574 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1575 file, linenum, *err);
1576 return -1;
1577 }
1578 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 }
1580 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1581 if (curproxy == &defproxy) {
1582 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1583 return -1;
1584 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001585 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1586 return 0;
1587
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 if (strchr(args[1], ':') == NULL) {
1589 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1590 return -1;
1591 }
1592 curproxy->dispatch_addr = *str2sa(args[1]);
1593 }
1594 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001595 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1596 return 0;
1597
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001598 memcpy(trash, "error near 'balance'", 19);
1599 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1600 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1601 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 }
1604 else if (!strcmp(args[0], "server")) { /* server address */
1605 int cur_arg;
1606 char *rport;
1607 char *raddr;
1608 short realport;
1609 int do_check;
1610
1611 if (curproxy == &defproxy) {
1612 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1613 return -1;
1614 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001615 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1616 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001617
1618 if (!*args[2]) {
1619 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1620 file, linenum, args[0]);
1621 return -1;
1622 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001623
1624 err = invalid_char(args[1]);
1625 if (err) {
1626 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1627 file, linenum, *err, args[1]);
1628 return -1;
1629 }
1630
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1632 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1633 return -1;
1634 }
1635
1636 /* the servers are linked backwards first */
1637 newsrv->next = curproxy->srv;
1638 curproxy->srv = newsrv;
1639 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001640 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001641
1642 LIST_INIT(&newsrv->pendconns);
1643 do_check = 0;
1644 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001645 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001646 newsrv->id = strdup(args[1]);
1647
1648 /* several ways to check the port component :
1649 * - IP => port=+0, relative
1650 * - IP: => port=+0, relative
1651 * - IP:N => port=N, absolute
1652 * - IP:+N => port=+N, relative
1653 * - IP:-N => port=-N, relative
1654 */
1655 raddr = strdup(args[2]);
1656 rport = strchr(raddr, ':');
1657 if (rport) {
1658 *rport++ = 0;
1659 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001660 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001661 newsrv->state |= SRV_MAPPORTS;
1662 } else {
1663 realport = 0;
1664 newsrv->state |= SRV_MAPPORTS;
1665 }
1666
1667 newsrv->addr = *str2sa(raddr);
1668 newsrv->addr.sin_port = htons(realport);
1669 free(raddr);
1670
1671 newsrv->curfd = -1; /* no health-check in progress */
1672 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001673 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1674 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001675 newsrv->rise = DEF_RISETIME;
1676 newsrv->fall = DEF_FALLTIME;
1677 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001678 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001679 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001680 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001681
Willy Tarreaubaaee002006-06-26 02:48:02 +02001682 cur_arg = 3;
1683 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001684 if (!strcmp(args[cur_arg], "id")) {
1685 struct server *target;
1686
1687 if (!*args[cur_arg + 1]) {
1688 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1689 file, linenum, args[cur_arg]);
1690 return -1;
1691 }
1692
1693 newsrv->puid = atol(args[cur_arg + 1]);
1694
1695 if (newsrv->puid< 1001) {
1696 Alert("parsing [%s:%d]: custom id has to be > 1000",
1697 file, linenum);
1698 return -1;
1699 }
1700
1701 for (target = proxy->srv; target; target = target->next)
1702 if (newsrv != target && newsrv->puid == target->puid) {
1703 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1704 file, linenum, newsrv->id, target->id);
1705 return -1;
1706 }
1707 cur_arg += 2;
1708 }
1709 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710 newsrv->cookie = strdup(args[cur_arg + 1]);
1711 newsrv->cklen = strlen(args[cur_arg + 1]);
1712 cur_arg += 2;
1713 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001714 else if (!strcmp(args[cur_arg], "redir")) {
1715 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1716 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1717 cur_arg += 2;
1718 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001719 else if (!strcmp(args[cur_arg], "rise")) {
1720 newsrv->rise = atol(args[cur_arg + 1]);
1721 newsrv->health = newsrv->rise;
1722 cur_arg += 2;
1723 }
1724 else if (!strcmp(args[cur_arg], "fall")) {
1725 newsrv->fall = atol(args[cur_arg + 1]);
1726 cur_arg += 2;
1727 }
1728 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001729 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1730 if (err) {
1731 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1732 file, linenum, *err, newsrv->id);
1733 return -1;
1734 }
1735 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 cur_arg += 2;
1737 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001738 else if (!strcmp(args[cur_arg], "fastinter")) {
1739 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1740 if (err) {
1741 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1742 file, linenum, *err, newsrv->id);
1743 return -1;
1744 }
1745 newsrv->fastinter = val;
1746 cur_arg += 2;
1747 }
1748 else if (!strcmp(args[cur_arg], "downinter")) {
1749 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1750 if (err) {
1751 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1752 file, linenum, *err, newsrv->id);
1753 return -1;
1754 }
1755 newsrv->downinter = val;
1756 cur_arg += 2;
1757 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001758 else if (!strcmp(args[cur_arg], "addr")) {
1759 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001760 cur_arg += 2;
1761 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001762 else if (!strcmp(args[cur_arg], "port")) {
1763 newsrv->check_port = atol(args[cur_arg + 1]);
1764 cur_arg += 2;
1765 }
1766 else if (!strcmp(args[cur_arg], "backup")) {
1767 newsrv->state |= SRV_BACKUP;
1768 cur_arg ++;
1769 }
1770 else if (!strcmp(args[cur_arg], "weight")) {
1771 int w;
1772 w = atol(args[cur_arg + 1]);
1773 if (w < 1 || w > 256) {
1774 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1775 file, linenum, newsrv->id, w);
1776 return -1;
1777 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001778 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001779 cur_arg += 2;
1780 }
1781 else if (!strcmp(args[cur_arg], "minconn")) {
1782 newsrv->minconn = atol(args[cur_arg + 1]);
1783 cur_arg += 2;
1784 }
1785 else if (!strcmp(args[cur_arg], "maxconn")) {
1786 newsrv->maxconn = atol(args[cur_arg + 1]);
1787 cur_arg += 2;
1788 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001789 else if (!strcmp(args[cur_arg], "maxqueue")) {
1790 newsrv->maxqueue = atol(args[cur_arg + 1]);
1791 cur_arg += 2;
1792 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001793 else if (!strcmp(args[cur_arg], "slowstart")) {
1794 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001795 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001796 if (err) {
1797 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1798 file, linenum, *err, newsrv->id);
1799 return -1;
1800 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001801 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001802 cur_arg += 2;
1803 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001804 else if (!strcmp(args[cur_arg], "track")) {
1805
1806 if (!*args[cur_arg + 1]) {
1807 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1808 file, linenum);
1809 return -1;
1810 }
1811
1812 newsrv->trackit = strdup(args[cur_arg + 1]);
1813
1814 cur_arg += 2;
1815 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001816 else if (!strcmp(args[cur_arg], "check")) {
1817 global.maxsock++;
1818 do_check = 1;
1819 cur_arg += 1;
1820 }
1821 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1822 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001823#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001824 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1825 file, linenum, "source", "usesrc");
1826#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001827 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1828 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001829#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001830 return -1;
1831 }
1832 newsrv->state |= SRV_BIND_SRC;
1833 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1834 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001835 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001836#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1837#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001838 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001839 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1840 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001841 return -1;
1842 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001843#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001844 if (!*args[cur_arg + 1]) {
1845 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1846 file, linenum, "usesrc");
1847 return -1;
1848 }
1849 if (!strcmp(args[cur_arg + 1], "client")) {
1850 newsrv->state |= SRV_TPROXY_CLI;
1851 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1852 newsrv->state |= SRV_TPROXY_CIP;
1853 } else {
1854 newsrv->state |= SRV_TPROXY_ADDR;
1855 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1856 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001857 global.last_checks |= LSTCHK_NETADM;
1858#if !defined(CONFIG_HAP_LINUX_TPROXY)
1859 global.last_checks |= LSTCHK_CTTPROXY;
1860#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001861 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001862#else /* no TPROXY support */
1863 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001864 file, linenum, "usesrc");
1865 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001866#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001867 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001869 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1870 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1871 file, linenum, "usesrc", "source");
1872 return -1;
1873 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001874 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001875 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 +02001876 file, linenum, newsrv->id);
1877 return -1;
1878 }
1879 }
1880
1881 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001882 if (newsrv->trackit) {
1883 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1884 file, linenum);
1885 return -1;
1886 }
1887
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001888 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1889 newsrv->check_port = newsrv->check_addr.sin_port;
1890
Willy Tarreaubaaee002006-06-26 02:48:02 +02001891 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1892 newsrv->check_port = realport; /* by default */
1893 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001894 /* not yet valid, because no port was set on
1895 * the server either. We'll check if we have
1896 * a known port on the first listener.
1897 */
1898 struct listener *l;
1899 l = curproxy->listen;
1900 if (l) {
1901 int port;
1902 port = (l->addr.ss_family == AF_INET6)
1903 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1904 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1905 newsrv->check_port = port;
1906 }
1907 }
1908 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1910 file, linenum, newsrv->id);
1911 return -1;
1912 }
1913 newsrv->state |= SRV_CHECKED;
1914 }
1915
1916 if (newsrv->state & SRV_BACKUP)
1917 curproxy->srv_bck++;
1918 else
1919 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001920
1921 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001922 }
1923 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001924 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 int facility;
1926
1927 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1928 curproxy->logfac1 = global.logfac1;
1929 curproxy->logsrv1 = global.logsrv1;
1930 curproxy->loglev1 = global.loglev1;
1931 curproxy->logfac2 = global.logfac2;
1932 curproxy->logsrv2 = global.logsrv2;
1933 curproxy->loglev2 = global.loglev2;
1934 }
1935 else if (*(args[1]) && *(args[2])) {
1936 int level;
1937
1938 facility = get_log_facility(args[2]);
1939 if (facility < 0) {
1940 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1941 exit(1);
1942 }
1943
1944 level = 7; /* max syslog level = debug */
1945 if (*(args[3])) {
1946 level = get_log_level(args[3]);
1947 if (level < 0) {
1948 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1949 exit(1);
1950 }
1951 }
1952
Robert Tsai81ae1952007-12-05 10:47:29 +01001953 if (args[1][0] == '/') {
1954 logsrv.u.addr.sa_family = AF_UNIX;
1955 logsrv.u.un = *str2sun(args[1]);
1956 } else {
1957 logsrv.u.addr.sa_family = AF_INET;
1958 logsrv.u.in = *str2sa(args[1]);
1959 if (!logsrv.u.in.sin_port) {
1960 logsrv.u.in.sin_port =
1961 htons(SYSLOG_PORT);
1962 }
1963 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001964
1965 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001966 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001967 curproxy->logfac1 = facility;
1968 curproxy->loglev1 = level;
1969 }
1970 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001971 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001972 curproxy->logfac2 = facility;
1973 curproxy->loglev2 = level;
1974 }
1975 else {
1976 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1977 return -1;
1978 }
1979 }
1980 else {
1981 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1982 file, linenum);
1983 return -1;
1984 }
1985 }
1986 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001987 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1988 return 0;
1989
Willy Tarreaubaaee002006-06-26 02:48:02 +02001990 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001991#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001992 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1993 file, linenum, "source", "usesrc");
1994#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001995 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1996 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001997#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001998 return -1;
1999 }
2000
2001 curproxy->source_addr = *str2sa(args[1]);
2002 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01002003 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002004#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2005#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002006 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2007 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2008 file, linenum, "usesrc");
2009 return -1;
2010 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002011#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002012 if (!*args[3]) {
2013 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2014 file, linenum, "usesrc");
2015 return -1;
2016 }
2017
2018 if (!strcmp(args[3], "client")) {
2019 curproxy->options |= PR_O_TPXY_CLI;
2020 } else if (!strcmp(args[3], "clientip")) {
2021 curproxy->options |= PR_O_TPXY_CIP;
2022 } else {
2023 curproxy->options |= PR_O_TPXY_ADDR;
2024 curproxy->tproxy_addr = *str2sa(args[3]);
2025 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002026 global.last_checks |= LSTCHK_NETADM;
2027#if !defined(CONFIG_HAP_LINUX_TPROXY)
2028 global.last_checks |= LSTCHK_CTTPROXY;
2029#endif
2030#else /* no TPROXY support */
2031 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002032 file, linenum, "usesrc");
2033 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002034#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002035 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002036 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002037 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2038 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2039 file, linenum, "usesrc", "source");
2040 return -1;
2041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002042 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2043 regex_t *preg;
2044 if (curproxy == &defproxy) {
2045 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2046 return -1;
2047 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002048 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2049 return 0;
2050
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051 if (*(args[1]) == 0 || *(args[2]) == 0) {
2052 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2053 file, linenum, args[0]);
2054 return -1;
2055 }
2056
2057 preg = calloc(1, sizeof(regex_t));
2058 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2059 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2060 return -1;
2061 }
2062
2063 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2064 if (err) {
2065 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2066 file, linenum, *err);
2067 return -1;
2068 }
2069 }
2070 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2071 regex_t *preg;
2072 if (curproxy == &defproxy) {
2073 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2074 return -1;
2075 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002076 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2077 return 0;
2078
Willy Tarreaubaaee002006-06-26 02:48:02 +02002079 if (*(args[1]) == 0) {
2080 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2081 return -1;
2082 }
2083
2084 preg = calloc(1, sizeof(regex_t));
2085 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2086 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2087 return -1;
2088 }
2089
2090 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2091 }
2092 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2093 regex_t *preg;
2094 if (curproxy == &defproxy) {
2095 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2096 return -1;
2097 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002098 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2099 return 0;
2100
Willy Tarreaubaaee002006-06-26 02:48:02 +02002101 if (*(args[1]) == 0) {
2102 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2103 return -1;
2104 }
2105
2106 preg = calloc(1, sizeof(regex_t));
2107 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2108 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2109 return -1;
2110 }
2111
2112 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2113 }
2114 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2115 regex_t *preg;
2116 if (curproxy == &defproxy) {
2117 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2118 return -1;
2119 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002120 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2121 return 0;
2122
Willy Tarreaubaaee002006-06-26 02:48:02 +02002123 if (*(args[1]) == 0) {
2124 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2125 return -1;
2126 }
2127
2128 preg = calloc(1, sizeof(regex_t));
2129 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2130 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2131 return -1;
2132 }
2133
2134 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2135 }
2136 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2137 regex_t *preg;
2138 if (curproxy == &defproxy) {
2139 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2140 return -1;
2141 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002142 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2143 return 0;
2144
Willy Tarreaubaaee002006-06-26 02:48:02 +02002145 if (*(args[1]) == 0) {
2146 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2147 return -1;
2148 }
2149
2150 preg = calloc(1, sizeof(regex_t));
2151 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2152 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2153 return -1;
2154 }
2155
2156 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2157 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002158 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2159 regex_t *preg;
2160 if (curproxy == &defproxy) {
2161 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2162 return -1;
2163 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002164 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2165 return 0;
2166
Willy Tarreaub8750a82006-09-03 09:56:00 +02002167 if (*(args[1]) == 0) {
2168 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2169 return -1;
2170 }
2171
2172 preg = calloc(1, sizeof(regex_t));
2173 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2174 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2175 return -1;
2176 }
2177
2178 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2179 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002180 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2181 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002182 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002183 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2184 return -1;
2185 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002186 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2187 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002188
Willy Tarreau977b8e42006-12-29 14:19:17 +01002189 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002190 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2191 file, linenum, args[0]);
2192 return -1;
2193 }
2194
2195 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002196 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002197 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2198 }
2199
2200 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2201 }
2202 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2203 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002204 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002205 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2206 return -1;
2207 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002208 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2209 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002210
Willy Tarreau977b8e42006-12-29 14:19:17 +01002211 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002212 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2213 file, linenum, args[0]);
2214 return -1;
2215 }
2216
2217 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002218 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002219 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2220 }
2221
2222 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2223 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002224 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2225 regex_t *preg;
2226 if (curproxy == &defproxy) {
2227 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2228 return -1;
2229 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002230 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2231 return 0;
2232
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233 if (*(args[1]) == 0 || *(args[2]) == 0) {
2234 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2235 file, linenum, args[0]);
2236 return -1;
2237 }
2238
2239 preg = calloc(1, sizeof(regex_t));
2240 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2241 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2242 return -1;
2243 }
2244
2245 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2246 if (err) {
2247 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2248 file, linenum, *err);
2249 return -1;
2250 }
2251 }
2252 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2253 regex_t *preg;
2254 if (curproxy == &defproxy) {
2255 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2256 return -1;
2257 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002258 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2259 return 0;
2260
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 if (*(args[1]) == 0) {
2262 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2263 return -1;
2264 }
2265
2266 preg = calloc(1, sizeof(regex_t));
2267 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2268 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2269 return -1;
2270 }
2271
2272 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2273 }
2274 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2275 regex_t *preg;
2276 if (curproxy == &defproxy) {
2277 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2278 return -1;
2279 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002280 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2281 return 0;
2282
Willy Tarreaubaaee002006-06-26 02:48:02 +02002283 if (*(args[1]) == 0) {
2284 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2285 return -1;
2286 }
2287
2288 preg = calloc(1, sizeof(regex_t));
2289 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2290 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2291 return -1;
2292 }
2293
2294 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2295 }
2296 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2297 regex_t *preg;
2298 if (curproxy == &defproxy) {
2299 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2300 return -1;
2301 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002302 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2303 return 0;
2304
Willy Tarreaubaaee002006-06-26 02:48:02 +02002305 if (*(args[1]) == 0) {
2306 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2307 return -1;
2308 }
2309
2310 preg = calloc(1, sizeof(regex_t));
2311 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2312 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2313 return -1;
2314 }
2315
2316 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2317 }
2318 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2319 regex_t *preg;
2320 if (curproxy == &defproxy) {
2321 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2322 return -1;
2323 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002324 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2325 return 0;
2326
Willy Tarreaubaaee002006-06-26 02:48:02 +02002327 if (*(args[1]) == 0) {
2328 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2329 return -1;
2330 }
2331
2332 preg = calloc(1, sizeof(regex_t));
2333 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2334 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2335 return -1;
2336 }
2337
2338 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2339 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002340 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2341 regex_t *preg;
2342 if (curproxy == &defproxy) {
2343 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2344 return -1;
2345 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002346 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2347 return 0;
2348
Willy Tarreaub8750a82006-09-03 09:56:00 +02002349 if (*(args[1]) == 0) {
2350 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2351 return -1;
2352 }
2353
2354 preg = calloc(1, sizeof(regex_t));
2355 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2356 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2357 return -1;
2358 }
2359
2360 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2361 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2363 if (curproxy == &defproxy) {
2364 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2365 return -1;
2366 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002367 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2368 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369
2370 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2371 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2372 return 0;
2373 }
2374
2375 if (*(args[1]) == 0) {
2376 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2377 return -1;
2378 }
2379
2380 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2381 }
2382 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2383 regex_t *preg;
2384
2385 if (*(args[1]) == 0 || *(args[2]) == 0) {
2386 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2387 file, linenum, args[0]);
2388 return -1;
2389 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002390 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2391 return 0;
2392
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 preg = calloc(1, sizeof(regex_t));
2394 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2395 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2396 return -1;
2397 }
2398
2399 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2400 if (err) {
2401 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2402 file, linenum, *err);
2403 return -1;
2404 }
2405 }
2406 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2407 regex_t *preg;
2408 if (curproxy == &defproxy) {
2409 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2410 return -1;
2411 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002412 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2413 return 0;
2414
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 if (*(args[1]) == 0) {
2416 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2417 return -1;
2418 }
2419
2420 preg = calloc(1, sizeof(regex_t));
2421 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2422 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2423 return -1;
2424 }
2425
2426 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2427 if (err) {
2428 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2429 file, linenum, *err);
2430 return -1;
2431 }
2432 }
2433 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2434 regex_t *preg;
2435 if (curproxy == &defproxy) {
2436 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2437 return -1;
2438 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002439 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2440 return 0;
2441
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 if (*(args[1]) == 0) {
2443 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2444 return -1;
2445 }
2446
2447 preg = calloc(1, sizeof(regex_t));
2448 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2449 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2450 return -1;
2451 }
2452
2453 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2454 if (err) {
2455 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2456 file, linenum, *err);
2457 return -1;
2458 }
2459 }
2460 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2461 regex_t *preg;
2462 if (curproxy == &defproxy) {
2463 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2464 return -1;
2465 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002466 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2467 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468
2469 if (*(args[1]) == 0 || *(args[2]) == 0) {
2470 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2471 file, linenum, args[0]);
2472 return -1;
2473 }
2474
2475 preg = calloc(1, sizeof(regex_t));
2476 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2477 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2478 return -1;
2479 }
2480
2481 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2482 if (err) {
2483 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2484 file, linenum, *err);
2485 return -1;
2486 }
2487 }
2488 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2489 regex_t *preg;
2490 if (curproxy == &defproxy) {
2491 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2492 return -1;
2493 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002494 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2495 return 0;
2496
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497 if (*(args[1]) == 0) {
2498 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2499 return -1;
2500 }
2501
2502 preg = calloc(1, sizeof(regex_t));
2503 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2504 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2505 return -1;
2506 }
2507
2508 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2509 if (err) {
2510 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2511 file, linenum, *err);
2512 return -1;
2513 }
2514 }
2515 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2516 regex_t *preg;
2517 if (curproxy == &defproxy) {
2518 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2519 return -1;
2520 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002521 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2522 return 0;
2523
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 if (*(args[1]) == 0) {
2525 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2526 return -1;
2527 }
2528
2529 preg = calloc(1, sizeof(regex_t));
2530 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2531 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2532 return -1;
2533 }
2534
2535 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2536 if (err) {
2537 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2538 file, linenum, *err);
2539 return -1;
2540 }
2541 }
2542 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2543 if (curproxy == &defproxy) {
2544 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2545 return -1;
2546 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002547 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2548 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549
2550 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2551 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2552 return 0;
2553 }
2554
2555 if (*(args[1]) == 0) {
2556 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2557 return -1;
2558 }
2559
2560 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2561 }
2562 else if (!strcmp(args[0], "errorloc") ||
2563 !strcmp(args[0], "errorloc302") ||
2564 !strcmp(args[0], "errorloc303")) { /* error location */
2565 int errnum, errlen;
2566 char *err;
2567
Willy Tarreau977b8e42006-12-29 14:19:17 +01002568 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2569 return 0;
2570
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002572 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 return -1;
2574 }
2575
2576 errnum = atol(args[1]);
2577 if (!strcmp(args[0], "errorloc303")) {
2578 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2579 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2580 } else {
2581 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2582 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2583 }
2584
Willy Tarreau0f772532006-12-23 20:51:41 +01002585 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2586 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002587 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002588 curproxy->errmsg[rc].str = err;
2589 curproxy->errmsg[rc].len = errlen;
2590 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002593
2594 if (rc >= HTTP_ERR_SIZE) {
2595 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2596 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 free(err);
2598 }
2599 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002600 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2601 int errnum, errlen, fd;
2602 char *err;
2603 struct stat stat;
2604
2605 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2606 return 0;
2607
2608 if (*(args[2]) == 0) {
2609 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2610 return -1;
2611 }
2612
2613 fd = open(args[2], O_RDONLY);
2614 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2615 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2616 file, linenum, args[2], args[1]);
2617 if (fd >= 0)
2618 close(fd);
2619 return -1;
2620 }
2621
2622 if (stat.st_size <= BUFSIZE) {
2623 errlen = stat.st_size;
2624 } else {
2625 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2626 file, linenum, args[2], BUFSIZE);
2627 errlen = BUFSIZE;
2628 }
2629
2630 err = malloc(errlen); /* malloc() must succeed during parsing */
2631 errnum = read(fd, err, errlen);
2632 if (errnum != errlen) {
2633 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2634 file, linenum, args[2], args[1]);
2635 close(fd);
2636 free(err);
2637 return -1;
2638 }
2639 close(fd);
2640
2641 errnum = atol(args[1]);
2642 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2643 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002644 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002645 curproxy->errmsg[rc].str = err;
2646 curproxy->errmsg[rc].len = errlen;
2647 break;
2648 }
2649 }
2650
2651 if (rc >= HTTP_ERR_SIZE) {
2652 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2653 file, linenum, errnum);
2654 free(err);
2655 }
2656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002658 struct cfg_kw_list *kwl;
2659 int index;
2660
2661 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2662 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2663 if (kwl->kw[index].section != CFG_LISTEN)
2664 continue;
2665 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2666 /* prepare error message just in case */
2667 snprintf(trash, sizeof(trash),
2668 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002669 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2670 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002671 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2672 return -1;
2673 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002674 else if (rc > 0) {
2675 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2676 return 0;
2677 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002678 return 0;
2679 }
2680 }
2681 }
2682
Willy Tarreau6daf3432008-01-22 16:44:08 +01002683 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 return -1;
2685 }
2686 return 0;
2687}
2688
2689
2690/*
2691 * This function reads and parses the configuration file given in the argument.
2692 * returns 0 if OK, -1 if error.
2693 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002694int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002696 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002697 FILE *f;
2698 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 int confsect = CFG_NONE;
2701
2702 struct proxy *curproxy = NULL;
2703 struct server *newsrv = NULL;
2704
2705 if ((f=fopen(file,"r")) == NULL)
2706 return -1;
2707
2708 init_default_instance();
2709
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002710 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002711 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002712 char *end;
2713 char *args[MAX_LINE_ARGS + 1];
2714 char *line = thisline;
2715
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716 linenum++;
2717
2718 end = line + strlen(line);
2719
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002720 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2721 /* Check if we reached the limit and the last char is not \n.
2722 * Watch out for the last line without the terminating '\n'!
2723 */
2724 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2725 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002726 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002727 }
2728
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002730 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 line++;
2732
2733 arg = 0;
2734 args[arg] = line;
2735
2736 while (*line && arg < MAX_LINE_ARGS) {
2737 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2738 * C equivalent value. Other combinations left unchanged (eg: \1).
2739 */
2740 if (*line == '\\') {
2741 int skip = 0;
2742 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2743 *line = line[1];
2744 skip = 1;
2745 }
2746 else if (line[1] == 'r') {
2747 *line = '\r';
2748 skip = 1;
2749 }
2750 else if (line[1] == 'n') {
2751 *line = '\n';
2752 skip = 1;
2753 }
2754 else if (line[1] == 't') {
2755 *line = '\t';
2756 skip = 1;
2757 }
2758 else if (line[1] == 'x') {
2759 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2760 unsigned char hex1, hex2;
2761 hex1 = toupper(line[2]) - '0';
2762 hex2 = toupper(line[3]) - '0';
2763 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2764 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2765 *line = (hex1<<4) + hex2;
2766 skip = 3;
2767 }
2768 else {
2769 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002770 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002771 }
2772 }
2773 if (skip) {
2774 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2775 end -= skip;
2776 }
2777 line++;
2778 }
2779 else if (*line == '#' || *line == '\n' || *line == '\r') {
2780 /* end of string, end of loop */
2781 *line = 0;
2782 break;
2783 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002784 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002786 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002787 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002788 line++;
2789 args[++arg] = line;
2790 }
2791 else {
2792 line++;
2793 }
2794 }
2795
2796 /* empty line */
2797 if (!**args)
2798 continue;
2799
Willy Tarreau540abe42007-05-02 20:50:16 +02002800 /* zero out remaining args and ensure that at least one entry
2801 * is zeroed out.
2802 */
2803 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804 args[arg] = line;
2805 }
2806
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002807 if (!strcmp(args[0], "no")) {
2808 inv = 1;
2809 for (arg=0; *args[arg+1]; arg++)
2810 args[arg] = args[arg+1]; // shift args after inversion
2811 }
2812
2813 if (inv && strcmp(args[0], "option")) {
2814 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002815 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002816 }
2817
Willy Tarreau977b8e42006-12-29 14:19:17 +01002818 if (!strcmp(args[0], "listen") ||
2819 !strcmp(args[0], "frontend") ||
2820 !strcmp(args[0], "backend") ||
2821 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002822 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002824 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002825 cursection = strdup(args[0]);
2826 }
2827 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002829 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002830 cursection = strdup(args[0]);
2831 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832 /* else it's a section keyword */
2833
2834 switch (confsect) {
2835 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002836 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002837 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002838 break;
2839 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002840 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002841 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002842 break;
2843 default:
2844 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002845 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002846 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002847 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002848 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002849 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002850 fclose(f);
2851
2852 /*
2853 * Now, check for the integrity of all that we have collected.
2854 */
2855
2856 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002857 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002858
2859 if ((curproxy = proxy) == NULL) {
2860 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2861 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002862 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002863 }
2864
2865 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002866 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002867 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002868
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02002870 /* ensure we don't keep listeners uselessly bound */
2871 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 curproxy = curproxy->next;
2873 continue;
2874 }
2875
Willy Tarreau977b8e42006-12-29 14:19:17 +01002876 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2877 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 +01002878 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879 cfgerr++;
2880 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002881 else if (curproxy->cap & PR_CAP_BE &&
2882 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002883 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002884 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002885 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2886 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 +01002887 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002888 cfgerr++;
2889 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002890
Willy Tarreau31682232007-11-29 15:38:04 +01002891 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002893 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002894 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002895 cfgerr++;
2896 }
2897#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2898 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002899 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002900 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 cfgerr++;
2902 }
2903#endif
2904 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002905 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002906 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907 }
2908 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002909
2910 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002911 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002912 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002913 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002916 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002917 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918 }
2919 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002920 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002921 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002922 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002923 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002924 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002925 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002926 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002927 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002928 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2929 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002930
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002931 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002932 file, proxy_type_str(curproxy), curproxy->id);
2933 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002935
2936 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2937 if ((newsrv = curproxy->srv) != NULL) {
2938 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2939 file, proxy_type_str(curproxy), curproxy->id);
2940 }
2941 }
2942
2943 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002944 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2945 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2946 file, curproxy->id);
2947 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002948 }
2949 }
2950
Willy Tarreau82936582007-11-30 15:20:09 +01002951 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2952 curproxy->options &= ~PR_O_DISABLE404;
2953 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2954 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2955 }
2956
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002957 /* if a default backend was specified, let's find it */
2958 if (curproxy->defbe.name) {
2959 struct proxy *target;
2960
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002961 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2962 if (!target) {
2963 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2964 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002965 cfgerr++;
2966 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002967 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2968 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002969 } else {
2970 free(curproxy->defbe.name);
2971 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002972 }
2973 }
2974
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002975 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002976 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2977 /* map jump target for ACT_SETBE in req_rep chain */
2978 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002979 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002980 struct proxy *target;
2981
Willy Tarreaua496b602006-12-17 23:15:24 +01002982 if (exp->action != ACT_SETBE)
2983 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002984
2985 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2986 if (!target) {
2987 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2988 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002989 cfgerr++;
2990 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002991 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2992 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002993 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002994 } else {
2995 free((void *)exp->replace);
2996 exp->replace = (const char *)target;
2997 }
2998 }
2999 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003000
3001 /* find the target proxy for 'use_backend' rules */
3002 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003003 struct proxy *target;
3004
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003005 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003006
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003007 if (!target) {
3008 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3009 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003010 cfgerr++;
3011 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003012 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3013 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003014 cfgerr++;
3015 } else {
3016 free((void *)rule->be.name);
3017 rule->be.backend = target;
3018 }
3019 }
3020
Willy Tarreau2738a142006-07-08 17:28:09 +02003021 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003022 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003023 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003024 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003025 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003026 " | While not properly invalid, you will certainly encounter various problems\n"
3027 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003028 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003029 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003030 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003031
Willy Tarreau1fa31262007-12-03 00:36:16 +01003032 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3033 * We must still support older configurations, so let's find out whether those
3034 * parameters have been set or must be copied from contimeouts.
3035 */
3036 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003037 if (!curproxy->timeout.tarpit ||
3038 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003039 /* tarpit timeout not set. We search in the following order:
3040 * default.tarpit, curr.connect, default.connect.
3041 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003042 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003043 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003044 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003045 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003046 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003047 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003048 }
3049 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003050 (!curproxy->timeout.queue ||
3051 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003052 /* queue timeout not set. We search in the following order:
3053 * default.queue, curr.connect, default.connect.
3054 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003055 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003056 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003057 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003058 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003059 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003060 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003061 }
3062 }
3063
Willy Tarreauf3c69202006-07-09 16:42:34 +02003064 if (curproxy->options & PR_O_SSL3_CHK) {
3065 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3066 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3067 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3068 }
3069
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003070 /* The small pools required for the capture lists */
3071 if (curproxy->nb_req_cap)
3072 curproxy->req_cap_pool = create_pool("ptrcap",
3073 curproxy->nb_req_cap * sizeof(char *),
3074 MEM_F_SHARED);
3075 if (curproxy->nb_rsp_cap)
3076 curproxy->rsp_cap_pool = create_pool("ptrcap",
3077 curproxy->nb_rsp_cap * sizeof(char *),
3078 MEM_F_SHARED);
3079
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003080 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3081 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3082 MEM_F_SHARED);
3083
Willy Tarreau86034312006-12-29 00:10:33 +01003084 /* for backwards compatibility with "listen" instances, if
3085 * fullconn is not set but maxconn is set, then maxconn
3086 * is used.
3087 */
3088 if (!curproxy->fullconn)
3089 curproxy->fullconn = curproxy->maxconn;
3090
Willy Tarreaubaaee002006-06-26 02:48:02 +02003091 /* first, we will invert the servers list order */
3092 newsrv = NULL;
3093 while (curproxy->srv) {
3094 struct server *next;
3095
3096 next = curproxy->srv->next;
3097 curproxy->srv->next = newsrv;
3098 newsrv = curproxy->srv;
3099 if (!next)
3100 break;
3101 curproxy->srv = next;
3102 }
3103
Willy Tarreau20697042007-11-15 23:26:18 +01003104 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003105 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106
Willy Tarreaub625a082007-11-26 01:15:43 +01003107 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003108 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003109 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003110 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3111 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003112 else
3113 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003114
3115 if (curproxy->options & PR_O_LOGASAP)
3116 curproxy->to_log &= ~LW_BYTES;
3117
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003119 * ensure that we're not cross-dressing a TCP server into HTTP.
3120 */
3121 newsrv = curproxy->srv;
3122 while (newsrv != NULL) {
3123 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3124 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3125 file, proxy_type_str(curproxy), curproxy->id, linenum);
3126 goto err;
3127 }
3128 newsrv = newsrv->next;
3129 }
3130
3131 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 * If this server supports a maxconn parameter, it needs a dedicated
3133 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003134 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 */
3136 newsrv = curproxy->srv;
3137 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003138 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 /* Only 'minconn' was specified, or it was higher than or equal
3140 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3141 * this will avoid further useless expensive computations.
3142 */
3143 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003144 } else if (newsrv->maxconn && !newsrv->minconn) {
3145 /* minconn was not specified, so we set it to maxconn */
3146 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003147 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3148 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003149 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003150 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151 }
3152
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003153 if (newsrv->trackit) {
3154 struct proxy *px;
3155 struct server *srv;
3156 char *pname, *sname;
3157
3158 pname = newsrv->trackit;
3159 sname = strrchr(pname, '/');
3160
3161 if (sname)
3162 *sname++ = '\0';
3163 else {
3164 sname = pname;
3165 pname = NULL;
3166 }
3167
3168 if (pname) {
3169 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3170 if (!px) {
3171 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3172 file, proxy_type_str(curproxy), curproxy->id,
3173 newsrv->id, pname);
3174 return -1;
3175 }
3176 } else
3177 px = curproxy;
3178
3179 srv = findserver(px, sname);
3180 if (!srv) {
3181 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3182 file, proxy_type_str(curproxy), curproxy->id,
3183 newsrv->id, sname);
3184 return -1;
3185 }
3186
3187 if (!(srv->state & SRV_CHECKED)) {
3188 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3189 "tracing as it does not have checks enabled.\n",
3190 file, proxy_type_str(curproxy), curproxy->id,
3191 newsrv->id, px->id, srv->id);
3192 return -1;
3193 }
3194
3195 if (curproxy != px &&
3196 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3197 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3198 "tracing: disable-on-404 option inconsistency.\n",
3199 file, proxy_type_str(curproxy), curproxy->id,
3200 newsrv->id, px->id, srv->id);
3201 return -1;
3202 }
3203
3204 newsrv->tracked = srv;
3205 newsrv->tracknext = srv->tracknext;
3206 srv->tracknext = newsrv;
3207
3208 free(newsrv->trackit);
3209 }
3210
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 newsrv = newsrv->next;
3212 }
3213
Willy Tarreaue6b98942007-10-29 01:09:36 +01003214 /* adjust this proxy's listeners */
3215 listener = curproxy->listen;
3216 while (listener) {
3217 if (curproxy->options & PR_O_TCP_NOLING)
3218 listener->options |= LI_O_NOLINGER;
3219 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003220 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003221 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003222 listener->accept = event_accept;
3223 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003224 listener->handler = process_session;
3225
3226 if (curproxy->mode == PR_MODE_HTTP)
3227 listener->analysers |= AN_REQ_HTTP_HDR;
3228
3229 if (curproxy->tcp_req.inspect_delay)
3230 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003231
3232 listener = listener->next;
3233 }
3234
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235 curproxy = curproxy->next;
3236 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003237
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 if (cfgerr > 0) {
3239 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003240 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003242
3243 /*
3244 * Recount currently required checks.
3245 */
3246
3247 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3248 int optnum;
3249
3250 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3251 if (!(curproxy->options & cfg_opts[optnum].val))
3252 continue;
3253
3254 global.last_checks |= cfg_opts[optnum].checks;
3255 }
3256 }
3257
Willy Tarreaua534fea2008-08-03 12:19:50 +02003258 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003259 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003260 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003261
3262 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003263 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003264 cursection = NULL;
3265 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266}
3267
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003268/*
3269 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3270 * parsing sessions.
3271 */
3272void cfg_register_keywords(struct cfg_kw_list *kwl)
3273{
3274 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3275}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003277/*
3278 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3279 */
3280void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3281{
3282 LIST_DEL(&kwl->list);
3283 LIST_INIT(&kwl->list);
3284}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285
3286/*
3287 * Local variables:
3288 * c-indent-level: 8
3289 * c-basic-offset: 8
3290 * End:
3291 */