blob: af29a47986f7c54968ac9edb9d76ab49da8998df [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>
Willy Tarreau0f772532006-12-23 20:51:41 +010035#include <types/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <types/polling.h>
37#include <types/proxy.h>
38#include <types/queue.h>
39
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010045#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020046#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010047#include <proto/protocols.h>
48#include <proto/proto_tcp.h>
49#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010050#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/server.h>
52#include <proto/task.h>
53
54
Willy Tarreauf3c69202006-07-09 16:42:34 +020055/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
56 * ssl-hello-chk option to ensure that the remote server speaks SSL.
57 *
58 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
59 */
60const char sslv3_client_hello_pkt[] = {
61 "\x16" /* ContentType : 0x16 = Hanshake */
62 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
63 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
64 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
65 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
66 "\x03\x00" /* Hello Version : 0x0300 = v3 */
67 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
68 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
69 "\x00" /* Session ID length : empty (no session ID) */
70 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
71 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
72 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
73 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
74 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
75 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
76 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
77 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
78 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
79 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
80 "\x00\x38" "\x00\x39" "\x00\x3A"
81 "\x01" /* Compression Length : 0x01 = 1 byte for types */
82 "\x00" /* Compression Type : 0x00 = NULL compression */
83};
84
Willy Tarreau13943ab2006-12-31 00:24:10 +010085/* some of the most common options which are also the easiest to handle */
86static const struct {
87 const char *name;
88 unsigned int val;
89 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010090 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010091} cfg_opts[] =
92{
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010094 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010095 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010096 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010097 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
98 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
99 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
100 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
101 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
102 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
103 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
104 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100106 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
107 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100108#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100109 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
110#endif
111#ifdef TPROXY
112 { "transparent", PR_O_TRANSP, PR_CAP_FE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100113#endif
114
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116};
117
Willy Tarreaubaaee002006-06-26 02:48:02 +0200118
Willy Tarreau6daf3432008-01-22 16:44:08 +0100119static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200120static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
121int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
122int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
123
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200124/* List head of all known configuration keywords */
125static struct cfg_kw_list cfg_keywords = {
126 .list = LIST_HEAD_INIT(cfg_keywords.list)
127};
128
Willy Tarreaubaaee002006-06-26 02:48:02 +0200129/*
130 * converts <str> to a list of listeners which are dynamically allocated.
131 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
132 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
133 * - <port> is a numerical port from 1 to 65535 ;
134 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
135 * This can be repeated as many times as necessary, separated by a coma.
136 * The <tail> argument is a pointer to a current list which should be appended
137 * to the tail of the new list. The pointer to the new list is returned.
138 */
139static struct listener *str2listener(char *str, struct listener *tail)
140{
141 struct listener *l;
142 char *c, *next, *range, *dupstr;
143 int port, end;
144
145 next = dupstr = strdup(str);
146
147 while (next && *next) {
148 struct sockaddr_storage ss;
149
150 str = next;
151 /* 1) look for the end of the first address */
152 if ((next = strrchr(str, ',')) != NULL) {
153 *next++ = 0;
154 }
155
156 /* 2) look for the addr/port delimiter, it's the last colon. */
157 if ((range = strrchr(str, ':')) == NULL) {
158 Alert("Missing port number: '%s'\n", str);
159 goto fail;
160 }
161
162 *range++ = 0;
163
164 if (strrchr(str, ':') != NULL) {
165 /* IPv6 address contains ':' */
166 memset(&ss, 0, sizeof(ss));
167 ss.ss_family = AF_INET6;
168
169 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
170 Alert("Invalid server address: '%s'\n", str);
171 goto fail;
172 }
173 }
174 else {
175 memset(&ss, 0, sizeof(ss));
176 ss.ss_family = AF_INET;
177
178 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
179 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
180 }
181 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
182 struct hostent *he;
183
184 if ((he = gethostbyname(str)) == NULL) {
185 Alert("Invalid server name: '%s'\n", str);
186 goto fail;
187 }
188 else
189 ((struct sockaddr_in *)&ss)->sin_addr =
190 *(struct in_addr *) *(he->h_addr_list);
191 }
192 }
193
194 /* 3) look for the port-end delimiter */
195 if ((c = strchr(range, '-')) != NULL) {
196 *c++ = 0;
197 end = atol(c);
198 }
199 else {
200 end = atol(range);
201 }
202
203 port = atol(range);
204
205 if (port < 1 || port > 65535) {
206 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
207 goto fail;
208 }
209
210 if (end < 1 || end > 65535) {
211 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
212 goto fail;
213 }
214
215 for (; port <= end; port++) {
216 l = (struct listener *)calloc(1, sizeof(struct listener));
217 l->next = tail;
218 tail = l;
219
220 l->fd = -1;
221 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100222 l->state = LI_INIT;
223
224 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100226 tcpv6_add_listener(l);
227 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100229 tcpv4_add_listener(l);
230 }
231 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200232 } /* end for(port) */
233 } /* end while(next) */
234 free(dupstr);
235 return tail;
236 fail:
237 free(dupstr);
238 return NULL;
239}
240
Willy Tarreau977b8e42006-12-29 14:19:17 +0100241/*
242 * Sends a warning if proxy <proxy> does not have at least one of the
243 * capabilities in <cap>. An optionnal <hint> may be added at the end
244 * of the warning to help the user. Returns 1 if a warning was emitted
245 * or 0 if the condition is valid.
246 */
247int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
248{
249 char *msg;
250
251 switch (cap) {
252 case PR_CAP_BE: msg = "no backend"; break;
253 case PR_CAP_FE: msg = "no frontend"; break;
254 case PR_CAP_RS: msg = "no ruleset"; break;
255 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
256 default: msg = "not enough"; break;
257 }
258
259 if (!(proxy->cap & cap)) {
260 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100261 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100262 return 1;
263 }
264 return 0;
265}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266
267/*
268 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
269 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100270int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271{
272
273 if (!strcmp(args[0], "global")) { /* new section */
274 /* no option, nothing special to do */
275 return 0;
276 }
277 else if (!strcmp(args[0], "daemon")) {
278 global.mode |= MODE_DAEMON;
279 }
280 else if (!strcmp(args[0], "debug")) {
281 global.mode |= MODE_DEBUG;
282 }
283 else if (!strcmp(args[0], "noepoll")) {
284 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
285 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200286 else if (!strcmp(args[0], "nosepoll")) {
287 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
288 }
289 else if (!strcmp(args[0], "nokqueue")) {
290 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
291 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292 else if (!strcmp(args[0], "nopoll")) {
293 cfg_polling_mechanism &= ~POLL_USE_POLL;
294 }
295 else if (!strcmp(args[0], "quiet")) {
296 global.mode |= MODE_QUIET;
297 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200298 else if (!strcmp(args[0], "tune.maxpollevents")) {
299 if (global.tune.maxpollevents != 0) {
300 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
301 return 0;
302 }
303 if (*(args[1]) == 0) {
304 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
305 return -1;
306 }
307 global.tune.maxpollevents = atol(args[1]);
308 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100309 else if (!strcmp(args[0], "tune.maxaccept")) {
310 if (global.tune.maxaccept != 0) {
311 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
312 return 0;
313 }
314 if (*(args[1]) == 0) {
315 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
316 return -1;
317 }
318 global.tune.maxaccept = atol(args[1]);
319 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200320 else if (!strcmp(args[0], "uid")) {
321 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200322 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323 return 0;
324 }
325 if (*(args[1]) == 0) {
326 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
327 return -1;
328 }
329 global.uid = atol(args[1]);
330 }
331 else if (!strcmp(args[0], "gid")) {
332 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200333 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200334 return 0;
335 }
336 if (*(args[1]) == 0) {
337 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
338 return -1;
339 }
340 global.gid = atol(args[1]);
341 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200342 /* user/group name handling */
343 else if (!strcmp(args[0], "user")) {
344 struct passwd *ha_user;
345 if (global.uid != 0) {
346 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
347 return 0;
348 }
349 errno = 0;
350 ha_user = getpwnam(args[1]);
351 if (ha_user != NULL) {
352 global.uid = (int)ha_user->pw_uid;
353 }
354 else {
355 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
356 exit(1);
357 }
358 }
359 else if (!strcmp(args[0], "group")) {
360 struct group *ha_group;
361 if (global.gid != 0) {
362 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
363 return 0;
364 }
365 errno = 0;
366 ha_group = getgrnam(args[1]);
367 if (ha_group != NULL) {
368 global.gid = (int)ha_group->gr_gid;
369 }
370 else {
371 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
372 exit(1);
373 }
374 }
375 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200376 else if (!strcmp(args[0], "nbproc")) {
377 if (global.nbproc != 0) {
378 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
379 return 0;
380 }
381 if (*(args[1]) == 0) {
382 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
383 return -1;
384 }
385 global.nbproc = atol(args[1]);
386 }
387 else if (!strcmp(args[0], "maxconn")) {
388 if (global.maxconn != 0) {
389 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
390 return 0;
391 }
392 if (*(args[1]) == 0) {
393 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
394 return -1;
395 }
396 global.maxconn = atol(args[1]);
397#ifdef SYSTEM_MAXCONN
398 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
399 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);
400 global.maxconn = DEFAULT_MAXCONN;
401 }
402#endif /* SYSTEM_MAXCONN */
403 }
404 else if (!strcmp(args[0], "ulimit-n")) {
405 if (global.rlimit_nofile != 0) {
406 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
407 return 0;
408 }
409 if (*(args[1]) == 0) {
410 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
411 return -1;
412 }
413 global.rlimit_nofile = atol(args[1]);
414 }
415 else if (!strcmp(args[0], "chroot")) {
416 if (global.chroot != NULL) {
417 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
418 return 0;
419 }
420 if (*(args[1]) == 0) {
421 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
422 return -1;
423 }
424 global.chroot = strdup(args[1]);
425 }
426 else if (!strcmp(args[0], "pidfile")) {
427 if (global.pidfile != NULL) {
428 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
429 return 0;
430 }
431 if (*(args[1]) == 0) {
432 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
433 return -1;
434 }
435 global.pidfile = strdup(args[1]);
436 }
437 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100438 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200439 int facility, level;
440
441 if (*(args[1]) == 0 || *(args[2]) == 0) {
442 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
443 return -1;
444 }
445
446 facility = get_log_facility(args[2]);
447 if (facility < 0) {
448 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
449 exit(1);
450 }
451
452 level = 7; /* max syslog level = debug */
453 if (*(args[3])) {
454 level = get_log_level(args[3]);
455 if (level < 0) {
456 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
457 exit(1);
458 }
459 }
460
Robert Tsai81ae1952007-12-05 10:47:29 +0100461 if (args[1][0] == '/') {
462 logsrv.u.addr.sa_family = AF_UNIX;
463 logsrv.u.un = *str2sun(args[1]);
464 } else {
465 logsrv.u.addr.sa_family = AF_INET;
466 logsrv.u.in = *str2sa(args[1]);
467 if (!logsrv.u.in.sin_port)
468 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470
471 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100472 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200473 global.logfac1 = facility;
474 global.loglev1 = level;
475 }
476 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100477 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200478 global.logfac2 = facility;
479 global.loglev2 = level;
480 }
481 else {
482 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
483 return -1;
484 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200485 }
486 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
487 if (global.spread_checks != 0) {
488 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
489 return 0;
490 }
491 if (*(args[1]) == 0) {
492 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
493 return -1;
494 }
495 global.spread_checks = atol(args[1]);
496 if (global.spread_checks < 0 || global.spread_checks > 50) {
497 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
498 return -1;
499 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200500 }
501 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200502 struct cfg_kw_list *kwl;
503 int index;
504
505 list_for_each_entry(kwl, &cfg_keywords.list, list) {
506 for (index = 0; kwl->kw[index].kw != NULL; index++) {
507 if (kwl->kw[index].section != CFG_GLOBAL)
508 continue;
509 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
510 /* prepare error message just in case */
511 snprintf(trash, sizeof(trash),
512 "error near '%s' in '%s' section", args[0], "global");
513 if (kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash)) < 0) {
514 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
515 return -1;
516 }
517 return 0;
518 }
519 }
520 }
521
Willy Tarreaubaaee002006-06-26 02:48:02 +0200522 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
523 return -1;
524 }
525 return 0;
526}
527
528
529static void init_default_instance()
530{
531 memset(&defproxy, 0, sizeof(defproxy));
532 defproxy.mode = PR_MODE_TCP;
533 defproxy.state = PR_STNEW;
534 defproxy.maxconn = cfg_maxpconn;
535 defproxy.conn_retries = CONN_RETRIES;
536 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100537 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538}
539
540/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100541 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
542 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200543 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100544int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200545{
546 static struct proxy *curproxy = NULL;
547 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200548 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100549 int rc;
550 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200551
Willy Tarreau977b8e42006-12-29 14:19:17 +0100552 if (!strcmp(args[0], "listen"))
553 rc = PR_CAP_LISTEN;
554 else if (!strcmp(args[0], "frontend"))
555 rc = PR_CAP_FE | PR_CAP_RS;
556 else if (!strcmp(args[0], "backend"))
557 rc = PR_CAP_BE | PR_CAP_RS;
558 else if (!strcmp(args[0], "ruleset"))
559 rc = PR_CAP_RS;
560 else
561 rc = PR_CAP_NONE;
562
563 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200564 if (!*args[1]) {
565 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
566 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
567 file, linenum, args[0]);
568 return -1;
569 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200570
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100571 err = invalid_char(args[1]);
572 if (err) {
573 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
574 file, linenum, *err, args[0], args[1]);
575 return -1;
576 }
577
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200578 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
579 /*
580 * If there are two proxies with the same name only following
581 * combinations are allowed:
582 *
583 * listen backend frontend ruleset
584 * listen - - - -
585 * backend - - OK -
586 * frontend - OK - -
587 * ruleset - - - -
588 */
589
590 if (!strcmp(curproxy->id, args[1]) &&
591 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
592 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100593 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
594 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200595 }
596 }
597
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
599 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
600 return -1;
601 }
602
603 curproxy->next = proxy;
604 proxy = curproxy;
605 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200606 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200607 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200608 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100609 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200610 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611
Willy Tarreauee991362007-05-14 14:37:50 +0200612 /* Timeouts are defined as -1, so we cannot use the zeroed area
613 * as a default value.
614 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100615 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200616
617 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100619 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200620
621 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100622 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 curproxy->listen = str2listener(args[2], curproxy->listen);
624 if (!curproxy->listen)
625 return -1;
626 global.maxsock++;
627 }
628
629 /* set default values */
630 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100632 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200633 curproxy->except_net = defproxy.except_net;
634 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635
Willy Tarreau977b8e42006-12-29 14:19:17 +0100636 if (curproxy->cap & PR_CAP_FE) {
637 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100638 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100639
640 /* initialize error relocations */
641 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
642 if (defproxy.errmsg[rc].str)
643 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
644 }
645
646 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
647 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200648
Willy Tarreau977b8e42006-12-29 14:19:17 +0100649 if (curproxy->cap & PR_CAP_BE) {
650 curproxy->fullconn = defproxy.fullconn;
651 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652
Willy Tarreau977b8e42006-12-29 14:19:17 +0100653 if (defproxy.check_req)
654 curproxy->check_req = strdup(defproxy.check_req);
655 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656
Willy Tarreau977b8e42006-12-29 14:19:17 +0100657 if (defproxy.cookie_name)
658 curproxy->cookie_name = strdup(defproxy.cookie_name);
659 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100660
661 if (defproxy.url_param_name)
662 curproxy->url_param_name = strdup(defproxy.url_param_name);
663 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665
Willy Tarreau977b8e42006-12-29 14:19:17 +0100666 if (curproxy->cap & PR_CAP_RS) {
667 if (defproxy.capture_name)
668 curproxy->capture_name = strdup(defproxy.capture_name);
669 curproxy->capture_namelen = defproxy.capture_namelen;
670 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100671 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200672
Willy Tarreau977b8e42006-12-29 14:19:17 +0100673 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100674 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100675 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100676 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100677 curproxy->uri_auth = defproxy.uri_auth;
678 curproxy->mon_net = defproxy.mon_net;
679 curproxy->mon_mask = defproxy.mon_mask;
680 if (defproxy.monitor_uri)
681 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
682 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100683 if (defproxy.defbe.name)
684 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100685 }
686
687 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100688 curproxy->timeout.connect = defproxy.timeout.connect;
689 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100690 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100691 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100692 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100693 curproxy->source_addr = defproxy.source_addr;
694 }
695
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696 curproxy->mode = defproxy.mode;
697 curproxy->logfac1 = defproxy.logfac1;
698 curproxy->logsrv1 = defproxy.logsrv1;
699 curproxy->loglev1 = defproxy.loglev1;
700 curproxy->logfac2 = defproxy.logfac2;
701 curproxy->logsrv2 = defproxy.logsrv2;
702 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100704 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
705 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200706
Willy Tarreaubaaee002006-06-26 02:48:02 +0200707 return 0;
708 }
709 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
710 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100711 /* FIXME-20070101: we should do this too at the end of the
712 * config parsing to free all default values.
713 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714 if (defproxy.check_req) free(defproxy.check_req);
715 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100716 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200717 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200718 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100719 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100720
721 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
722 if (defproxy.errmsg[rc].len)
723 free(defproxy.errmsg[rc].str);
724 }
725
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726 /* we cannot free uri_auth because it might already be used */
727 init_default_instance();
728 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100729 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200730 return 0;
731 }
732 else if (curproxy == NULL) {
733 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
734 return -1;
735 }
736
Willy Tarreau977b8e42006-12-29 14:19:17 +0100737
738 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200739 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100740 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200741 if (curproxy == &defproxy) {
742 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
743 return -1;
744 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100745 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
746 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747
748 if (strchr(args[1], ':') == NULL) {
749 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
750 file, linenum, args[0]);
751 return -1;
752 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100753
754 last_listen = curproxy->listen;
755 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200756 if (!curproxy->listen)
757 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100758 if (*args[2]) {
759#ifdef CONFIG_HAP_LINUX_TPROXY
760 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
761 struct listener *l;
762
763 for (l = curproxy->listen; l != last_listen; l = l->next)
764 l->options |= LI_O_FOREIGN;
765 }
766 else {
767 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
768 file, linenum, args[0]);
769 return -1;
770 }
771#else
772 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
773 file, linenum, args[0]);
774 return -1;
775#endif
776 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 global.maxsock++;
778 return 0;
779 }
780 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
781 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
782 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
783 file, linenum, args[0]);
784 return -1;
785 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100786 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
787 return 0;
788
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789 /* flush useless bits */
790 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
791 return 0;
792 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200793 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100794 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
795 return 0;
796
Willy Tarreau1c47f852006-07-09 08:22:27 +0200797 if (!*args[1]) {
798 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
799 file, linenum, args[0]);
800 return -1;
801 }
802
803 if (curproxy->monitor_uri != NULL)
804 free(curproxy->monitor_uri);
805
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100806 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200807 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100808 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200809 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
810
811 return 0;
812 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200813 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
814 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
815 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
816 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
817 else {
818 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
819 return -1;
820 }
821 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100822 else if (!strcmp(args[0], "id")) {
823 struct proxy *target;
824
825 if (curproxy == &defproxy) {
826 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
827 file, linenum, args[0]);
828 return -1;
829 }
830
831 if (!*args[1]) {
832 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
833 file, linenum, args[0]);
834 return -1;
835 }
836
837 curproxy->uuid = atol(args[1]);
838
839 if (curproxy->uuid < 1001) {
840 Alert("parsing [%s:%d]: custom id has to be > 1000",
841 file, linenum);
842 return -1;
843 }
844
845 for (target = proxy; target; target = target->next)
846 if (curproxy != target && curproxy->uuid == target->uuid) {
847 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
848 file, linenum, curproxy->id, target->id);
849 return -1;
850 }
851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200852 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
853 curproxy->state = PR_STSTOPPED;
854 }
855 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
856 curproxy->state = PR_STNEW;
857 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200858 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100859 err = invalid_char(args[1]);
860 if (err) {
861 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
862 file, linenum, *err, args[1]);
863 return -1;
864 }
865
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200866 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
867 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
868 file, linenum, args[1]);
869 return -1;
870 }
871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872 else if (!strcmp(args[0], "cookie")) { /* cookie name */
873 int cur_arg;
874 // if (curproxy == &defproxy) {
875 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
876 // return -1;
877 // }
878
Willy Tarreau977b8e42006-12-29 14:19:17 +0100879 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
880 return 0;
881
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882 if (curproxy->cookie_name != NULL) {
883 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
884 // file, linenum);
885 // return 0;
886 free(curproxy->cookie_name);
887 }
888
889 if (*(args[1]) == 0) {
890 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
891 file, linenum, args[0]);
892 return -1;
893 }
894 curproxy->cookie_name = strdup(args[1]);
895 curproxy->cookie_len = strlen(curproxy->cookie_name);
896
897 cur_arg = 2;
898 while (*(args[cur_arg])) {
899 if (!strcmp(args[cur_arg], "rewrite")) {
900 curproxy->options |= PR_O_COOK_RW;
901 }
902 else if (!strcmp(args[cur_arg], "indirect")) {
903 curproxy->options |= PR_O_COOK_IND;
904 }
905 else if (!strcmp(args[cur_arg], "insert")) {
906 curproxy->options |= PR_O_COOK_INS;
907 }
908 else if (!strcmp(args[cur_arg], "nocache")) {
909 curproxy->options |= PR_O_COOK_NOC;
910 }
911 else if (!strcmp(args[cur_arg], "postonly")) {
912 curproxy->options |= PR_O_COOK_POST;
913 }
914 else if (!strcmp(args[cur_arg], "prefix")) {
915 curproxy->options |= PR_O_COOK_PFX;
916 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200917 else if (!strcmp(args[cur_arg], "domain")) {
918 if (!*args[cur_arg + 1]) {
919 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
920 file, linenum, args[cur_arg]);
921 return -1;
922 }
923
924 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
925 /* rfc2109, 4.3.2 Rejecting Cookies */
926 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
927 " dots or does not start with a dot.\n",
928 file, linenum, args[cur_arg + 1]);
929 return -1;
930 }
931
932 err = invalid_domainchar(args[cur_arg + 1]);
933 if (err) {
934 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
935 file, linenum, *err, args[cur_arg + 1]);
936 return -1;
937 }
938
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +0200939 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200940 cur_arg++;
941 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200943 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +0200944 file, linenum, args[0]);
945 return -1;
946 }
947 cur_arg++;
948 }
949 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
950 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
951 file, linenum);
952 return -1;
953 }
954
955 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
956 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
957 file, linenum);
958 return -1;
959 }
960 }/* end else if (!strcmp(args[0], "cookie")) */
961 else if (!strcmp(args[0], "appsession")) { /* cookie name */
962 // if (curproxy == &defproxy) {
963 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
964 // return -1;
965 // }
966
Willy Tarreau977b8e42006-12-29 14:19:17 +0100967 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
968 return 0;
969
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 if (curproxy->appsession_name != NULL) {
971 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
972 // file, linenum);
973 // return 0;
974 free(curproxy->appsession_name);
975 }
976
977 if (*(args[5]) == 0) {
978 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
979 file, linenum, args[0]);
980 return -1;
981 }
982 have_appsession = 1;
983 curproxy->appsession_name = strdup(args[1]);
984 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
985 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100986 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
987 if (err) {
988 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
989 file, linenum, *err, args[0]);
990 return -1;
991 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200992 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +0200993
Willy Tarreau51041c72007-09-09 21:56:53 +0200994 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
995 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200996 return -1;
997 }
998 } /* Url App Session */
999 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001000 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1001 return 0;
1002
Willy Tarreaubaaee002006-06-26 02:48:02 +02001003 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
1004 // if (curproxy == &defproxy) {
1005 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1006 // return -1;
1007 // }
1008
1009 if (curproxy->capture_name != NULL) {
1010 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
1011 // file, linenum, args[0]);
1012 // return 0;
1013 free(curproxy->capture_name);
1014 }
1015
1016 if (*(args[4]) == 0) {
1017 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1018 file, linenum, args[0]);
1019 return -1;
1020 }
1021 curproxy->capture_name = strdup(args[2]);
1022 curproxy->capture_namelen = strlen(curproxy->capture_name);
1023 curproxy->capture_len = atol(args[4]);
1024 if (curproxy->capture_len >= CAPTURE_LEN) {
1025 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1026 file, linenum, CAPTURE_LEN - 1);
1027 curproxy->capture_len = CAPTURE_LEN - 1;
1028 }
1029 curproxy->to_log |= LW_COOKIE;
1030 }
1031 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1032 struct cap_hdr *hdr;
1033
1034 if (curproxy == &defproxy) {
1035 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1036 return -1;
1037 }
1038
1039 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1040 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1041 file, linenum, args[0], args[1]);
1042 return -1;
1043 }
1044
1045 hdr = calloc(sizeof(struct cap_hdr), 1);
1046 hdr->next = curproxy->req_cap;
1047 hdr->name = strdup(args[3]);
1048 hdr->namelen = strlen(args[3]);
1049 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001050 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 hdr->index = curproxy->nb_req_cap++;
1052 curproxy->req_cap = hdr;
1053 curproxy->to_log |= LW_REQHDR;
1054 }
1055 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1056 struct cap_hdr *hdr;
1057
1058 if (curproxy == &defproxy) {
1059 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1060 return -1;
1061 }
1062
1063 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1064 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1065 file, linenum, args[0], args[1]);
1066 return -1;
1067 }
1068 hdr = calloc(sizeof(struct cap_hdr), 1);
1069 hdr->next = curproxy->rsp_cap;
1070 hdr->name = strdup(args[3]);
1071 hdr->namelen = strlen(args[3]);
1072 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001073 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074 hdr->index = curproxy->nb_rsp_cap++;
1075 curproxy->rsp_cap = hdr;
1076 curproxy->to_log |= LW_RSPHDR;
1077 }
1078 else {
1079 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1080 file, linenum, args[0]);
1081 return -1;
1082 }
1083 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001084 else if (!strcmp(args[0], "contimeout") || !strcmp(args[0], "clitimeout") ||
1085 !strcmp(args[0], "srvtimeout") || !strcmp(args[0], "timeout")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001086
Willy Tarreaue219db72007-12-03 01:30:13 +01001087 /* either we have {con|srv|cli}timeout <value> or we have the
1088 * new form: timeout <type> <value>. The parser needs the word
1089 * preceeding the value.
1090 */
1091 const char **start_arg = (const char **)args;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001092
Willy Tarreaue219db72007-12-03 01:30:13 +01001093 if (strcmp(args[0], "timeout") == 0)
1094 start_arg++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001095
Willy Tarreaue219db72007-12-03 01:30:13 +01001096 snprintf(trash, sizeof(trash), "error near '%s'", args[0]);
1097 rc = proxy_parse_timeout(start_arg, curproxy, &defproxy, trash, sizeof(trash));
1098 if (rc < 0) {
1099 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001100 return -1;
1101 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001102 if (rc > 0)
1103 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104 }
1105 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001106 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1107 return 0;
1108
Willy Tarreaubaaee002006-06-26 02:48:02 +02001109 if (*(args[1]) == 0) {
1110 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1111 file, linenum, args[0]);
1112 return -1;
1113 }
1114 curproxy->conn_retries = atol(args[1]);
1115 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001116 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1117 int pol = ACL_COND_NONE;
1118 struct acl_cond *cond;
1119
1120 if (!strcmp(args[1], "if"))
1121 pol = ACL_COND_IF;
1122 else if (!strcmp(args[1], "unless"))
1123 pol = ACL_COND_UNLESS;
1124
1125 if (pol == ACL_COND_NONE) {
1126 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1127 file, linenum, args[0]);
1128 return -1;
1129 }
1130
1131 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1132 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1133 file, linenum);
1134 return -1;
1135 }
1136 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1137 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001138 else if (!strcmp(args[0], "redirect")) {
1139 int pol = ACL_COND_NONE;
1140 struct acl_cond *cond;
1141 struct redirect_rule *rule;
1142 int cur_arg;
1143 int type = REDIRECT_TYPE_NONE;
1144 int code = 302;
1145 char *destination = NULL;
1146
1147 cur_arg = 1;
1148 while (*(args[cur_arg])) {
1149 if (!strcmp(args[cur_arg], "location")) {
1150 if (!*args[cur_arg + 1]) {
1151 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1152 file, linenum, args[0], args[cur_arg]);
1153 return -1;
1154 }
1155
1156 type = REDIRECT_TYPE_LOCATION;
1157 cur_arg++;
1158 destination = args[cur_arg];
1159 }
1160 else if (!strcmp(args[cur_arg], "prefix")) {
1161 if (!*args[cur_arg + 1]) {
1162 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1163 file, linenum, args[0], args[cur_arg]);
1164 return -1;
1165 }
1166
1167 type = REDIRECT_TYPE_PREFIX;
1168 cur_arg++;
1169 destination = args[cur_arg];
1170 }
1171 else if (!strcmp(args[cur_arg],"code")) {
1172 if (!*args[cur_arg + 1]) {
1173 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1174 file, linenum, args[0]);
1175 return -1;
1176 }
1177 cur_arg++;
1178 code = atol(args[cur_arg]);
1179 if (code < 301 || code > 303) {
1180 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1181 file, linenum, args[0], code);
1182 return -1;
1183 }
1184 }
1185 else if (!strcmp(args[cur_arg], "if")) {
1186 pol = ACL_COND_IF;
1187 cur_arg++;
1188 break;
1189 }
1190 else if (!strcmp(args[cur_arg], "unless")) {
1191 pol = ACL_COND_UNLESS;
1192 cur_arg++;
1193 break;
1194 }
1195 else {
1196 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1197 file, linenum, args[0], args[cur_arg]);
1198 return -1;
1199 }
1200 cur_arg++;
1201 }
1202
1203 if (type == REDIRECT_TYPE_NONE) {
1204 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1205 file, linenum, args[0]);
1206 return -1;
1207 }
1208
1209 if (pol == ACL_COND_NONE) {
1210 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1211 file, linenum, args[0]);
1212 return -1;
1213 }
1214
1215 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1216 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1217 file, linenum, args[0]);
1218 return -1;
1219 }
1220
1221 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1222 rule->cond = cond;
1223 rule->rdr_str = strdup(destination);
1224 rule->rdr_len = strlen(destination);
1225 rule->type = type;
1226 rule->code = code;
1227 LIST_INIT(&rule->list);
1228 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1229 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001230 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1231 int pol = ACL_COND_NONE;
1232 struct acl_cond *cond;
1233 struct switching_rule *rule;
1234
1235 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1236 return 0;
1237
1238 if (*(args[1]) == 0) {
1239 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1240 return -1;
1241 }
1242
1243 if (!strcmp(args[2], "if"))
1244 pol = ACL_COND_IF;
1245 else if (!strcmp(args[2], "unless"))
1246 pol = ACL_COND_UNLESS;
1247
1248 if (pol == ACL_COND_NONE) {
1249 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1250 file, linenum, args[0]);
1251 return -1;
1252 }
1253
1254 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1255 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1256 file, linenum);
1257 return -1;
1258 }
1259
1260 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1261 rule->cond = cond;
1262 rule->be.name = strdup(args[1]);
1263 LIST_INIT(&rule->list);
1264 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001266 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001267 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1268 return 0;
1269
Willy Tarreaubaaee002006-06-26 02:48:02 +02001270 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1271 curproxy->uri_auth = NULL; /* we must detach from the default config */
1272
1273 if (*(args[1]) == 0) {
1274 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1275 return -1;
1276 } else if (!strcmp(args[1], "uri")) {
1277 if (*(args[2]) == 0) {
1278 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1279 return -1;
1280 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1281 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1282 return -1;
1283 }
1284 } else if (!strcmp(args[1], "realm")) {
1285 if (*(args[2]) == 0) {
1286 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1287 return -1;
1288 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1289 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1290 return -1;
1291 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001292 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001293 unsigned interval;
1294
1295 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1296 if (err) {
1297 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1298 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001299 return -1;
1300 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1301 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1302 return -1;
1303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304 } else if (!strcmp(args[1], "auth")) {
1305 if (*(args[2]) == 0) {
1306 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1307 return -1;
1308 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1309 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1310 return -1;
1311 }
1312 } else if (!strcmp(args[1], "scope")) {
1313 if (*(args[2]) == 0) {
1314 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1315 return -1;
1316 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1317 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1318 return -1;
1319 }
1320 } else if (!strcmp(args[1], "enable")) {
1321 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1322 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1323 return -1;
1324 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001325 } else if (!strcmp(args[1], "hide-version")) {
1326 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1327 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1328 return -1;
1329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001330 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001331 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001332 file, linenum, args[0]);
1333 return -1;
1334 }
1335 }
1336 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001337 int optnum;
1338
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001339 if (*(args[1]) == '\0') {
1340 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1341 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001342 return -1;
1343 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001344
1345 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1346 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1347 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1348 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001349
1350 if (!inv)
1351 curproxy->options |= cfg_opts[optnum].val;
1352 else
1353 curproxy->options &= ~cfg_opts[optnum].val;
1354
Willy Tarreau13943ab2006-12-31 00:24:10 +01001355 return 0;
1356 }
1357 }
1358
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001359 if (inv) {
1360 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1361 file, linenum, args[1]);
1362 return -1;
1363 }
1364
Willy Tarreau13943ab2006-12-31 00:24:10 +01001365 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001366 /* generate a complete HTTP log */
1367 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1368 else if (!strcmp(args[1], "tcplog"))
1369 /* generate a detailed TCP log */
1370 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001371 else if (!strcmp(args[1], "tcpka")) {
1372 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001373 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1374 return 0;
1375
1376 if (curproxy->cap & PR_CAP_FE)
1377 curproxy->options |= PR_O_TCP_CLI_KA;
1378 if (curproxy->cap & PR_CAP_BE)
1379 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 }
1381 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001382 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1383 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 /* use HTTP request to check servers' health */
1385 if (curproxy->check_req != NULL) {
1386 free(curproxy->check_req);
1387 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001388 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001389 curproxy->options &= ~PR_O_SMTP_CHK;
1390 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391 if (!*args[2]) { /* no argument */
1392 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1393 curproxy->check_len = strlen(DEF_CHECK_REQ);
1394 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001395 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001396 curproxy->check_req = (char *)malloc(reqlen);
1397 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1398 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1399 } else { /* more arguments : METHOD URI [HTTP_VER] */
1400 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1401 if (*args[4])
1402 reqlen += strlen(args[4]);
1403 else
1404 reqlen += strlen("HTTP/1.0");
1405
1406 curproxy->check_req = (char *)malloc(reqlen);
1407 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1408 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1409 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001410 }
1411 else if (!strcmp(args[1], "ssl-hello-chk")) {
1412 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001413 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1414 return 0;
1415
Willy Tarreauf3c69202006-07-09 16:42:34 +02001416 if (curproxy->check_req != NULL) {
1417 free(curproxy->check_req);
1418 }
1419 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001420 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001421 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422 }
Willy Tarreau23677902007-05-08 23:50:35 +02001423 else if (!strcmp(args[1], "smtpchk")) {
1424 /* use SMTP request to check servers' health */
1425 if (curproxy->check_req != NULL) {
1426 free(curproxy->check_req);
1427 }
1428 curproxy->options &= ~PR_O_HTTP_CHK;
1429 curproxy->options &= ~PR_O_SSL3_CHK;
1430 curproxy->options |= PR_O_SMTP_CHK;
1431
1432 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1433 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1434 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1435 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1436 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1437 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1438 curproxy->check_req = (char *)malloc(reqlen);
1439 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1440 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1441 } else {
1442 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1443 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1444 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1445 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1446 }
1447 }
1448 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001449 else if (!strcmp(args[1], "forwardfor")) {
1450 /* insert x-forwarded-for field, but not for the
1451 * IP address listed as an except.
1452 */
1453 if (*(args[2])) {
1454 if (!strcmp(args[2], "except")) {
1455 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1456 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1457 file, linenum, args[0]);
1458 return -1;
1459 }
1460 /* flush useless bits */
1461 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1462 } else {
1463 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1464 file, linenum, args[0]);
1465 return -1;
1466 }
1467 }
1468 curproxy->options |= PR_O_FWDFOR;
1469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470 else {
1471 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1472 return -1;
1473 }
1474 return 0;
1475 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001476 else if (!strcmp(args[0], "default_backend")) {
1477 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1478 return 0;
1479
1480 if (*(args[1]) == 0) {
1481 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1482 return -1;
1483 }
1484 if (curproxy->defbe.name)
1485 free(curproxy->defbe.name);
1486 curproxy->defbe.name = strdup(args[1]);
1487 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001488 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001489 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1490 return 0;
1491
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001492 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1493 file, linenum, args[0]);
1494
Willy Tarreaubaaee002006-06-26 02:48:02 +02001495 /* enable reconnections to dispatch */
1496 curproxy->options |= PR_O_REDISP;
1497 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001498 else if (!strcmp(args[0], "http-check")) {
1499 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1500 return 0;
1501
1502 if (strcmp(args[1], "disable-on-404") == 0) {
1503 /* enable a graceful server shutdown on an HTTP 404 response */
1504 curproxy->options |= PR_O_DISABLE404;
1505 }
1506 else {
1507 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1508 return -1;
1509 }
1510 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001511 else if (!strcmp(args[0], "monitor")) {
1512 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1513 return 0;
1514
1515 if (strcmp(args[1], "fail") == 0) {
1516 /* add a condition to fail monitor requests */
1517 int pol = ACL_COND_NONE;
1518 struct acl_cond *cond;
1519
1520 if (!strcmp(args[2], "if"))
1521 pol = ACL_COND_IF;
1522 else if (!strcmp(args[2], "unless"))
1523 pol = ACL_COND_UNLESS;
1524
1525 if (pol == ACL_COND_NONE) {
1526 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1527 file, linenum, args[0], args[1]);
1528 return -1;
1529 }
1530
1531 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1532 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1533 file, linenum, args[0], args[1]);
1534 return -1;
1535 }
1536 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1537 }
1538 else {
1539 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1540 return -1;
1541 }
1542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001543#ifdef TPROXY
1544 else if (!strcmp(args[0], "transparent")) {
1545 /* enable transparent proxy connections */
1546 curproxy->options |= PR_O_TRANSP;
1547 }
1548#endif
1549 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001550 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1551 return 0;
1552
Willy Tarreaubaaee002006-06-26 02:48:02 +02001553 if (*(args[1]) == 0) {
1554 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1555 return -1;
1556 }
1557 curproxy->maxconn = atol(args[1]);
1558 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001559 else if (!strcmp(args[0], "backlog")) { /* backlog */
1560 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1561 return 0;
1562
1563 if (*(args[1]) == 0) {
1564 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1565 return -1;
1566 }
1567 curproxy->backlog = atol(args[1]);
1568 }
Willy Tarreau86034312006-12-29 00:10:33 +01001569 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001570 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1571 return 0;
1572
Willy Tarreau86034312006-12-29 00:10:33 +01001573 if (*(args[1]) == 0) {
1574 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1575 return -1;
1576 }
1577 curproxy->fullconn = atol(args[1]);
1578 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1580 if (*(args[1]) == 0) {
1581 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1582 return -1;
1583 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001584 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1585 if (err) {
1586 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1587 file, linenum, *err);
1588 return -1;
1589 }
1590 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591 }
1592 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1593 if (curproxy == &defproxy) {
1594 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1595 return -1;
1596 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001597 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1598 return 0;
1599
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600 if (strchr(args[1], ':') == NULL) {
1601 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1602 return -1;
1603 }
1604 curproxy->dispatch_addr = *str2sa(args[1]);
1605 }
1606 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001607 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1608 return 0;
1609
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001610 memcpy(trash, "error near 'balance'", 19);
1611 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1612 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1613 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001614 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615 }
1616 else if (!strcmp(args[0], "server")) { /* server address */
1617 int cur_arg;
1618 char *rport;
1619 char *raddr;
1620 short realport;
1621 int do_check;
1622
1623 if (curproxy == &defproxy) {
1624 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1625 return -1;
1626 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001627 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1628 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629
1630 if (!*args[2]) {
1631 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1632 file, linenum, args[0]);
1633 return -1;
1634 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001635
1636 err = invalid_char(args[1]);
1637 if (err) {
1638 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1639 file, linenum, *err, args[1]);
1640 return -1;
1641 }
1642
Willy Tarreaubaaee002006-06-26 02:48:02 +02001643 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1644 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1645 return -1;
1646 }
1647
1648 /* the servers are linked backwards first */
1649 newsrv->next = curproxy->srv;
1650 curproxy->srv = newsrv;
1651 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001652 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001653
1654 LIST_INIT(&newsrv->pendconns);
1655 do_check = 0;
1656 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001657 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 newsrv->id = strdup(args[1]);
1659
1660 /* several ways to check the port component :
1661 * - IP => port=+0, relative
1662 * - IP: => port=+0, relative
1663 * - IP:N => port=N, absolute
1664 * - IP:+N => port=+N, relative
1665 * - IP:-N => port=-N, relative
1666 */
1667 raddr = strdup(args[2]);
1668 rport = strchr(raddr, ':');
1669 if (rport) {
1670 *rport++ = 0;
1671 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001672 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 newsrv->state |= SRV_MAPPORTS;
1674 } else {
1675 realport = 0;
1676 newsrv->state |= SRV_MAPPORTS;
1677 }
1678
1679 newsrv->addr = *str2sa(raddr);
1680 newsrv->addr.sin_port = htons(realport);
1681 free(raddr);
1682
1683 newsrv->curfd = -1; /* no health-check in progress */
1684 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001685 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1686 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001687 newsrv->rise = DEF_RISETIME;
1688 newsrv->fall = DEF_FALLTIME;
1689 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001690 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001691 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001692 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001693
Willy Tarreaubaaee002006-06-26 02:48:02 +02001694 cur_arg = 3;
1695 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001696 if (!strcmp(args[cur_arg], "id")) {
1697 struct server *target;
1698
1699 if (!*args[cur_arg + 1]) {
1700 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1701 file, linenum, args[cur_arg]);
1702 return -1;
1703 }
1704
1705 newsrv->puid = atol(args[cur_arg + 1]);
1706
1707 if (newsrv->puid< 1001) {
1708 Alert("parsing [%s:%d]: custom id has to be > 1000",
1709 file, linenum);
1710 return -1;
1711 }
1712
1713 for (target = proxy->srv; target; target = target->next)
1714 if (newsrv != target && newsrv->puid == target->puid) {
1715 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1716 file, linenum, newsrv->id, target->id);
1717 return -1;
1718 }
1719 cur_arg += 2;
1720 }
1721 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001722 newsrv->cookie = strdup(args[cur_arg + 1]);
1723 newsrv->cklen = strlen(args[cur_arg + 1]);
1724 cur_arg += 2;
1725 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001726 else if (!strcmp(args[cur_arg], "redir")) {
1727 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1728 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1729 cur_arg += 2;
1730 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001731 else if (!strcmp(args[cur_arg], "rise")) {
1732 newsrv->rise = atol(args[cur_arg + 1]);
1733 newsrv->health = newsrv->rise;
1734 cur_arg += 2;
1735 }
1736 else if (!strcmp(args[cur_arg], "fall")) {
1737 newsrv->fall = atol(args[cur_arg + 1]);
1738 cur_arg += 2;
1739 }
1740 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001741 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1742 if (err) {
1743 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1744 file, linenum, *err, newsrv->id);
1745 return -1;
1746 }
1747 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001748 cur_arg += 2;
1749 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001750 else if (!strcmp(args[cur_arg], "fastinter")) {
1751 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1752 if (err) {
1753 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1754 file, linenum, *err, newsrv->id);
1755 return -1;
1756 }
1757 newsrv->fastinter = val;
1758 cur_arg += 2;
1759 }
1760 else if (!strcmp(args[cur_arg], "downinter")) {
1761 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1762 if (err) {
1763 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1764 file, linenum, *err, newsrv->id);
1765 return -1;
1766 }
1767 newsrv->downinter = val;
1768 cur_arg += 2;
1769 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001770 else if (!strcmp(args[cur_arg], "addr")) {
1771 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001772 cur_arg += 2;
1773 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774 else if (!strcmp(args[cur_arg], "port")) {
1775 newsrv->check_port = atol(args[cur_arg + 1]);
1776 cur_arg += 2;
1777 }
1778 else if (!strcmp(args[cur_arg], "backup")) {
1779 newsrv->state |= SRV_BACKUP;
1780 cur_arg ++;
1781 }
1782 else if (!strcmp(args[cur_arg], "weight")) {
1783 int w;
1784 w = atol(args[cur_arg + 1]);
1785 if (w < 1 || w > 256) {
1786 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1787 file, linenum, newsrv->id, w);
1788 return -1;
1789 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001790 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001791 cur_arg += 2;
1792 }
1793 else if (!strcmp(args[cur_arg], "minconn")) {
1794 newsrv->minconn = atol(args[cur_arg + 1]);
1795 cur_arg += 2;
1796 }
1797 else if (!strcmp(args[cur_arg], "maxconn")) {
1798 newsrv->maxconn = atol(args[cur_arg + 1]);
1799 cur_arg += 2;
1800 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001801 else if (!strcmp(args[cur_arg], "maxqueue")) {
1802 newsrv->maxqueue = atol(args[cur_arg + 1]);
1803 cur_arg += 2;
1804 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001805 else if (!strcmp(args[cur_arg], "slowstart")) {
1806 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001807 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001808 if (err) {
1809 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1810 file, linenum, *err, newsrv->id);
1811 return -1;
1812 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001813 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001814 cur_arg += 2;
1815 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001816 else if (!strcmp(args[cur_arg], "track")) {
1817
1818 if (!*args[cur_arg + 1]) {
1819 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1820 file, linenum);
1821 return -1;
1822 }
1823
1824 newsrv->trackit = strdup(args[cur_arg + 1]);
1825
1826 cur_arg += 2;
1827 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001828 else if (!strcmp(args[cur_arg], "check")) {
1829 global.maxsock++;
1830 do_check = 1;
1831 cur_arg += 1;
1832 }
1833 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1834 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001835#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001836 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1837 file, linenum, "source", "usesrc");
1838#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001839 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1840 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001841#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001842 return -1;
1843 }
1844 newsrv->state |= SRV_BIND_SRC;
1845 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1846 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001847 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001848#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1849#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001850 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001851 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1852 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001853 return -1;
1854 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001855#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001856 if (!*args[cur_arg + 1]) {
1857 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1858 file, linenum, "usesrc");
1859 return -1;
1860 }
1861 if (!strcmp(args[cur_arg + 1], "client")) {
1862 newsrv->state |= SRV_TPROXY_CLI;
1863 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1864 newsrv->state |= SRV_TPROXY_CIP;
1865 } else {
1866 newsrv->state |= SRV_TPROXY_ADDR;
1867 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1868 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001869 global.last_checks |= LSTCHK_NETADM;
1870#if !defined(CONFIG_HAP_LINUX_TPROXY)
1871 global.last_checks |= LSTCHK_CTTPROXY;
1872#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001873 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001874#else /* no TPROXY support */
1875 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001876 file, linenum, "usesrc");
1877 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001878#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001879 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001880 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001881 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1882 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1883 file, linenum, "usesrc", "source");
1884 return -1;
1885 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001886 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001887 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 +02001888 file, linenum, newsrv->id);
1889 return -1;
1890 }
1891 }
1892
1893 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001894 if (newsrv->trackit) {
1895 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1896 file, linenum);
1897 return -1;
1898 }
1899
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001900 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1901 newsrv->check_port = newsrv->check_addr.sin_port;
1902
Willy Tarreaubaaee002006-06-26 02:48:02 +02001903 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1904 newsrv->check_port = realport; /* by default */
1905 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001906 /* not yet valid, because no port was set on
1907 * the server either. We'll check if we have
1908 * a known port on the first listener.
1909 */
1910 struct listener *l;
1911 l = curproxy->listen;
1912 if (l) {
1913 int port;
1914 port = (l->addr.ss_family == AF_INET6)
1915 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1916 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1917 newsrv->check_port = port;
1918 }
1919 }
1920 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1922 file, linenum, newsrv->id);
1923 return -1;
1924 }
1925 newsrv->state |= SRV_CHECKED;
1926 }
1927
1928 if (newsrv->state & SRV_BACKUP)
1929 curproxy->srv_bck++;
1930 else
1931 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001932
1933 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934 }
1935 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001936 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 int facility;
1938
1939 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1940 curproxy->logfac1 = global.logfac1;
1941 curproxy->logsrv1 = global.logsrv1;
1942 curproxy->loglev1 = global.loglev1;
1943 curproxy->logfac2 = global.logfac2;
1944 curproxy->logsrv2 = global.logsrv2;
1945 curproxy->loglev2 = global.loglev2;
1946 }
1947 else if (*(args[1]) && *(args[2])) {
1948 int level;
1949
1950 facility = get_log_facility(args[2]);
1951 if (facility < 0) {
1952 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1953 exit(1);
1954 }
1955
1956 level = 7; /* max syslog level = debug */
1957 if (*(args[3])) {
1958 level = get_log_level(args[3]);
1959 if (level < 0) {
1960 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1961 exit(1);
1962 }
1963 }
1964
Robert Tsai81ae1952007-12-05 10:47:29 +01001965 if (args[1][0] == '/') {
1966 logsrv.u.addr.sa_family = AF_UNIX;
1967 logsrv.u.un = *str2sun(args[1]);
1968 } else {
1969 logsrv.u.addr.sa_family = AF_INET;
1970 logsrv.u.in = *str2sa(args[1]);
1971 if (!logsrv.u.in.sin_port) {
1972 logsrv.u.in.sin_port =
1973 htons(SYSLOG_PORT);
1974 }
1975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976
1977 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001978 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001979 curproxy->logfac1 = facility;
1980 curproxy->loglev1 = level;
1981 }
1982 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001983 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001984 curproxy->logfac2 = facility;
1985 curproxy->loglev2 = level;
1986 }
1987 else {
1988 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1989 return -1;
1990 }
1991 }
1992 else {
1993 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1994 file, linenum);
1995 return -1;
1996 }
1997 }
1998 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001999 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2000 return 0;
2001
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002003#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002004 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2005 file, linenum, "source", "usesrc");
2006#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002007 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2008 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002009#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002010 return -1;
2011 }
2012
2013 curproxy->source_addr = *str2sa(args[1]);
2014 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01002015 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002016#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2017#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002018 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2019 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2020 file, linenum, "usesrc");
2021 return -1;
2022 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002023#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002024 if (!*args[3]) {
2025 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2026 file, linenum, "usesrc");
2027 return -1;
2028 }
2029
2030 if (!strcmp(args[3], "client")) {
2031 curproxy->options |= PR_O_TPXY_CLI;
2032 } else if (!strcmp(args[3], "clientip")) {
2033 curproxy->options |= PR_O_TPXY_CIP;
2034 } else {
2035 curproxy->options |= PR_O_TPXY_ADDR;
2036 curproxy->tproxy_addr = *str2sa(args[3]);
2037 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002038 global.last_checks |= LSTCHK_NETADM;
2039#if !defined(CONFIG_HAP_LINUX_TPROXY)
2040 global.last_checks |= LSTCHK_CTTPROXY;
2041#endif
2042#else /* no TPROXY support */
2043 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002044 file, linenum, "usesrc");
2045 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002046#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002047 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002048 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002049 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2050 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2051 file, linenum, "usesrc", "source");
2052 return -1;
2053 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002054 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2055 regex_t *preg;
2056 if (curproxy == &defproxy) {
2057 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2058 return -1;
2059 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002060 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2061 return 0;
2062
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063 if (*(args[1]) == 0 || *(args[2]) == 0) {
2064 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2065 file, linenum, args[0]);
2066 return -1;
2067 }
2068
2069 preg = calloc(1, sizeof(regex_t));
2070 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2071 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2072 return -1;
2073 }
2074
2075 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2076 if (err) {
2077 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2078 file, linenum, *err);
2079 return -1;
2080 }
2081 }
2082 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2083 regex_t *preg;
2084 if (curproxy == &defproxy) {
2085 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2086 return -1;
2087 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002088 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2089 return 0;
2090
Willy Tarreaubaaee002006-06-26 02:48:02 +02002091 if (*(args[1]) == 0) {
2092 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2093 return -1;
2094 }
2095
2096 preg = calloc(1, sizeof(regex_t));
2097 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2098 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2099 return -1;
2100 }
2101
2102 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2103 }
2104 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2105 regex_t *preg;
2106 if (curproxy == &defproxy) {
2107 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2108 return -1;
2109 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002110 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2111 return 0;
2112
Willy Tarreaubaaee002006-06-26 02:48:02 +02002113 if (*(args[1]) == 0) {
2114 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2115 return -1;
2116 }
2117
2118 preg = calloc(1, sizeof(regex_t));
2119 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2120 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2121 return -1;
2122 }
2123
2124 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2125 }
2126 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2127 regex_t *preg;
2128 if (curproxy == &defproxy) {
2129 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2130 return -1;
2131 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002132 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2133 return 0;
2134
Willy Tarreaubaaee002006-06-26 02:48:02 +02002135 if (*(args[1]) == 0) {
2136 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2137 return -1;
2138 }
2139
2140 preg = calloc(1, sizeof(regex_t));
2141 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2142 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2143 return -1;
2144 }
2145
2146 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2147 }
2148 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2149 regex_t *preg;
2150 if (curproxy == &defproxy) {
2151 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2152 return -1;
2153 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002154 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2155 return 0;
2156
Willy Tarreaubaaee002006-06-26 02:48:02 +02002157 if (*(args[1]) == 0) {
2158 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2159 return -1;
2160 }
2161
2162 preg = calloc(1, sizeof(regex_t));
2163 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2164 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2165 return -1;
2166 }
2167
2168 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2169 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002170 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2171 regex_t *preg;
2172 if (curproxy == &defproxy) {
2173 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2174 return -1;
2175 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002176 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2177 return 0;
2178
Willy Tarreaub8750a82006-09-03 09:56:00 +02002179 if (*(args[1]) == 0) {
2180 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2181 return -1;
2182 }
2183
2184 preg = calloc(1, sizeof(regex_t));
2185 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2186 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2187 return -1;
2188 }
2189
2190 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2191 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002192 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2193 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002194 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002195 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2196 return -1;
2197 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002198 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2199 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002200
Willy Tarreau977b8e42006-12-29 14:19:17 +01002201 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002202 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2203 file, linenum, args[0]);
2204 return -1;
2205 }
2206
2207 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002208 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002209 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2210 }
2211
2212 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2213 }
2214 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2215 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002216 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002217 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2218 return -1;
2219 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002220 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2221 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002222
Willy Tarreau977b8e42006-12-29 14:19:17 +01002223 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002224 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2225 file, linenum, args[0]);
2226 return -1;
2227 }
2228
2229 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002230 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002231 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2232 }
2233
2234 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2237 regex_t *preg;
2238 if (curproxy == &defproxy) {
2239 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2240 return -1;
2241 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002242 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2243 return 0;
2244
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 if (*(args[1]) == 0 || *(args[2]) == 0) {
2246 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2247 file, linenum, args[0]);
2248 return -1;
2249 }
2250
2251 preg = calloc(1, sizeof(regex_t));
2252 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2253 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2254 return -1;
2255 }
2256
2257 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2258 if (err) {
2259 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2260 file, linenum, *err);
2261 return -1;
2262 }
2263 }
2264 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2265 regex_t *preg;
2266 if (curproxy == &defproxy) {
2267 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2268 return -1;
2269 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002270 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2271 return 0;
2272
Willy Tarreaubaaee002006-06-26 02:48:02 +02002273 if (*(args[1]) == 0) {
2274 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2275 return -1;
2276 }
2277
2278 preg = calloc(1, sizeof(regex_t));
2279 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2280 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2281 return -1;
2282 }
2283
2284 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2285 }
2286 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2287 regex_t *preg;
2288 if (curproxy == &defproxy) {
2289 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2290 return -1;
2291 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002292 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2293 return 0;
2294
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295 if (*(args[1]) == 0) {
2296 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2297 return -1;
2298 }
2299
2300 preg = calloc(1, sizeof(regex_t));
2301 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2302 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2303 return -1;
2304 }
2305
2306 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2307 }
2308 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2309 regex_t *preg;
2310 if (curproxy == &defproxy) {
2311 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2312 return -1;
2313 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002314 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2315 return 0;
2316
Willy Tarreaubaaee002006-06-26 02:48:02 +02002317 if (*(args[1]) == 0) {
2318 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2319 return -1;
2320 }
2321
2322 preg = calloc(1, sizeof(regex_t));
2323 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2324 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2325 return -1;
2326 }
2327
2328 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2329 }
2330 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2331 regex_t *preg;
2332 if (curproxy == &defproxy) {
2333 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2334 return -1;
2335 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002336 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2337 return 0;
2338
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 if (*(args[1]) == 0) {
2340 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2341 return -1;
2342 }
2343
2344 preg = calloc(1, sizeof(regex_t));
2345 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2346 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2347 return -1;
2348 }
2349
2350 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2351 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002352 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2353 regex_t *preg;
2354 if (curproxy == &defproxy) {
2355 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2356 return -1;
2357 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002358 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2359 return 0;
2360
Willy Tarreaub8750a82006-09-03 09:56:00 +02002361 if (*(args[1]) == 0) {
2362 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2363 return -1;
2364 }
2365
2366 preg = calloc(1, sizeof(regex_t));
2367 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2368 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2369 return -1;
2370 }
2371
2372 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2373 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002374 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2375 if (curproxy == &defproxy) {
2376 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2377 return -1;
2378 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002379 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2380 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381
2382 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2383 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2384 return 0;
2385 }
2386
2387 if (*(args[1]) == 0) {
2388 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2389 return -1;
2390 }
2391
2392 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2393 }
2394 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2395 regex_t *preg;
2396
2397 if (*(args[1]) == 0 || *(args[2]) == 0) {
2398 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2399 file, linenum, args[0]);
2400 return -1;
2401 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002402 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2403 return 0;
2404
Willy Tarreaubaaee002006-06-26 02:48:02 +02002405 preg = calloc(1, sizeof(regex_t));
2406 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2407 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2408 return -1;
2409 }
2410
2411 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2412 if (err) {
2413 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2414 file, linenum, *err);
2415 return -1;
2416 }
2417 }
2418 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2419 regex_t *preg;
2420 if (curproxy == &defproxy) {
2421 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2422 return -1;
2423 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002424 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2425 return 0;
2426
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 if (*(args[1]) == 0) {
2428 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2429 return -1;
2430 }
2431
2432 preg = calloc(1, sizeof(regex_t));
2433 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2434 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2435 return -1;
2436 }
2437
2438 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2439 if (err) {
2440 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2441 file, linenum, *err);
2442 return -1;
2443 }
2444 }
2445 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2446 regex_t *preg;
2447 if (curproxy == &defproxy) {
2448 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2449 return -1;
2450 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002451 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2452 return 0;
2453
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454 if (*(args[1]) == 0) {
2455 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2456 return -1;
2457 }
2458
2459 preg = calloc(1, sizeof(regex_t));
2460 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2461 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2462 return -1;
2463 }
2464
2465 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2466 if (err) {
2467 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2468 file, linenum, *err);
2469 return -1;
2470 }
2471 }
2472 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2473 regex_t *preg;
2474 if (curproxy == &defproxy) {
2475 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2476 return -1;
2477 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002478 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2479 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480
2481 if (*(args[1]) == 0 || *(args[2]) == 0) {
2482 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2483 file, linenum, args[0]);
2484 return -1;
2485 }
2486
2487 preg = calloc(1, sizeof(regex_t));
2488 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2489 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2490 return -1;
2491 }
2492
2493 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2494 if (err) {
2495 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2496 file, linenum, *err);
2497 return -1;
2498 }
2499 }
2500 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2501 regex_t *preg;
2502 if (curproxy == &defproxy) {
2503 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2504 return -1;
2505 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002506 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2507 return 0;
2508
Willy Tarreaubaaee002006-06-26 02:48:02 +02002509 if (*(args[1]) == 0) {
2510 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2511 return -1;
2512 }
2513
2514 preg = calloc(1, sizeof(regex_t));
2515 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2516 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2517 return -1;
2518 }
2519
2520 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2521 if (err) {
2522 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2523 file, linenum, *err);
2524 return -1;
2525 }
2526 }
2527 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2528 regex_t *preg;
2529 if (curproxy == &defproxy) {
2530 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2531 return -1;
2532 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002533 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2534 return 0;
2535
Willy Tarreaubaaee002006-06-26 02:48:02 +02002536 if (*(args[1]) == 0) {
2537 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2538 return -1;
2539 }
2540
2541 preg = calloc(1, sizeof(regex_t));
2542 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2543 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2544 return -1;
2545 }
2546
2547 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2548 if (err) {
2549 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2550 file, linenum, *err);
2551 return -1;
2552 }
2553 }
2554 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2555 if (curproxy == &defproxy) {
2556 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2557 return -1;
2558 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002559 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2560 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561
2562 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2563 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2564 return 0;
2565 }
2566
2567 if (*(args[1]) == 0) {
2568 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2569 return -1;
2570 }
2571
2572 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2573 }
2574 else if (!strcmp(args[0], "errorloc") ||
2575 !strcmp(args[0], "errorloc302") ||
2576 !strcmp(args[0], "errorloc303")) { /* error location */
2577 int errnum, errlen;
2578 char *err;
2579
Willy Tarreau977b8e42006-12-29 14:19:17 +01002580 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2581 return 0;
2582
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002584 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 return -1;
2586 }
2587
2588 errnum = atol(args[1]);
2589 if (!strcmp(args[0], "errorloc303")) {
2590 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2591 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2592 } else {
2593 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2594 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2595 }
2596
Willy Tarreau0f772532006-12-23 20:51:41 +01002597 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2598 if (http_err_codes[rc] == errnum) {
2599 if (curproxy->errmsg[rc].str)
2600 free(curproxy->errmsg[rc].str);
2601 curproxy->errmsg[rc].str = err;
2602 curproxy->errmsg[rc].len = errlen;
2603 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002606
2607 if (rc >= HTTP_ERR_SIZE) {
2608 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2609 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 free(err);
2611 }
2612 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002613 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2614 int errnum, errlen, fd;
2615 char *err;
2616 struct stat stat;
2617
2618 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2619 return 0;
2620
2621 if (*(args[2]) == 0) {
2622 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2623 return -1;
2624 }
2625
2626 fd = open(args[2], O_RDONLY);
2627 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2628 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2629 file, linenum, args[2], args[1]);
2630 if (fd >= 0)
2631 close(fd);
2632 return -1;
2633 }
2634
2635 if (stat.st_size <= BUFSIZE) {
2636 errlen = stat.st_size;
2637 } else {
2638 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2639 file, linenum, args[2], BUFSIZE);
2640 errlen = BUFSIZE;
2641 }
2642
2643 err = malloc(errlen); /* malloc() must succeed during parsing */
2644 errnum = read(fd, err, errlen);
2645 if (errnum != errlen) {
2646 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2647 file, linenum, args[2], args[1]);
2648 close(fd);
2649 free(err);
2650 return -1;
2651 }
2652 close(fd);
2653
2654 errnum = atol(args[1]);
2655 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2656 if (http_err_codes[rc] == errnum) {
2657 if (curproxy->errmsg[rc].str)
2658 free(curproxy->errmsg[rc].str);
2659 curproxy->errmsg[rc].str = err;
2660 curproxy->errmsg[rc].len = errlen;
2661 break;
2662 }
2663 }
2664
2665 if (rc >= HTTP_ERR_SIZE) {
2666 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2667 file, linenum, errnum);
2668 free(err);
2669 }
2670 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002671 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002672 struct cfg_kw_list *kwl;
2673 int index;
2674
2675 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2676 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2677 if (kwl->kw[index].section != CFG_LISTEN)
2678 continue;
2679 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2680 /* prepare error message just in case */
2681 snprintf(trash, sizeof(trash),
2682 "error near '%s' in %s section", args[0], cursection);
2683 if (kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash)) < 0) {
2684 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2685 return -1;
2686 }
2687 return 0;
2688 }
2689 }
2690 }
2691
Willy Tarreau6daf3432008-01-22 16:44:08 +01002692 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002693 return -1;
2694 }
2695 return 0;
2696}
2697
2698
2699/*
2700 * This function reads and parses the configuration file given in the argument.
2701 * returns 0 if OK, -1 if error.
2702 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002703int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002704{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002705 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002706 FILE *f;
2707 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002708 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002709 int confsect = CFG_NONE;
2710
2711 struct proxy *curproxy = NULL;
2712 struct server *newsrv = NULL;
2713
2714 if ((f=fopen(file,"r")) == NULL)
2715 return -1;
2716
2717 init_default_instance();
2718
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002719 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002720 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002721 char *end;
2722 char *args[MAX_LINE_ARGS + 1];
2723 char *line = thisline;
2724
Willy Tarreaubaaee002006-06-26 02:48:02 +02002725 linenum++;
2726
2727 end = line + strlen(line);
2728
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002729 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2730 /* Check if we reached the limit and the last char is not \n.
2731 * Watch out for the last line without the terminating '\n'!
2732 */
2733 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2734 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002735 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002736 }
2737
Willy Tarreaubaaee002006-06-26 02:48:02 +02002738 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002739 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 line++;
2741
2742 arg = 0;
2743 args[arg] = line;
2744
2745 while (*line && arg < MAX_LINE_ARGS) {
2746 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2747 * C equivalent value. Other combinations left unchanged (eg: \1).
2748 */
2749 if (*line == '\\') {
2750 int skip = 0;
2751 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2752 *line = line[1];
2753 skip = 1;
2754 }
2755 else if (line[1] == 'r') {
2756 *line = '\r';
2757 skip = 1;
2758 }
2759 else if (line[1] == 'n') {
2760 *line = '\n';
2761 skip = 1;
2762 }
2763 else if (line[1] == 't') {
2764 *line = '\t';
2765 skip = 1;
2766 }
2767 else if (line[1] == 'x') {
2768 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2769 unsigned char hex1, hex2;
2770 hex1 = toupper(line[2]) - '0';
2771 hex2 = toupper(line[3]) - '0';
2772 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2773 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2774 *line = (hex1<<4) + hex2;
2775 skip = 3;
2776 }
2777 else {
2778 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002779 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780 }
2781 }
2782 if (skip) {
2783 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2784 end -= skip;
2785 }
2786 line++;
2787 }
2788 else if (*line == '#' || *line == '\n' || *line == '\r') {
2789 /* end of string, end of loop */
2790 *line = 0;
2791 break;
2792 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002793 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002794 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002795 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002796 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002797 line++;
2798 args[++arg] = line;
2799 }
2800 else {
2801 line++;
2802 }
2803 }
2804
2805 /* empty line */
2806 if (!**args)
2807 continue;
2808
Willy Tarreau540abe42007-05-02 20:50:16 +02002809 /* zero out remaining args and ensure that at least one entry
2810 * is zeroed out.
2811 */
2812 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002813 args[arg] = line;
2814 }
2815
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002816 if (!strcmp(args[0], "no")) {
2817 inv = 1;
2818 for (arg=0; *args[arg+1]; arg++)
2819 args[arg] = args[arg+1]; // shift args after inversion
2820 }
2821
2822 if (inv && strcmp(args[0], "option")) {
2823 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002824 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002825 }
2826
Willy Tarreau977b8e42006-12-29 14:19:17 +01002827 if (!strcmp(args[0], "listen") ||
2828 !strcmp(args[0], "frontend") ||
2829 !strcmp(args[0], "backend") ||
2830 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002831 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832 confsect = CFG_LISTEN;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002833 if (cursection)
2834 free(cursection);
2835 cursection = strdup(args[0]);
2836 }
2837 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002838 confsect = CFG_GLOBAL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002839 if (cursection)
2840 free(cursection);
2841 cursection = strdup(args[0]);
2842 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002843 /* else it's a section keyword */
2844
2845 switch (confsect) {
2846 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002847 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002848 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849 break;
2850 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002851 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002852 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002853 break;
2854 default:
2855 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002856 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002857 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002858 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01002859 if (cursection)
2860 free(cursection);
2861 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002862 fclose(f);
2863
2864 /*
2865 * Now, check for the integrity of all that we have collected.
2866 */
2867
2868 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002869 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870
2871 if ((curproxy = proxy) == NULL) {
2872 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2873 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002874 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875 }
2876
2877 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002878 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002879 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002880
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 if (curproxy->state == PR_STSTOPPED) {
2882 curproxy = curproxy->next;
2883 continue;
2884 }
2885
Willy Tarreau977b8e42006-12-29 14:19:17 +01002886 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2887 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 +01002888 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002889 cfgerr++;
2890 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002891 else if (curproxy->cap & PR_CAP_BE &&
2892 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002893 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002894 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002895 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2896 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 +01002897 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002898 cfgerr++;
2899 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002900
Willy Tarreau31682232007-11-29 15:38:04 +01002901 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002902 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002903 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002904 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002905 cfgerr++;
2906 }
2907#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2908 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002909 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002910 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002911 cfgerr++;
2912 }
2913#endif
2914 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002915 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002916 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002917 }
2918 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002919
2920 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002921 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002922 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002923 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002925 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002926 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002927 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928 }
2929 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002930 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002931 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002932 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002933 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002934 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002935 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002936 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002937 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002938 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2939 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002940
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002941 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002942 file, proxy_type_str(curproxy), curproxy->id);
2943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002944 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002945
2946 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2947 if ((newsrv = curproxy->srv) != NULL) {
2948 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2949 file, proxy_type_str(curproxy), curproxy->id);
2950 }
2951 }
2952
2953 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002954 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2955 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2956 file, curproxy->id);
2957 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002958 }
2959 }
2960
Willy Tarreau82936582007-11-30 15:20:09 +01002961 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2962 curproxy->options &= ~PR_O_DISABLE404;
2963 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2964 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2965 }
2966
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002967 /* if a default backend was specified, let's find it */
2968 if (curproxy->defbe.name) {
2969 struct proxy *target;
2970
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002971 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2972 if (!target) {
2973 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2974 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002975 cfgerr++;
2976 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002977 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2978 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002979 } else {
2980 free(curproxy->defbe.name);
2981 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002982 }
2983 }
2984
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002985 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002986 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2987 /* map jump target for ACT_SETBE in req_rep chain */
2988 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002989 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002990 struct proxy *target;
2991
Willy Tarreaua496b602006-12-17 23:15:24 +01002992 if (exp->action != ACT_SETBE)
2993 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002994
2995 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2996 if (!target) {
2997 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2998 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002999 cfgerr++;
3000 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003001 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3002 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003003 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003004 } else {
3005 free((void *)exp->replace);
3006 exp->replace = (const char *)target;
3007 }
3008 }
3009 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003010
3011 /* find the target proxy for 'use_backend' rules */
3012 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003013 struct proxy *target;
3014
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003015 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003016
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003017 if (!target) {
3018 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3019 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003020 cfgerr++;
3021 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003022 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3023 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003024 cfgerr++;
3025 } else {
3026 free((void *)rule->be.name);
3027 rule->be.backend = target;
3028 }
3029 }
3030
Willy Tarreau2738a142006-07-08 17:28:09 +02003031 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003032 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003033 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003034 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003035 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003036 " | While not properly invalid, you will certainly encounter various problems\n"
3037 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003038 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003039 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003040 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003041
Willy Tarreau1fa31262007-12-03 00:36:16 +01003042 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3043 * We must still support older configurations, so let's find out whether those
3044 * parameters have been set or must be copied from contimeouts.
3045 */
3046 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003047 if (!curproxy->timeout.tarpit ||
3048 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003049 /* tarpit timeout not set. We search in the following order:
3050 * default.tarpit, curr.connect, default.connect.
3051 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003052 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003053 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003054 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003055 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003056 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003057 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003058 }
3059 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003060 (!curproxy->timeout.queue ||
3061 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003062 /* queue timeout not set. We search in the following order:
3063 * default.queue, curr.connect, default.connect.
3064 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003065 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003066 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003067 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003068 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003069 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003070 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003071 }
3072 }
3073
Willy Tarreauf3c69202006-07-09 16:42:34 +02003074 if (curproxy->options & PR_O_SSL3_CHK) {
3075 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3076 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3077 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3078 }
3079
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003080 /* The small pools required for the capture lists */
3081 if (curproxy->nb_req_cap)
3082 curproxy->req_cap_pool = create_pool("ptrcap",
3083 curproxy->nb_req_cap * sizeof(char *),
3084 MEM_F_SHARED);
3085 if (curproxy->nb_rsp_cap)
3086 curproxy->rsp_cap_pool = create_pool("ptrcap",
3087 curproxy->nb_rsp_cap * sizeof(char *),
3088 MEM_F_SHARED);
3089
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003090 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3091 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3092 MEM_F_SHARED);
3093
Willy Tarreau86034312006-12-29 00:10:33 +01003094 /* for backwards compatibility with "listen" instances, if
3095 * fullconn is not set but maxconn is set, then maxconn
3096 * is used.
3097 */
3098 if (!curproxy->fullconn)
3099 curproxy->fullconn = curproxy->maxconn;
3100
Willy Tarreaubaaee002006-06-26 02:48:02 +02003101 /* first, we will invert the servers list order */
3102 newsrv = NULL;
3103 while (curproxy->srv) {
3104 struct server *next;
3105
3106 next = curproxy->srv->next;
3107 curproxy->srv->next = newsrv;
3108 newsrv = curproxy->srv;
3109 if (!next)
3110 break;
3111 curproxy->srv = next;
3112 }
3113
Willy Tarreau20697042007-11-15 23:26:18 +01003114 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003115 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116
Willy Tarreaub625a082007-11-26 01:15:43 +01003117 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003118 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003119 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003120 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3121 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003122 else
3123 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124
3125 if (curproxy->options & PR_O_LOGASAP)
3126 curproxy->to_log &= ~LW_BYTES;
3127
Willy Tarreaubaaee002006-06-26 02:48:02 +02003128 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003129 * ensure that we're not cross-dressing a TCP server into HTTP.
3130 */
3131 newsrv = curproxy->srv;
3132 while (newsrv != NULL) {
3133 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3134 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3135 file, proxy_type_str(curproxy), curproxy->id, linenum);
3136 goto err;
3137 }
3138 newsrv = newsrv->next;
3139 }
3140
3141 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 * If this server supports a maxconn parameter, it needs a dedicated
3143 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003144 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 */
3146 newsrv = curproxy->srv;
3147 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003148 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003149 /* Only 'minconn' was specified, or it was higher than or equal
3150 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3151 * this will avoid further useless expensive computations.
3152 */
3153 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003154 } else if (newsrv->maxconn && !newsrv->minconn) {
3155 /* minconn was not specified, so we set it to maxconn */
3156 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003157 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3158 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003159 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003160 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003161 }
3162
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003163 if (newsrv->trackit) {
3164 struct proxy *px;
3165 struct server *srv;
3166 char *pname, *sname;
3167
3168 pname = newsrv->trackit;
3169 sname = strrchr(pname, '/');
3170
3171 if (sname)
3172 *sname++ = '\0';
3173 else {
3174 sname = pname;
3175 pname = NULL;
3176 }
3177
3178 if (pname) {
3179 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3180 if (!px) {
3181 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3182 file, proxy_type_str(curproxy), curproxy->id,
3183 newsrv->id, pname);
3184 return -1;
3185 }
3186 } else
3187 px = curproxy;
3188
3189 srv = findserver(px, sname);
3190 if (!srv) {
3191 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3192 file, proxy_type_str(curproxy), curproxy->id,
3193 newsrv->id, sname);
3194 return -1;
3195 }
3196
3197 if (!(srv->state & SRV_CHECKED)) {
3198 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3199 "tracing as it does not have checks enabled.\n",
3200 file, proxy_type_str(curproxy), curproxy->id,
3201 newsrv->id, px->id, srv->id);
3202 return -1;
3203 }
3204
3205 if (curproxy != px &&
3206 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3207 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3208 "tracing: disable-on-404 option inconsistency.\n",
3209 file, proxy_type_str(curproxy), curproxy->id,
3210 newsrv->id, px->id, srv->id);
3211 return -1;
3212 }
3213
3214 newsrv->tracked = srv;
3215 newsrv->tracknext = srv->tracknext;
3216 srv->tracknext = newsrv;
3217
3218 free(newsrv->trackit);
3219 }
3220
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 newsrv = newsrv->next;
3222 }
3223
Willy Tarreaue6b98942007-10-29 01:09:36 +01003224 /* adjust this proxy's listeners */
3225 listener = curproxy->listen;
3226 while (listener) {
3227 if (curproxy->options & PR_O_TCP_NOLING)
3228 listener->options |= LI_O_NOLINGER;
3229 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003230 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003231 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003232 listener->accept = event_accept;
3233 listener->private = curproxy;
3234
3235 listener = listener->next;
3236 }
3237
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 curproxy = curproxy->next;
3239 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003240
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 if (cfgerr > 0) {
3242 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003243 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003245
3246 /*
3247 * Recount currently required checks.
3248 */
3249
3250 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3251 int optnum;
3252
3253 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3254 if (!(curproxy->options & cfg_opts[optnum].val))
3255 continue;
3256
3257 global.last_checks |= cfg_opts[optnum].checks;
3258 }
3259 }
3260
Willy Tarreau6daf3432008-01-22 16:44:08 +01003261 if (cursection)
3262 free(cursection);
3263 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003264 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003265
3266 err:
3267 if (cursection)
3268 free(cursection);
3269 cursection = NULL;
3270 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271}
3272
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003273/*
3274 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3275 * parsing sessions.
3276 */
3277void cfg_register_keywords(struct cfg_kw_list *kwl)
3278{
3279 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3280}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003282/*
3283 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3284 */
3285void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3286{
3287 LIST_DEL(&kwl->list);
3288 LIST_INIT(&kwl->list);
3289}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290
3291/*
3292 * Local variables:
3293 * c-indent-level: 8
3294 * c-basic-offset: 8
3295 * End:
3296 */