blob: 0b1a0bafc59664b510e98afe5d4212657ac9ed99 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau0b4ed902007-03-26 00:18:40 +02004 * Copyright 2000-2007 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
124/*
125 * converts <str> to a list of listeners which are dynamically allocated.
126 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
127 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
128 * - <port> is a numerical port from 1 to 65535 ;
129 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
130 * This can be repeated as many times as necessary, separated by a coma.
131 * The <tail> argument is a pointer to a current list which should be appended
132 * to the tail of the new list. The pointer to the new list is returned.
133 */
134static struct listener *str2listener(char *str, struct listener *tail)
135{
136 struct listener *l;
137 char *c, *next, *range, *dupstr;
138 int port, end;
139
140 next = dupstr = strdup(str);
141
142 while (next && *next) {
143 struct sockaddr_storage ss;
144
145 str = next;
146 /* 1) look for the end of the first address */
147 if ((next = strrchr(str, ',')) != NULL) {
148 *next++ = 0;
149 }
150
151 /* 2) look for the addr/port delimiter, it's the last colon. */
152 if ((range = strrchr(str, ':')) == NULL) {
153 Alert("Missing port number: '%s'\n", str);
154 goto fail;
155 }
156
157 *range++ = 0;
158
159 if (strrchr(str, ':') != NULL) {
160 /* IPv6 address contains ':' */
161 memset(&ss, 0, sizeof(ss));
162 ss.ss_family = AF_INET6;
163
164 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
165 Alert("Invalid server address: '%s'\n", str);
166 goto fail;
167 }
168 }
169 else {
170 memset(&ss, 0, sizeof(ss));
171 ss.ss_family = AF_INET;
172
173 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
174 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
175 }
176 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
177 struct hostent *he;
178
179 if ((he = gethostbyname(str)) == NULL) {
180 Alert("Invalid server name: '%s'\n", str);
181 goto fail;
182 }
183 else
184 ((struct sockaddr_in *)&ss)->sin_addr =
185 *(struct in_addr *) *(he->h_addr_list);
186 }
187 }
188
189 /* 3) look for the port-end delimiter */
190 if ((c = strchr(range, '-')) != NULL) {
191 *c++ = 0;
192 end = atol(c);
193 }
194 else {
195 end = atol(range);
196 }
197
198 port = atol(range);
199
200 if (port < 1 || port > 65535) {
201 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
202 goto fail;
203 }
204
205 if (end < 1 || end > 65535) {
206 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
207 goto fail;
208 }
209
210 for (; port <= end; port++) {
211 l = (struct listener *)calloc(1, sizeof(struct listener));
212 l->next = tail;
213 tail = l;
214
215 l->fd = -1;
216 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100217 l->state = LI_INIT;
218
219 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100221 tcpv6_add_listener(l);
222 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100224 tcpv4_add_listener(l);
225 }
226 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 } /* end for(port) */
228 } /* end while(next) */
229 free(dupstr);
230 return tail;
231 fail:
232 free(dupstr);
233 return NULL;
234}
235
Willy Tarreau977b8e42006-12-29 14:19:17 +0100236/*
237 * Sends a warning if proxy <proxy> does not have at least one of the
238 * capabilities in <cap>. An optionnal <hint> may be added at the end
239 * of the warning to help the user. Returns 1 if a warning was emitted
240 * or 0 if the condition is valid.
241 */
242int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
243{
244 char *msg;
245
246 switch (cap) {
247 case PR_CAP_BE: msg = "no backend"; break;
248 case PR_CAP_FE: msg = "no frontend"; break;
249 case PR_CAP_RS: msg = "no ruleset"; break;
250 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
251 default: msg = "not enough"; break;
252 }
253
254 if (!(proxy->cap & cap)) {
255 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100256 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100257 return 1;
258 }
259 return 0;
260}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261
262/*
263 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
264 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100265int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266{
267
268 if (!strcmp(args[0], "global")) { /* new section */
269 /* no option, nothing special to do */
270 return 0;
271 }
272 else if (!strcmp(args[0], "daemon")) {
273 global.mode |= MODE_DAEMON;
274 }
275 else if (!strcmp(args[0], "debug")) {
276 global.mode |= MODE_DEBUG;
277 }
278 else if (!strcmp(args[0], "noepoll")) {
279 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
280 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200281 else if (!strcmp(args[0], "nosepoll")) {
282 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
283 }
284 else if (!strcmp(args[0], "nokqueue")) {
285 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
286 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200287 else if (!strcmp(args[0], "nopoll")) {
288 cfg_polling_mechanism &= ~POLL_USE_POLL;
289 }
290 else if (!strcmp(args[0], "quiet")) {
291 global.mode |= MODE_QUIET;
292 }
293 else if (!strcmp(args[0], "stats")) {
Willy Tarreaufbee7132007-10-18 13:53:22 +0200294 memcpy(trash, "error near 'stats'", 19);
295 if (stats_parse_global((const char **)args + 1, trash, sizeof(trash)) < 0) {
296 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
297 return -1;
298 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200300 else if (!strcmp(args[0], "tune.maxpollevents")) {
301 if (global.tune.maxpollevents != 0) {
302 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
303 return 0;
304 }
305 if (*(args[1]) == 0) {
306 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
307 return -1;
308 }
309 global.tune.maxpollevents = atol(args[1]);
310 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100311 else if (!strcmp(args[0], "tune.maxaccept")) {
312 if (global.tune.maxaccept != 0) {
313 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
314 return 0;
315 }
316 if (*(args[1]) == 0) {
317 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
318 return -1;
319 }
320 global.tune.maxaccept = atol(args[1]);
321 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200322 else if (!strcmp(args[0], "uid")) {
323 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200324 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200325 return 0;
326 }
327 if (*(args[1]) == 0) {
328 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
329 return -1;
330 }
331 global.uid = atol(args[1]);
332 }
333 else if (!strcmp(args[0], "gid")) {
334 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200335 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200336 return 0;
337 }
338 if (*(args[1]) == 0) {
339 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
340 return -1;
341 }
342 global.gid = atol(args[1]);
343 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200344 /* user/group name handling */
345 else if (!strcmp(args[0], "user")) {
346 struct passwd *ha_user;
347 if (global.uid != 0) {
348 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
349 return 0;
350 }
351 errno = 0;
352 ha_user = getpwnam(args[1]);
353 if (ha_user != NULL) {
354 global.uid = (int)ha_user->pw_uid;
355 }
356 else {
357 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
358 exit(1);
359 }
360 }
361 else if (!strcmp(args[0], "group")) {
362 struct group *ha_group;
363 if (global.gid != 0) {
364 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
365 return 0;
366 }
367 errno = 0;
368 ha_group = getgrnam(args[1]);
369 if (ha_group != NULL) {
370 global.gid = (int)ha_group->gr_gid;
371 }
372 else {
373 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
374 exit(1);
375 }
376 }
377 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200378 else if (!strcmp(args[0], "nbproc")) {
379 if (global.nbproc != 0) {
380 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
381 return 0;
382 }
383 if (*(args[1]) == 0) {
384 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
385 return -1;
386 }
387 global.nbproc = atol(args[1]);
388 }
389 else if (!strcmp(args[0], "maxconn")) {
390 if (global.maxconn != 0) {
391 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
392 return 0;
393 }
394 if (*(args[1]) == 0) {
395 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
396 return -1;
397 }
398 global.maxconn = atol(args[1]);
399#ifdef SYSTEM_MAXCONN
400 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
401 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);
402 global.maxconn = DEFAULT_MAXCONN;
403 }
404#endif /* SYSTEM_MAXCONN */
405 }
406 else if (!strcmp(args[0], "ulimit-n")) {
407 if (global.rlimit_nofile != 0) {
408 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
409 return 0;
410 }
411 if (*(args[1]) == 0) {
412 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
413 return -1;
414 }
415 global.rlimit_nofile = atol(args[1]);
416 }
417 else if (!strcmp(args[0], "chroot")) {
418 if (global.chroot != NULL) {
419 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
420 return 0;
421 }
422 if (*(args[1]) == 0) {
423 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
424 return -1;
425 }
426 global.chroot = strdup(args[1]);
427 }
428 else if (!strcmp(args[0], "pidfile")) {
429 if (global.pidfile != NULL) {
430 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
431 return 0;
432 }
433 if (*(args[1]) == 0) {
434 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
435 return -1;
436 }
437 global.pidfile = strdup(args[1]);
438 }
439 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100440 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200441 int facility, level;
442
443 if (*(args[1]) == 0 || *(args[2]) == 0) {
444 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
445 return -1;
446 }
447
448 facility = get_log_facility(args[2]);
449 if (facility < 0) {
450 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
451 exit(1);
452 }
453
454 level = 7; /* max syslog level = debug */
455 if (*(args[3])) {
456 level = get_log_level(args[3]);
457 if (level < 0) {
458 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
459 exit(1);
460 }
461 }
462
Robert Tsai81ae1952007-12-05 10:47:29 +0100463 if (args[1][0] == '/') {
464 logsrv.u.addr.sa_family = AF_UNIX;
465 logsrv.u.un = *str2sun(args[1]);
466 } else {
467 logsrv.u.addr.sa_family = AF_INET;
468 logsrv.u.in = *str2sa(args[1]);
469 if (!logsrv.u.in.sin_port)
470 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200472
473 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100474 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 global.logfac1 = facility;
476 global.loglev1 = level;
477 }
478 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100479 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200480 global.logfac2 = facility;
481 global.loglev2 = level;
482 }
483 else {
484 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
485 return -1;
486 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200487 }
488 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
489 if (global.spread_checks != 0) {
490 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
491 return 0;
492 }
493 if (*(args[1]) == 0) {
494 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
495 return -1;
496 }
497 global.spread_checks = atol(args[1]);
498 if (global.spread_checks < 0 || global.spread_checks > 50) {
499 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
500 return -1;
501 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200502 }
503 else {
504 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
505 return -1;
506 }
507 return 0;
508}
509
510
511static void init_default_instance()
512{
513 memset(&defproxy, 0, sizeof(defproxy));
514 defproxy.mode = PR_MODE_TCP;
515 defproxy.state = PR_STNEW;
516 defproxy.maxconn = cfg_maxpconn;
517 defproxy.conn_retries = CONN_RETRIES;
518 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100519 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520}
521
522/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100523 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
524 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200525 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100526int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527{
528 static struct proxy *curproxy = NULL;
529 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200530 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100531 int rc;
532 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200533
Willy Tarreau977b8e42006-12-29 14:19:17 +0100534 if (!strcmp(args[0], "listen"))
535 rc = PR_CAP_LISTEN;
536 else if (!strcmp(args[0], "frontend"))
537 rc = PR_CAP_FE | PR_CAP_RS;
538 else if (!strcmp(args[0], "backend"))
539 rc = PR_CAP_BE | PR_CAP_RS;
540 else if (!strcmp(args[0], "ruleset"))
541 rc = PR_CAP_RS;
542 else
543 rc = PR_CAP_NONE;
544
545 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 if (!*args[1]) {
547 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
548 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
549 file, linenum, args[0]);
550 return -1;
551 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200552
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100553 err = invalid_char(args[1]);
554 if (err) {
555 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
556 file, linenum, *err, args[0], args[1]);
557 return -1;
558 }
559
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200560 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
561 /*
562 * If there are two proxies with the same name only following
563 * combinations are allowed:
564 *
565 * listen backend frontend ruleset
566 * listen - - - -
567 * backend - - OK -
568 * frontend - OK - -
569 * ruleset - - - -
570 */
571
572 if (!strcmp(curproxy->id, args[1]) &&
573 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
574 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100575 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
576 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200577 }
578 }
579
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
581 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
582 return -1;
583 }
584
585 curproxy->next = proxy;
586 proxy = curproxy;
587 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200588 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200589 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100590 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200591 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200592
Willy Tarreauee991362007-05-14 14:37:50 +0200593 /* Timeouts are defined as -1, so we cannot use the zeroed area
594 * as a default value.
595 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100596 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200597
598 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100600 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601
602 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100603 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604 curproxy->listen = str2listener(args[2], curproxy->listen);
605 if (!curproxy->listen)
606 return -1;
607 global.maxsock++;
608 }
609
610 /* set default values */
611 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100613 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200614 curproxy->except_net = defproxy.except_net;
615 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616
Willy Tarreau977b8e42006-12-29 14:19:17 +0100617 if (curproxy->cap & PR_CAP_FE) {
618 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100619 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100620
621 /* initialize error relocations */
622 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
623 if (defproxy.errmsg[rc].str)
624 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
625 }
626
627 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629
Willy Tarreau977b8e42006-12-29 14:19:17 +0100630 if (curproxy->cap & PR_CAP_BE) {
631 curproxy->fullconn = defproxy.fullconn;
632 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633
Willy Tarreau977b8e42006-12-29 14:19:17 +0100634 if (defproxy.check_req)
635 curproxy->check_req = strdup(defproxy.check_req);
636 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200637
Willy Tarreau977b8e42006-12-29 14:19:17 +0100638 if (defproxy.cookie_name)
639 curproxy->cookie_name = strdup(defproxy.cookie_name);
640 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100641
642 if (defproxy.url_param_name)
643 curproxy->url_param_name = strdup(defproxy.url_param_name);
644 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100645 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646
Willy Tarreau977b8e42006-12-29 14:19:17 +0100647 if (curproxy->cap & PR_CAP_RS) {
648 if (defproxy.capture_name)
649 curproxy->capture_name = strdup(defproxy.capture_name);
650 curproxy->capture_namelen = defproxy.capture_namelen;
651 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200653
Willy Tarreau977b8e42006-12-29 14:19:17 +0100654 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100655 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100656 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100657 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100658 curproxy->uri_auth = defproxy.uri_auth;
659 curproxy->mon_net = defproxy.mon_net;
660 curproxy->mon_mask = defproxy.mon_mask;
661 if (defproxy.monitor_uri)
662 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
663 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100664 if (defproxy.defbe.name)
665 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100666 }
667
668 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100669 curproxy->timeout.connect = defproxy.timeout.connect;
670 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100671 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100672 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100673 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100674 curproxy->source_addr = defproxy.source_addr;
675 }
676
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 curproxy->mode = defproxy.mode;
678 curproxy->logfac1 = defproxy.logfac1;
679 curproxy->logsrv1 = defproxy.logsrv1;
680 curproxy->loglev1 = defproxy.loglev1;
681 curproxy->logfac2 = defproxy.logfac2;
682 curproxy->logsrv2 = defproxy.logsrv2;
683 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200684 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100685 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
686 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200687
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 return 0;
689 }
690 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
691 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100692 /* FIXME-20070101: we should do this too at the end of the
693 * config parsing to free all default values.
694 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200695 if (defproxy.check_req) free(defproxy.check_req);
696 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100697 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200699 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100700 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100701
702 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
703 if (defproxy.errmsg[rc].len)
704 free(defproxy.errmsg[rc].str);
705 }
706
Willy Tarreaubaaee002006-06-26 02:48:02 +0200707 /* we cannot free uri_auth because it might already be used */
708 init_default_instance();
709 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100710 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 return 0;
712 }
713 else if (curproxy == NULL) {
714 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
715 return -1;
716 }
717
Willy Tarreau977b8e42006-12-29 14:19:17 +0100718
719 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200720 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100721 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200722 if (curproxy == &defproxy) {
723 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
724 return -1;
725 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100726 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
727 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200728
729 if (strchr(args[1], ':') == NULL) {
730 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
731 file, linenum, args[0]);
732 return -1;
733 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100734
735 last_listen = curproxy->listen;
736 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200737 if (!curproxy->listen)
738 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100739 if (*args[2]) {
740#ifdef CONFIG_HAP_LINUX_TPROXY
741 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
742 struct listener *l;
743
744 for (l = curproxy->listen; l != last_listen; l = l->next)
745 l->options |= LI_O_FOREIGN;
746 }
747 else {
748 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
749 file, linenum, args[0]);
750 return -1;
751 }
752#else
753 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
754 file, linenum, args[0]);
755 return -1;
756#endif
757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200758 global.maxsock++;
759 return 0;
760 }
761 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
762 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
763 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
764 file, linenum, args[0]);
765 return -1;
766 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100767 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
768 return 0;
769
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 /* flush useless bits */
771 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
772 return 0;
773 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200774 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100775 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
776 return 0;
777
Willy Tarreau1c47f852006-07-09 08:22:27 +0200778 if (!*args[1]) {
779 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
780 file, linenum, args[0]);
781 return -1;
782 }
783
784 if (curproxy->monitor_uri != NULL)
785 free(curproxy->monitor_uri);
786
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100787 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200788 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100789 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200790 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
791
792 return 0;
793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200794 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
795 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
796 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
797 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
798 else {
799 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
800 return -1;
801 }
802 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100803 else if (!strcmp(args[0], "id")) {
804 struct proxy *target;
805
806 if (curproxy == &defproxy) {
807 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
808 file, linenum, args[0]);
809 return -1;
810 }
811
812 if (!*args[1]) {
813 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
814 file, linenum, args[0]);
815 return -1;
816 }
817
818 curproxy->uuid = atol(args[1]);
819
820 if (curproxy->uuid < 1001) {
821 Alert("parsing [%s:%d]: custom id has to be > 1000",
822 file, linenum);
823 return -1;
824 }
825
826 for (target = proxy; target; target = target->next)
827 if (curproxy != target && curproxy->uuid == target->uuid) {
828 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
829 file, linenum, curproxy->id, target->id);
830 return -1;
831 }
832 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
834 curproxy->state = PR_STSTOPPED;
835 }
836 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
837 curproxy->state = PR_STNEW;
838 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200839 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100840 err = invalid_char(args[1]);
841 if (err) {
842 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
843 file, linenum, *err, args[1]);
844 return -1;
845 }
846
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200847 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
848 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
849 file, linenum, args[1]);
850 return -1;
851 }
852 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200853 else if (!strcmp(args[0], "cookie")) { /* cookie name */
854 int cur_arg;
855 // if (curproxy == &defproxy) {
856 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
857 // return -1;
858 // }
859
Willy Tarreau977b8e42006-12-29 14:19:17 +0100860 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
861 return 0;
862
Willy Tarreaubaaee002006-06-26 02:48:02 +0200863 if (curproxy->cookie_name != NULL) {
864 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
865 // file, linenum);
866 // return 0;
867 free(curproxy->cookie_name);
868 }
869
870 if (*(args[1]) == 0) {
871 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
872 file, linenum, args[0]);
873 return -1;
874 }
875 curproxy->cookie_name = strdup(args[1]);
876 curproxy->cookie_len = strlen(curproxy->cookie_name);
877
878 cur_arg = 2;
879 while (*(args[cur_arg])) {
880 if (!strcmp(args[cur_arg], "rewrite")) {
881 curproxy->options |= PR_O_COOK_RW;
882 }
883 else if (!strcmp(args[cur_arg], "indirect")) {
884 curproxy->options |= PR_O_COOK_IND;
885 }
886 else if (!strcmp(args[cur_arg], "insert")) {
887 curproxy->options |= PR_O_COOK_INS;
888 }
889 else if (!strcmp(args[cur_arg], "nocache")) {
890 curproxy->options |= PR_O_COOK_NOC;
891 }
892 else if (!strcmp(args[cur_arg], "postonly")) {
893 curproxy->options |= PR_O_COOK_POST;
894 }
895 else if (!strcmp(args[cur_arg], "prefix")) {
896 curproxy->options |= PR_O_COOK_PFX;
897 }
898 else {
899 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
900 file, linenum, args[0]);
901 return -1;
902 }
903 cur_arg++;
904 }
905 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
906 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
907 file, linenum);
908 return -1;
909 }
910
911 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
912 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
913 file, linenum);
914 return -1;
915 }
916 }/* end else if (!strcmp(args[0], "cookie")) */
917 else if (!strcmp(args[0], "appsession")) { /* cookie name */
918 // if (curproxy == &defproxy) {
919 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
920 // return -1;
921 // }
922
Willy Tarreau977b8e42006-12-29 14:19:17 +0100923 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
924 return 0;
925
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 if (curproxy->appsession_name != NULL) {
927 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
928 // file, linenum);
929 // return 0;
930 free(curproxy->appsession_name);
931 }
932
933 if (*(args[5]) == 0) {
934 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
935 file, linenum, args[0]);
936 return -1;
937 }
938 have_appsession = 1;
939 curproxy->appsession_name = strdup(args[1]);
940 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
941 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100942 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
943 if (err) {
944 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
945 file, linenum, *err, args[0]);
946 return -1;
947 }
Willy Tarreauee991362007-05-14 14:37:50 +0200948 if (val > 0)
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100949 __tv_from_ms(&curproxy->timeout.appsession, val);
Willy Tarreauee991362007-05-14 14:37:50 +0200950 else
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100951 tv_eternity(&curproxy->timeout.appsession);
Willy Tarreauee991362007-05-14 14:37:50 +0200952
Willy Tarreau51041c72007-09-09 21:56:53 +0200953 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
954 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 return -1;
956 }
957 } /* Url App Session */
958 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100959 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
960 return 0;
961
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
963 // if (curproxy == &defproxy) {
964 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
965 // return -1;
966 // }
967
968 if (curproxy->capture_name != NULL) {
969 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
970 // file, linenum, args[0]);
971 // return 0;
972 free(curproxy->capture_name);
973 }
974
975 if (*(args[4]) == 0) {
976 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
977 file, linenum, args[0]);
978 return -1;
979 }
980 curproxy->capture_name = strdup(args[2]);
981 curproxy->capture_namelen = strlen(curproxy->capture_name);
982 curproxy->capture_len = atol(args[4]);
983 if (curproxy->capture_len >= CAPTURE_LEN) {
984 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
985 file, linenum, CAPTURE_LEN - 1);
986 curproxy->capture_len = CAPTURE_LEN - 1;
987 }
988 curproxy->to_log |= LW_COOKIE;
989 }
990 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
991 struct cap_hdr *hdr;
992
993 if (curproxy == &defproxy) {
994 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
995 return -1;
996 }
997
998 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
999 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1000 file, linenum, args[0], args[1]);
1001 return -1;
1002 }
1003
1004 hdr = calloc(sizeof(struct cap_hdr), 1);
1005 hdr->next = curproxy->req_cap;
1006 hdr->name = strdup(args[3]);
1007 hdr->namelen = strlen(args[3]);
1008 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001009 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001010 hdr->index = curproxy->nb_req_cap++;
1011 curproxy->req_cap = hdr;
1012 curproxy->to_log |= LW_REQHDR;
1013 }
1014 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1015 struct cap_hdr *hdr;
1016
1017 if (curproxy == &defproxy) {
1018 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1019 return -1;
1020 }
1021
1022 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1023 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1024 file, linenum, args[0], args[1]);
1025 return -1;
1026 }
1027 hdr = calloc(sizeof(struct cap_hdr), 1);
1028 hdr->next = curproxy->rsp_cap;
1029 hdr->name = strdup(args[3]);
1030 hdr->namelen = strlen(args[3]);
1031 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001032 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001033 hdr->index = curproxy->nb_rsp_cap++;
1034 curproxy->rsp_cap = hdr;
1035 curproxy->to_log |= LW_RSPHDR;
1036 }
1037 else {
1038 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1039 file, linenum, args[0]);
1040 return -1;
1041 }
1042 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001043 else if (!strcmp(args[0], "contimeout") || !strcmp(args[0], "clitimeout") ||
1044 !strcmp(args[0], "srvtimeout") || !strcmp(args[0], "timeout")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001045
Willy Tarreaue219db72007-12-03 01:30:13 +01001046 /* either we have {con|srv|cli}timeout <value> or we have the
1047 * new form: timeout <type> <value>. The parser needs the word
1048 * preceeding the value.
1049 */
1050 const char **start_arg = (const char **)args;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001051
Willy Tarreaue219db72007-12-03 01:30:13 +01001052 if (strcmp(args[0], "timeout") == 0)
1053 start_arg++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001054
Willy Tarreaue219db72007-12-03 01:30:13 +01001055 snprintf(trash, sizeof(trash), "error near '%s'", args[0]);
1056 rc = proxy_parse_timeout(start_arg, curproxy, &defproxy, trash, sizeof(trash));
1057 if (rc < 0) {
1058 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001059 return -1;
1060 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001061 if (rc > 0)
1062 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001063 }
1064 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001065 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1066 return 0;
1067
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 if (*(args[1]) == 0) {
1069 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1070 file, linenum, args[0]);
1071 return -1;
1072 }
1073 curproxy->conn_retries = atol(args[1]);
1074 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001075 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1076 int pol = ACL_COND_NONE;
1077 struct acl_cond *cond;
1078
1079 if (!strcmp(args[1], "if"))
1080 pol = ACL_COND_IF;
1081 else if (!strcmp(args[1], "unless"))
1082 pol = ACL_COND_UNLESS;
1083
1084 if (pol == ACL_COND_NONE) {
1085 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1086 file, linenum, args[0]);
1087 return -1;
1088 }
1089
1090 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1091 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1092 file, linenum);
1093 return -1;
1094 }
1095 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1096 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001097 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1098 int pol = ACL_COND_NONE;
1099 struct acl_cond *cond;
1100 struct switching_rule *rule;
1101
1102 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1103 return 0;
1104
1105 if (*(args[1]) == 0) {
1106 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1107 return -1;
1108 }
1109
1110 if (!strcmp(args[2], "if"))
1111 pol = ACL_COND_IF;
1112 else if (!strcmp(args[2], "unless"))
1113 pol = ACL_COND_UNLESS;
1114
1115 if (pol == ACL_COND_NONE) {
1116 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1117 file, linenum, args[0]);
1118 return -1;
1119 }
1120
1121 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1122 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1123 file, linenum);
1124 return -1;
1125 }
1126
1127 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1128 rule->cond = cond;
1129 rule->be.name = strdup(args[1]);
1130 LIST_INIT(&rule->list);
1131 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1132 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001133 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001134 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1135 return 0;
1136
Willy Tarreaubaaee002006-06-26 02:48:02 +02001137 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1138 curproxy->uri_auth = NULL; /* we must detach from the default config */
1139
1140 if (*(args[1]) == 0) {
1141 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1142 return -1;
1143 } else if (!strcmp(args[1], "uri")) {
1144 if (*(args[2]) == 0) {
1145 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1146 return -1;
1147 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1148 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1149 return -1;
1150 }
1151 } else if (!strcmp(args[1], "realm")) {
1152 if (*(args[2]) == 0) {
1153 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1154 return -1;
1155 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1156 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1157 return -1;
1158 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001159 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001160 unsigned interval;
1161
1162 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1163 if (err) {
1164 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1165 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001166 return -1;
1167 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1168 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1169 return -1;
1170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001171 } else if (!strcmp(args[1], "auth")) {
1172 if (*(args[2]) == 0) {
1173 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1174 return -1;
1175 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1176 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1177 return -1;
1178 }
1179 } else if (!strcmp(args[1], "scope")) {
1180 if (*(args[2]) == 0) {
1181 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1182 return -1;
1183 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1184 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1185 return -1;
1186 }
1187 } else if (!strcmp(args[1], "enable")) {
1188 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1189 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1190 return -1;
1191 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001192 } else if (!strcmp(args[1], "hide-version")) {
1193 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1194 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1195 return -1;
1196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001198 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001199 file, linenum, args[0]);
1200 return -1;
1201 }
1202 }
1203 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001204 int optnum;
1205
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001206 if (*(args[1]) == '\0') {
1207 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1208 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001209 return -1;
1210 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001211
1212 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1213 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1214 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1215 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001216
1217 if (!inv)
1218 curproxy->options |= cfg_opts[optnum].val;
1219 else
1220 curproxy->options &= ~cfg_opts[optnum].val;
1221
Willy Tarreau13943ab2006-12-31 00:24:10 +01001222 return 0;
1223 }
1224 }
1225
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001226 if (inv) {
1227 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1228 file, linenum, args[1]);
1229 return -1;
1230 }
1231
Willy Tarreau13943ab2006-12-31 00:24:10 +01001232 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001233 /* generate a complete HTTP log */
1234 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1235 else if (!strcmp(args[1], "tcplog"))
1236 /* generate a detailed TCP log */
1237 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001238 else if (!strcmp(args[1], "tcpka")) {
1239 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001240 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1241 return 0;
1242
1243 if (curproxy->cap & PR_CAP_FE)
1244 curproxy->options |= PR_O_TCP_CLI_KA;
1245 if (curproxy->cap & PR_CAP_BE)
1246 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001247 }
1248 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001249 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1250 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001251 /* use HTTP request to check servers' health */
1252 if (curproxy->check_req != NULL) {
1253 free(curproxy->check_req);
1254 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001255 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001256 curproxy->options &= ~PR_O_SMTP_CHK;
1257 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 if (!*args[2]) { /* no argument */
1259 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1260 curproxy->check_len = strlen(DEF_CHECK_REQ);
1261 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001262 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001263 curproxy->check_req = (char *)malloc(reqlen);
1264 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1265 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1266 } else { /* more arguments : METHOD URI [HTTP_VER] */
1267 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1268 if (*args[4])
1269 reqlen += strlen(args[4]);
1270 else
1271 reqlen += strlen("HTTP/1.0");
1272
1273 curproxy->check_req = (char *)malloc(reqlen);
1274 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1275 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1276 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001277 }
1278 else if (!strcmp(args[1], "ssl-hello-chk")) {
1279 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001280 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1281 return 0;
1282
Willy Tarreauf3c69202006-07-09 16:42:34 +02001283 if (curproxy->check_req != NULL) {
1284 free(curproxy->check_req);
1285 }
1286 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001287 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001288 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001289 }
Willy Tarreau23677902007-05-08 23:50:35 +02001290 else if (!strcmp(args[1], "smtpchk")) {
1291 /* use SMTP request to check servers' health */
1292 if (curproxy->check_req != NULL) {
1293 free(curproxy->check_req);
1294 }
1295 curproxy->options &= ~PR_O_HTTP_CHK;
1296 curproxy->options &= ~PR_O_SSL3_CHK;
1297 curproxy->options |= PR_O_SMTP_CHK;
1298
1299 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1300 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1301 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1302 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1303 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1304 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1305 curproxy->check_req = (char *)malloc(reqlen);
1306 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1307 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1308 } else {
1309 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1310 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1311 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1312 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1313 }
1314 }
1315 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001316 else if (!strcmp(args[1], "forwardfor")) {
1317 /* insert x-forwarded-for field, but not for the
1318 * IP address listed as an except.
1319 */
1320 if (*(args[2])) {
1321 if (!strcmp(args[2], "except")) {
1322 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1323 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1324 file, linenum, args[0]);
1325 return -1;
1326 }
1327 /* flush useless bits */
1328 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1329 } else {
1330 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1331 file, linenum, args[0]);
1332 return -1;
1333 }
1334 }
1335 curproxy->options |= PR_O_FWDFOR;
1336 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001337 else {
1338 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1339 return -1;
1340 }
1341 return 0;
1342 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001343 else if (!strcmp(args[0], "default_backend")) {
1344 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1345 return 0;
1346
1347 if (*(args[1]) == 0) {
1348 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1349 return -1;
1350 }
1351 if (curproxy->defbe.name)
1352 free(curproxy->defbe.name);
1353 curproxy->defbe.name = strdup(args[1]);
1354 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001355 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001356 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1357 return 0;
1358
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001359 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1360 file, linenum, args[0]);
1361
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 /* enable reconnections to dispatch */
1363 curproxy->options |= PR_O_REDISP;
1364 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001365 else if (!strcmp(args[0], "http-check")) {
1366 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1367 return 0;
1368
1369 if (strcmp(args[1], "disable-on-404") == 0) {
1370 /* enable a graceful server shutdown on an HTTP 404 response */
1371 curproxy->options |= PR_O_DISABLE404;
1372 }
1373 else {
1374 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1375 return -1;
1376 }
1377 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001378 else if (!strcmp(args[0], "monitor")) {
1379 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1380 return 0;
1381
1382 if (strcmp(args[1], "fail") == 0) {
1383 /* add a condition to fail monitor requests */
1384 int pol = ACL_COND_NONE;
1385 struct acl_cond *cond;
1386
1387 if (!strcmp(args[2], "if"))
1388 pol = ACL_COND_IF;
1389 else if (!strcmp(args[2], "unless"))
1390 pol = ACL_COND_UNLESS;
1391
1392 if (pol == ACL_COND_NONE) {
1393 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1394 file, linenum, args[0], args[1]);
1395 return -1;
1396 }
1397
1398 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1399 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1400 file, linenum, args[0], args[1]);
1401 return -1;
1402 }
1403 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1404 }
1405 else {
1406 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1407 return -1;
1408 }
1409 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410#ifdef TPROXY
1411 else if (!strcmp(args[0], "transparent")) {
1412 /* enable transparent proxy connections */
1413 curproxy->options |= PR_O_TRANSP;
1414 }
1415#endif
1416 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001417 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1418 return 0;
1419
Willy Tarreaubaaee002006-06-26 02:48:02 +02001420 if (*(args[1]) == 0) {
1421 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1422 return -1;
1423 }
1424 curproxy->maxconn = atol(args[1]);
1425 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001426 else if (!strcmp(args[0], "backlog")) { /* backlog */
1427 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1428 return 0;
1429
1430 if (*(args[1]) == 0) {
1431 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1432 return -1;
1433 }
1434 curproxy->backlog = atol(args[1]);
1435 }
Willy Tarreau86034312006-12-29 00:10:33 +01001436 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001437 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1438 return 0;
1439
Willy Tarreau86034312006-12-29 00:10:33 +01001440 if (*(args[1]) == 0) {
1441 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1442 return -1;
1443 }
1444 curproxy->fullconn = atol(args[1]);
1445 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001446 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1447 if (*(args[1]) == 0) {
1448 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1449 return -1;
1450 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001451 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1452 if (err) {
1453 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1454 file, linenum, *err);
1455 return -1;
1456 }
1457 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001458 }
1459 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1460 if (curproxy == &defproxy) {
1461 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1462 return -1;
1463 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001464 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1465 return 0;
1466
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467 if (strchr(args[1], ':') == NULL) {
1468 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1469 return -1;
1470 }
1471 curproxy->dispatch_addr = *str2sa(args[1]);
1472 }
1473 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001474 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1475 return 0;
1476
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001477 memcpy(trash, "error near 'balance'", 19);
1478 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1479 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1480 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001481 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001482 }
1483 else if (!strcmp(args[0], "server")) { /* server address */
1484 int cur_arg;
1485 char *rport;
1486 char *raddr;
1487 short realport;
1488 int do_check;
1489
1490 if (curproxy == &defproxy) {
1491 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1492 return -1;
1493 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001494 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1495 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001496
1497 if (!*args[2]) {
1498 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1499 file, linenum, args[0]);
1500 return -1;
1501 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001502
1503 err = invalid_char(args[1]);
1504 if (err) {
1505 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1506 file, linenum, *err, args[1]);
1507 return -1;
1508 }
1509
Willy Tarreaubaaee002006-06-26 02:48:02 +02001510 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1511 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1512 return -1;
1513 }
1514
1515 /* the servers are linked backwards first */
1516 newsrv->next = curproxy->srv;
1517 curproxy->srv = newsrv;
1518 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001519 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001520
1521 LIST_INIT(&newsrv->pendconns);
1522 do_check = 0;
1523 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001524 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001525 newsrv->id = strdup(args[1]);
1526
1527 /* several ways to check the port component :
1528 * - IP => port=+0, relative
1529 * - IP: => port=+0, relative
1530 * - IP:N => port=N, absolute
1531 * - IP:+N => port=+N, relative
1532 * - IP:-N => port=-N, relative
1533 */
1534 raddr = strdup(args[2]);
1535 rport = strchr(raddr, ':');
1536 if (rport) {
1537 *rport++ = 0;
1538 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001539 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540 newsrv->state |= SRV_MAPPORTS;
1541 } else {
1542 realport = 0;
1543 newsrv->state |= SRV_MAPPORTS;
1544 }
1545
1546 newsrv->addr = *str2sa(raddr);
1547 newsrv->addr.sin_port = htons(realport);
1548 free(raddr);
1549
1550 newsrv->curfd = -1; /* no health-check in progress */
1551 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001552 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1553 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 newsrv->rise = DEF_RISETIME;
1555 newsrv->fall = DEF_FALLTIME;
1556 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001557 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001558 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001559 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001560
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561 cur_arg = 3;
1562 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001563 if (!strcmp(args[cur_arg], "id")) {
1564 struct server *target;
1565
1566 if (!*args[cur_arg + 1]) {
1567 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1568 file, linenum, args[cur_arg]);
1569 return -1;
1570 }
1571
1572 newsrv->puid = atol(args[cur_arg + 1]);
1573
1574 if (newsrv->puid< 1001) {
1575 Alert("parsing [%s:%d]: custom id has to be > 1000",
1576 file, linenum);
1577 return -1;
1578 }
1579
1580 for (target = proxy->srv; target; target = target->next)
1581 if (newsrv != target && newsrv->puid == target->puid) {
1582 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1583 file, linenum, newsrv->id, target->id);
1584 return -1;
1585 }
1586 cur_arg += 2;
1587 }
1588 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 newsrv->cookie = strdup(args[cur_arg + 1]);
1590 newsrv->cklen = strlen(args[cur_arg + 1]);
1591 cur_arg += 2;
1592 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001593 else if (!strcmp(args[cur_arg], "redir")) {
1594 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1595 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1596 cur_arg += 2;
1597 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 else if (!strcmp(args[cur_arg], "rise")) {
1599 newsrv->rise = atol(args[cur_arg + 1]);
1600 newsrv->health = newsrv->rise;
1601 cur_arg += 2;
1602 }
1603 else if (!strcmp(args[cur_arg], "fall")) {
1604 newsrv->fall = atol(args[cur_arg + 1]);
1605 cur_arg += 2;
1606 }
1607 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001608 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1609 if (err) {
1610 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1611 file, linenum, *err, newsrv->id);
1612 return -1;
1613 }
1614 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615 cur_arg += 2;
1616 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001617 else if (!strcmp(args[cur_arg], "fastinter")) {
1618 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1619 if (err) {
1620 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1621 file, linenum, *err, newsrv->id);
1622 return -1;
1623 }
1624 newsrv->fastinter = val;
1625 cur_arg += 2;
1626 }
1627 else if (!strcmp(args[cur_arg], "downinter")) {
1628 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1629 if (err) {
1630 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1631 file, linenum, *err, newsrv->id);
1632 return -1;
1633 }
1634 newsrv->downinter = val;
1635 cur_arg += 2;
1636 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001637 else if (!strcmp(args[cur_arg], "addr")) {
1638 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001639 cur_arg += 2;
1640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001641 else if (!strcmp(args[cur_arg], "port")) {
1642 newsrv->check_port = atol(args[cur_arg + 1]);
1643 cur_arg += 2;
1644 }
1645 else if (!strcmp(args[cur_arg], "backup")) {
1646 newsrv->state |= SRV_BACKUP;
1647 cur_arg ++;
1648 }
1649 else if (!strcmp(args[cur_arg], "weight")) {
1650 int w;
1651 w = atol(args[cur_arg + 1]);
1652 if (w < 1 || w > 256) {
1653 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1654 file, linenum, newsrv->id, w);
1655 return -1;
1656 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001657 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 cur_arg += 2;
1659 }
1660 else if (!strcmp(args[cur_arg], "minconn")) {
1661 newsrv->minconn = atol(args[cur_arg + 1]);
1662 cur_arg += 2;
1663 }
1664 else if (!strcmp(args[cur_arg], "maxconn")) {
1665 newsrv->maxconn = atol(args[cur_arg + 1]);
1666 cur_arg += 2;
1667 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001668 else if (!strcmp(args[cur_arg], "maxqueue")) {
1669 newsrv->maxqueue = atol(args[cur_arg + 1]);
1670 cur_arg += 2;
1671 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001672 else if (!strcmp(args[cur_arg], "slowstart")) {
1673 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001674 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001675 if (err) {
1676 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1677 file, linenum, *err, newsrv->id);
1678 return -1;
1679 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001680 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001681 cur_arg += 2;
1682 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001683 else if (!strcmp(args[cur_arg], "track")) {
1684
1685 if (!*args[cur_arg + 1]) {
1686 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1687 file, linenum);
1688 return -1;
1689 }
1690
1691 newsrv->trackit = strdup(args[cur_arg + 1]);
1692
1693 cur_arg += 2;
1694 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001695 else if (!strcmp(args[cur_arg], "check")) {
1696 global.maxsock++;
1697 do_check = 1;
1698 cur_arg += 1;
1699 }
1700 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1701 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001702#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001703 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1704 file, linenum, "source", "usesrc");
1705#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001706 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1707 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001708#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001709 return -1;
1710 }
1711 newsrv->state |= SRV_BIND_SRC;
1712 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1713 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001714 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001715#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1716#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001717 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001718 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1719 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001720 return -1;
1721 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001722#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001723 if (!*args[cur_arg + 1]) {
1724 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1725 file, linenum, "usesrc");
1726 return -1;
1727 }
1728 if (!strcmp(args[cur_arg + 1], "client")) {
1729 newsrv->state |= SRV_TPROXY_CLI;
1730 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1731 newsrv->state |= SRV_TPROXY_CIP;
1732 } else {
1733 newsrv->state |= SRV_TPROXY_ADDR;
1734 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1735 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001736 global.last_checks |= LSTCHK_NETADM;
1737#if !defined(CONFIG_HAP_LINUX_TPROXY)
1738 global.last_checks |= LSTCHK_CTTPROXY;
1739#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001740 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001741#else /* no TPROXY support */
1742 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001743 file, linenum, "usesrc");
1744 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001745#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001746 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001747 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001748 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1749 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1750 file, linenum, "usesrc", "source");
1751 return -1;
1752 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001753 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001754 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 +02001755 file, linenum, newsrv->id);
1756 return -1;
1757 }
1758 }
1759
1760 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001761 if (newsrv->trackit) {
1762 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1763 file, linenum);
1764 return -1;
1765 }
1766
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001767 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1768 newsrv->check_port = newsrv->check_addr.sin_port;
1769
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1771 newsrv->check_port = realport; /* by default */
1772 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001773 /* not yet valid, because no port was set on
1774 * the server either. We'll check if we have
1775 * a known port on the first listener.
1776 */
1777 struct listener *l;
1778 l = curproxy->listen;
1779 if (l) {
1780 int port;
1781 port = (l->addr.ss_family == AF_INET6)
1782 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1783 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1784 newsrv->check_port = port;
1785 }
1786 }
1787 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001788 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1789 file, linenum, newsrv->id);
1790 return -1;
1791 }
1792 newsrv->state |= SRV_CHECKED;
1793 }
1794
1795 if (newsrv->state & SRV_BACKUP)
1796 curproxy->srv_bck++;
1797 else
1798 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001799
1800 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801 }
1802 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001803 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001804 int facility;
1805
1806 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1807 curproxy->logfac1 = global.logfac1;
1808 curproxy->logsrv1 = global.logsrv1;
1809 curproxy->loglev1 = global.loglev1;
1810 curproxy->logfac2 = global.logfac2;
1811 curproxy->logsrv2 = global.logsrv2;
1812 curproxy->loglev2 = global.loglev2;
1813 }
1814 else if (*(args[1]) && *(args[2])) {
1815 int level;
1816
1817 facility = get_log_facility(args[2]);
1818 if (facility < 0) {
1819 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1820 exit(1);
1821 }
1822
1823 level = 7; /* max syslog level = debug */
1824 if (*(args[3])) {
1825 level = get_log_level(args[3]);
1826 if (level < 0) {
1827 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1828 exit(1);
1829 }
1830 }
1831
Robert Tsai81ae1952007-12-05 10:47:29 +01001832 if (args[1][0] == '/') {
1833 logsrv.u.addr.sa_family = AF_UNIX;
1834 logsrv.u.un = *str2sun(args[1]);
1835 } else {
1836 logsrv.u.addr.sa_family = AF_INET;
1837 logsrv.u.in = *str2sa(args[1]);
1838 if (!logsrv.u.in.sin_port) {
1839 logsrv.u.in.sin_port =
1840 htons(SYSLOG_PORT);
1841 }
1842 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001843
1844 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001845 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001846 curproxy->logfac1 = facility;
1847 curproxy->loglev1 = level;
1848 }
1849 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001850 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001851 curproxy->logfac2 = facility;
1852 curproxy->loglev2 = level;
1853 }
1854 else {
1855 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1856 return -1;
1857 }
1858 }
1859 else {
1860 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1861 file, linenum);
1862 return -1;
1863 }
1864 }
1865 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001866 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1867 return 0;
1868
Willy Tarreaubaaee002006-06-26 02:48:02 +02001869 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001870#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001871 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1872 file, linenum, "source", "usesrc");
1873#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001874 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1875 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001876#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001877 return -1;
1878 }
1879
1880 curproxy->source_addr = *str2sa(args[1]);
1881 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001882 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001883#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1884#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001885 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1886 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1887 file, linenum, "usesrc");
1888 return -1;
1889 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001890#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001891 if (!*args[3]) {
1892 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1893 file, linenum, "usesrc");
1894 return -1;
1895 }
1896
1897 if (!strcmp(args[3], "client")) {
1898 curproxy->options |= PR_O_TPXY_CLI;
1899 } else if (!strcmp(args[3], "clientip")) {
1900 curproxy->options |= PR_O_TPXY_CIP;
1901 } else {
1902 curproxy->options |= PR_O_TPXY_ADDR;
1903 curproxy->tproxy_addr = *str2sa(args[3]);
1904 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001905 global.last_checks |= LSTCHK_NETADM;
1906#if !defined(CONFIG_HAP_LINUX_TPROXY)
1907 global.last_checks |= LSTCHK_CTTPROXY;
1908#endif
1909#else /* no TPROXY support */
1910 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001911 file, linenum, "usesrc");
1912 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001913#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001914 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001916 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1917 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1918 file, linenum, "usesrc", "source");
1919 return -1;
1920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1922 regex_t *preg;
1923 if (curproxy == &defproxy) {
1924 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1925 return -1;
1926 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001927 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1928 return 0;
1929
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930 if (*(args[1]) == 0 || *(args[2]) == 0) {
1931 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1932 file, linenum, args[0]);
1933 return -1;
1934 }
1935
1936 preg = calloc(1, sizeof(regex_t));
1937 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1938 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1939 return -1;
1940 }
1941
1942 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1943 if (err) {
1944 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1945 file, linenum, *err);
1946 return -1;
1947 }
1948 }
1949 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1950 regex_t *preg;
1951 if (curproxy == &defproxy) {
1952 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1953 return -1;
1954 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001955 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1956 return 0;
1957
Willy Tarreaubaaee002006-06-26 02:48:02 +02001958 if (*(args[1]) == 0) {
1959 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1960 return -1;
1961 }
1962
1963 preg = calloc(1, sizeof(regex_t));
1964 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1965 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1966 return -1;
1967 }
1968
1969 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1970 }
1971 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1972 regex_t *preg;
1973 if (curproxy == &defproxy) {
1974 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1975 return -1;
1976 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001977 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1978 return 0;
1979
Willy Tarreaubaaee002006-06-26 02:48:02 +02001980 if (*(args[1]) == 0) {
1981 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1982 return -1;
1983 }
1984
1985 preg = calloc(1, sizeof(regex_t));
1986 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1987 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1988 return -1;
1989 }
1990
1991 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1992 }
1993 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1994 regex_t *preg;
1995 if (curproxy == &defproxy) {
1996 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1997 return -1;
1998 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001999 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2000 return 0;
2001
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002 if (*(args[1]) == 0) {
2003 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2004 return -1;
2005 }
2006
2007 preg = calloc(1, sizeof(regex_t));
2008 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2009 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2010 return -1;
2011 }
2012
2013 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2014 }
2015 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2016 regex_t *preg;
2017 if (curproxy == &defproxy) {
2018 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2019 return -1;
2020 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002021 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2022 return 0;
2023
Willy Tarreaubaaee002006-06-26 02:48:02 +02002024 if (*(args[1]) == 0) {
2025 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2026 return -1;
2027 }
2028
2029 preg = calloc(1, sizeof(regex_t));
2030 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2031 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2032 return -1;
2033 }
2034
2035 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2036 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002037 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2038 regex_t *preg;
2039 if (curproxy == &defproxy) {
2040 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2041 return -1;
2042 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002043 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2044 return 0;
2045
Willy Tarreaub8750a82006-09-03 09:56:00 +02002046 if (*(args[1]) == 0) {
2047 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2048 return -1;
2049 }
2050
2051 preg = calloc(1, sizeof(regex_t));
2052 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2053 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2054 return -1;
2055 }
2056
2057 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2058 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002059 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2060 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002061 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002062 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2063 return -1;
2064 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002065 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2066 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002067
Willy Tarreau977b8e42006-12-29 14:19:17 +01002068 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002069 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2070 file, linenum, args[0]);
2071 return -1;
2072 }
2073
2074 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002075 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002076 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2077 }
2078
2079 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2080 }
2081 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2082 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002083 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002084 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2085 return -1;
2086 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002087 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2088 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002089
Willy Tarreau977b8e42006-12-29 14:19:17 +01002090 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002091 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2092 file, linenum, args[0]);
2093 return -1;
2094 }
2095
2096 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002097 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002098 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2099 }
2100
2101 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2102 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2104 regex_t *preg;
2105 if (curproxy == &defproxy) {
2106 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2107 return -1;
2108 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002109 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2110 return 0;
2111
Willy Tarreaubaaee002006-06-26 02:48:02 +02002112 if (*(args[1]) == 0 || *(args[2]) == 0) {
2113 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2114 file, linenum, args[0]);
2115 return -1;
2116 }
2117
2118 preg = calloc(1, sizeof(regex_t));
2119 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2120 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2121 return -1;
2122 }
2123
2124 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2125 if (err) {
2126 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2127 file, linenum, *err);
2128 return -1;
2129 }
2130 }
2131 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2132 regex_t *preg;
2133 if (curproxy == &defproxy) {
2134 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2135 return -1;
2136 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002137 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2138 return 0;
2139
Willy Tarreaubaaee002006-06-26 02:48:02 +02002140 if (*(args[1]) == 0) {
2141 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2142 return -1;
2143 }
2144
2145 preg = calloc(1, sizeof(regex_t));
2146 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2147 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2148 return -1;
2149 }
2150
2151 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2152 }
2153 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2154 regex_t *preg;
2155 if (curproxy == &defproxy) {
2156 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2157 return -1;
2158 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002159 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2160 return 0;
2161
Willy Tarreaubaaee002006-06-26 02:48:02 +02002162 if (*(args[1]) == 0) {
2163 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2164 return -1;
2165 }
2166
2167 preg = calloc(1, sizeof(regex_t));
2168 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2169 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2170 return -1;
2171 }
2172
2173 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2174 }
2175 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2176 regex_t *preg;
2177 if (curproxy == &defproxy) {
2178 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2179 return -1;
2180 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002181 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2182 return 0;
2183
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 if (*(args[1]) == 0) {
2185 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2186 return -1;
2187 }
2188
2189 preg = calloc(1, sizeof(regex_t));
2190 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2191 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2192 return -1;
2193 }
2194
2195 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2196 }
2197 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2198 regex_t *preg;
2199 if (curproxy == &defproxy) {
2200 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2201 return -1;
2202 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002203 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2204 return 0;
2205
Willy Tarreaubaaee002006-06-26 02:48:02 +02002206 if (*(args[1]) == 0) {
2207 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2208 return -1;
2209 }
2210
2211 preg = calloc(1, sizeof(regex_t));
2212 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2213 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2214 return -1;
2215 }
2216
2217 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2218 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002219 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2220 regex_t *preg;
2221 if (curproxy == &defproxy) {
2222 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2223 return -1;
2224 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002225 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2226 return 0;
2227
Willy Tarreaub8750a82006-09-03 09:56:00 +02002228 if (*(args[1]) == 0) {
2229 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2230 return -1;
2231 }
2232
2233 preg = calloc(1, sizeof(regex_t));
2234 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2235 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2236 return -1;
2237 }
2238
2239 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2242 if (curproxy == &defproxy) {
2243 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2244 return -1;
2245 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002246 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2247 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248
2249 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2250 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2251 return 0;
2252 }
2253
2254 if (*(args[1]) == 0) {
2255 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2256 return -1;
2257 }
2258
2259 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2260 }
2261 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2262 regex_t *preg;
2263
2264 if (*(args[1]) == 0 || *(args[2]) == 0) {
2265 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2266 file, linenum, args[0]);
2267 return -1;
2268 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002269 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2270 return 0;
2271
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 preg = calloc(1, sizeof(regex_t));
2273 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2274 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2275 return -1;
2276 }
2277
2278 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2279 if (err) {
2280 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2281 file, linenum, *err);
2282 return -1;
2283 }
2284 }
2285 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2286 regex_t *preg;
2287 if (curproxy == &defproxy) {
2288 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2289 return -1;
2290 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002291 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2292 return 0;
2293
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 if (*(args[1]) == 0) {
2295 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2296 return -1;
2297 }
2298
2299 preg = calloc(1, sizeof(regex_t));
2300 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2301 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2302 return -1;
2303 }
2304
2305 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2306 if (err) {
2307 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2308 file, linenum, *err);
2309 return -1;
2310 }
2311 }
2312 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2313 regex_t *preg;
2314 if (curproxy == &defproxy) {
2315 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2316 return -1;
2317 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002318 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2319 return 0;
2320
Willy Tarreaubaaee002006-06-26 02:48:02 +02002321 if (*(args[1]) == 0) {
2322 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2323 return -1;
2324 }
2325
2326 preg = calloc(1, sizeof(regex_t));
2327 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2328 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2329 return -1;
2330 }
2331
2332 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2333 if (err) {
2334 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2335 file, linenum, *err);
2336 return -1;
2337 }
2338 }
2339 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2340 regex_t *preg;
2341 if (curproxy == &defproxy) {
2342 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2343 return -1;
2344 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002345 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2346 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002347
2348 if (*(args[1]) == 0 || *(args[2]) == 0) {
2349 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2350 file, linenum, args[0]);
2351 return -1;
2352 }
2353
2354 preg = calloc(1, sizeof(regex_t));
2355 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2356 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2357 return -1;
2358 }
2359
2360 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2361 if (err) {
2362 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2363 file, linenum, *err);
2364 return -1;
2365 }
2366 }
2367 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2368 regex_t *preg;
2369 if (curproxy == &defproxy) {
2370 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2371 return -1;
2372 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002373 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2374 return 0;
2375
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 if (*(args[1]) == 0) {
2377 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2378 return -1;
2379 }
2380
2381 preg = calloc(1, sizeof(regex_t));
2382 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2383 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2384 return -1;
2385 }
2386
2387 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2388 if (err) {
2389 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2390 file, linenum, *err);
2391 return -1;
2392 }
2393 }
2394 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2395 regex_t *preg;
2396 if (curproxy == &defproxy) {
2397 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2398 return -1;
2399 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002400 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2401 return 0;
2402
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 if (*(args[1]) == 0) {
2404 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2405 return -1;
2406 }
2407
2408 preg = calloc(1, sizeof(regex_t));
2409 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2410 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2411 return -1;
2412 }
2413
2414 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2415 if (err) {
2416 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2417 file, linenum, *err);
2418 return -1;
2419 }
2420 }
2421 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2422 if (curproxy == &defproxy) {
2423 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2424 return -1;
2425 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002426 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2427 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428
2429 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2430 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2431 return 0;
2432 }
2433
2434 if (*(args[1]) == 0) {
2435 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2436 return -1;
2437 }
2438
2439 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2440 }
2441 else if (!strcmp(args[0], "errorloc") ||
2442 !strcmp(args[0], "errorloc302") ||
2443 !strcmp(args[0], "errorloc303")) { /* error location */
2444 int errnum, errlen;
2445 char *err;
2446
Willy Tarreau977b8e42006-12-29 14:19:17 +01002447 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2448 return 0;
2449
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002451 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 return -1;
2453 }
2454
2455 errnum = atol(args[1]);
2456 if (!strcmp(args[0], "errorloc303")) {
2457 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2458 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2459 } else {
2460 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2461 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2462 }
2463
Willy Tarreau0f772532006-12-23 20:51:41 +01002464 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2465 if (http_err_codes[rc] == errnum) {
2466 if (curproxy->errmsg[rc].str)
2467 free(curproxy->errmsg[rc].str);
2468 curproxy->errmsg[rc].str = err;
2469 curproxy->errmsg[rc].len = errlen;
2470 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002473
2474 if (rc >= HTTP_ERR_SIZE) {
2475 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2476 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 free(err);
2478 }
2479 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002480 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2481 int errnum, errlen, fd;
2482 char *err;
2483 struct stat stat;
2484
2485 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2486 return 0;
2487
2488 if (*(args[2]) == 0) {
2489 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2490 return -1;
2491 }
2492
2493 fd = open(args[2], O_RDONLY);
2494 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2495 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2496 file, linenum, args[2], args[1]);
2497 if (fd >= 0)
2498 close(fd);
2499 return -1;
2500 }
2501
2502 if (stat.st_size <= BUFSIZE) {
2503 errlen = stat.st_size;
2504 } else {
2505 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2506 file, linenum, args[2], BUFSIZE);
2507 errlen = BUFSIZE;
2508 }
2509
2510 err = malloc(errlen); /* malloc() must succeed during parsing */
2511 errnum = read(fd, err, errlen);
2512 if (errnum != errlen) {
2513 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2514 file, linenum, args[2], args[1]);
2515 close(fd);
2516 free(err);
2517 return -1;
2518 }
2519 close(fd);
2520
2521 errnum = atol(args[1]);
2522 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2523 if (http_err_codes[rc] == errnum) {
2524 if (curproxy->errmsg[rc].str)
2525 free(curproxy->errmsg[rc].str);
2526 curproxy->errmsg[rc].str = err;
2527 curproxy->errmsg[rc].len = errlen;
2528 break;
2529 }
2530 }
2531
2532 if (rc >= HTTP_ERR_SIZE) {
2533 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2534 file, linenum, errnum);
2535 free(err);
2536 }
2537 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002538 else {
Willy Tarreau6daf3432008-01-22 16:44:08 +01002539 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002540 return -1;
2541 }
2542 return 0;
2543}
2544
2545
2546/*
2547 * This function reads and parses the configuration file given in the argument.
2548 * returns 0 if OK, -1 if error.
2549 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002550int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002552 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 FILE *f;
2554 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 int confsect = CFG_NONE;
2557
2558 struct proxy *curproxy = NULL;
2559 struct server *newsrv = NULL;
2560
2561 if ((f=fopen(file,"r")) == NULL)
2562 return -1;
2563
2564 init_default_instance();
2565
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002566 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002567 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002568 char *end;
2569 char *args[MAX_LINE_ARGS + 1];
2570 char *line = thisline;
2571
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 linenum++;
2573
2574 end = line + strlen(line);
2575
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002576 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2577 /* Check if we reached the limit and the last char is not \n.
2578 * Watch out for the last line without the terminating '\n'!
2579 */
2580 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2581 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002582 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002583 }
2584
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002586 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 line++;
2588
2589 arg = 0;
2590 args[arg] = line;
2591
2592 while (*line && arg < MAX_LINE_ARGS) {
2593 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2594 * C equivalent value. Other combinations left unchanged (eg: \1).
2595 */
2596 if (*line == '\\') {
2597 int skip = 0;
2598 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2599 *line = line[1];
2600 skip = 1;
2601 }
2602 else if (line[1] == 'r') {
2603 *line = '\r';
2604 skip = 1;
2605 }
2606 else if (line[1] == 'n') {
2607 *line = '\n';
2608 skip = 1;
2609 }
2610 else if (line[1] == 't') {
2611 *line = '\t';
2612 skip = 1;
2613 }
2614 else if (line[1] == 'x') {
2615 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2616 unsigned char hex1, hex2;
2617 hex1 = toupper(line[2]) - '0';
2618 hex2 = toupper(line[3]) - '0';
2619 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2620 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2621 *line = (hex1<<4) + hex2;
2622 skip = 3;
2623 }
2624 else {
2625 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002626 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002627 }
2628 }
2629 if (skip) {
2630 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2631 end -= skip;
2632 }
2633 line++;
2634 }
2635 else if (*line == '#' || *line == '\n' || *line == '\r') {
2636 /* end of string, end of loop */
2637 *line = 0;
2638 break;
2639 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002640 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002641 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002642 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002643 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002644 line++;
2645 args[++arg] = line;
2646 }
2647 else {
2648 line++;
2649 }
2650 }
2651
2652 /* empty line */
2653 if (!**args)
2654 continue;
2655
Willy Tarreau540abe42007-05-02 20:50:16 +02002656 /* zero out remaining args and ensure that at least one entry
2657 * is zeroed out.
2658 */
2659 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002660 args[arg] = line;
2661 }
2662
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002663 if (!strcmp(args[0], "no")) {
2664 inv = 1;
2665 for (arg=0; *args[arg+1]; arg++)
2666 args[arg] = args[arg+1]; // shift args after inversion
2667 }
2668
2669 if (inv && strcmp(args[0], "option")) {
2670 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002671 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002672 }
2673
Willy Tarreau977b8e42006-12-29 14:19:17 +01002674 if (!strcmp(args[0], "listen") ||
2675 !strcmp(args[0], "frontend") ||
2676 !strcmp(args[0], "backend") ||
2677 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002678 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 confsect = CFG_LISTEN;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002680 if (cursection)
2681 free(cursection);
2682 cursection = strdup(args[0]);
2683 }
2684 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002685 confsect = CFG_GLOBAL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002686 if (cursection)
2687 free(cursection);
2688 cursection = strdup(args[0]);
2689 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002690 /* else it's a section keyword */
2691
2692 switch (confsect) {
2693 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002694 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002695 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696 break;
2697 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002698 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002699 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 break;
2701 default:
2702 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002703 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002704 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01002706 if (cursection)
2707 free(cursection);
2708 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002709 fclose(f);
2710
2711 /*
2712 * Now, check for the integrity of all that we have collected.
2713 */
2714
2715 /* will be needed further to delay some tasks */
2716 tv_now(&now);
2717
2718 if ((curproxy = proxy) == NULL) {
2719 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2720 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002721 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002722 }
2723
2724 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002725 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002726 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002727
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728 if (curproxy->state == PR_STSTOPPED) {
2729 curproxy = curproxy->next;
2730 continue;
2731 }
2732
Willy Tarreau977b8e42006-12-29 14:19:17 +01002733 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2734 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 +01002735 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002736 cfgerr++;
2737 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002738 else if (curproxy->cap & PR_CAP_BE &&
2739 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002740 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002741 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002742 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2743 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 +01002744 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002745 cfgerr++;
2746 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002747
Willy Tarreau31682232007-11-29 15:38:04 +01002748 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002749 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002750 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002751 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002752 cfgerr++;
2753 }
2754#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2755 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002756 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002757 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002758 cfgerr++;
2759 }
2760#endif
2761 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002762 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002763 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764 }
2765 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002766
2767 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002768 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002769 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002770 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002771 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002772 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002773 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002774 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 }
2776 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002777 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002778 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002780 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002781 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002782 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002783 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002784 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002785 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2786 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002787
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002788 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002789 file, proxy_type_str(curproxy), curproxy->id);
2790 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002791 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002792
2793 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2794 if ((newsrv = curproxy->srv) != NULL) {
2795 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2796 file, proxy_type_str(curproxy), curproxy->id);
2797 }
2798 }
2799
2800 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002801 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2802 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2803 file, curproxy->id);
2804 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002805 }
2806 }
2807
Willy Tarreau82936582007-11-30 15:20:09 +01002808 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2809 curproxy->options &= ~PR_O_DISABLE404;
2810 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2811 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2812 }
2813
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002814 /* if a default backend was specified, let's find it */
2815 if (curproxy->defbe.name) {
2816 struct proxy *target;
2817
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002818 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2819 if (!target) {
2820 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2821 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002822 cfgerr++;
2823 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002824 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2825 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002826 } else {
2827 free(curproxy->defbe.name);
2828 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002829 }
2830 }
2831
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002832 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002833 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2834 /* map jump target for ACT_SETBE in req_rep chain */
2835 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002836 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002837 struct proxy *target;
2838
Willy Tarreaua496b602006-12-17 23:15:24 +01002839 if (exp->action != ACT_SETBE)
2840 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002841
2842 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2843 if (!target) {
2844 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2845 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002846 cfgerr++;
2847 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002848 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2849 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002850 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002851 } else {
2852 free((void *)exp->replace);
2853 exp->replace = (const char *)target;
2854 }
2855 }
2856 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002857
2858 /* find the target proxy for 'use_backend' rules */
2859 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002860 struct proxy *target;
2861
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002862 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002863
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002864 if (!target) {
2865 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2866 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002867 cfgerr++;
2868 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002869 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2870 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002871 cfgerr++;
2872 } else {
2873 free((void *)rule->be.name);
2874 rule->be.backend = target;
2875 }
2876 }
2877
Willy Tarreau2738a142006-07-08 17:28:09 +02002878 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002879 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->timeout.client)) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02002880 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002881 (!tv_isset(&curproxy->timeout.connect) || !tv_isset(&curproxy->timeout.server))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002882 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002883 " | While not properly invalid, you will certainly encounter various problems\n"
2884 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01002885 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002886 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002887 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002888
Willy Tarreau1fa31262007-12-03 00:36:16 +01002889 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
2890 * We must still support older configurations, so let's find out whether those
2891 * parameters have been set or must be copied from contimeouts.
2892 */
2893 if (curproxy != &defproxy) {
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002894 if (!tv_isset(&curproxy->timeout.tarpit) ||
2895 __tv_iseq(&curproxy->timeout.tarpit, &defproxy.timeout.tarpit)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01002896 /* tarpit timeout not set. We search in the following order:
2897 * default.tarpit, curr.connect, default.connect.
2898 */
2899 if (tv_isset(&defproxy.timeout.tarpit))
2900 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002901 else if (tv_isset(&curproxy->timeout.connect))
2902 curproxy->timeout.tarpit = curproxy->timeout.connect;
2903 else if (tv_isset(&defproxy.timeout.connect))
2904 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002905 }
2906 if ((curproxy->cap & PR_CAP_BE) &&
2907 (!tv_isset(&curproxy->timeout.queue) ||
2908 __tv_iseq(&curproxy->timeout.queue, &defproxy.timeout.queue))) {
2909 /* queue timeout not set. We search in the following order:
2910 * default.queue, curr.connect, default.connect.
2911 */
2912 if (tv_isset(&defproxy.timeout.queue))
2913 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002914 else if (tv_isset(&curproxy->timeout.connect))
2915 curproxy->timeout.queue = curproxy->timeout.connect;
2916 else if (tv_isset(&defproxy.timeout.connect))
2917 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002918 }
2919 }
2920
Willy Tarreauf3c69202006-07-09 16:42:34 +02002921 if (curproxy->options & PR_O_SSL3_CHK) {
2922 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2923 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2924 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2925 }
2926
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002927 /* The small pools required for the capture lists */
2928 if (curproxy->nb_req_cap)
2929 curproxy->req_cap_pool = create_pool("ptrcap",
2930 curproxy->nb_req_cap * sizeof(char *),
2931 MEM_F_SHARED);
2932 if (curproxy->nb_rsp_cap)
2933 curproxy->rsp_cap_pool = create_pool("ptrcap",
2934 curproxy->nb_rsp_cap * sizeof(char *),
2935 MEM_F_SHARED);
2936
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002937 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2938 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2939 MEM_F_SHARED);
2940
Willy Tarreau86034312006-12-29 00:10:33 +01002941 /* for backwards compatibility with "listen" instances, if
2942 * fullconn is not set but maxconn is set, then maxconn
2943 * is used.
2944 */
2945 if (!curproxy->fullconn)
2946 curproxy->fullconn = curproxy->maxconn;
2947
Willy Tarreaubaaee002006-06-26 02:48:02 +02002948 /* first, we will invert the servers list order */
2949 newsrv = NULL;
2950 while (curproxy->srv) {
2951 struct server *next;
2952
2953 next = curproxy->srv->next;
2954 curproxy->srv->next = newsrv;
2955 newsrv = curproxy->srv;
2956 if (!next)
2957 break;
2958 curproxy->srv = next;
2959 }
2960
Willy Tarreau20697042007-11-15 23:26:18 +01002961 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01002962 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002963
Willy Tarreaub625a082007-11-26 01:15:43 +01002964 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01002965 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01002966 fwrr_init_server_groups(curproxy);
2967 else
2968 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969
2970 if (curproxy->options & PR_O_LOGASAP)
2971 curproxy->to_log &= ~LW_BYTES;
2972
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01002974 * ensure that we're not cross-dressing a TCP server into HTTP.
2975 */
2976 newsrv = curproxy->srv;
2977 while (newsrv != NULL) {
2978 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
2979 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
2980 file, proxy_type_str(curproxy), curproxy->id, linenum);
2981 goto err;
2982 }
2983 newsrv = newsrv->next;
2984 }
2985
2986 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02002987 * If this server supports a maxconn parameter, it needs a dedicated
2988 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002989 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002990 */
2991 newsrv = curproxy->srv;
2992 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002993 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994 /* Only 'minconn' was specified, or it was higher than or equal
2995 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2996 * this will avoid further useless expensive computations.
2997 */
2998 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002999 } else if (newsrv->maxconn && !newsrv->minconn) {
3000 /* minconn was not specified, so we set it to maxconn */
3001 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003002 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3003 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003004 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003005 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003006 }
3007
3008 if (newsrv->maxconn > 0) {
3009 struct task *t;
3010
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02003011 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003012 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003013 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 }
3015
Willy Tarreau96bcfd72007-04-29 10:41:56 +02003016 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01003017 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018 t->state = TASK_IDLE;
3019 t->process = process_srv_queue;
3020 t->context = newsrv;
3021 newsrv->queue_mgt = t;
3022
3023 /* never run it unless specifically woken up */
3024 tv_eternity(&t->expire);
3025 task_queue(t);
3026 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003027
3028 if (newsrv->trackit) {
3029 struct proxy *px;
3030 struct server *srv;
3031 char *pname, *sname;
3032
3033 pname = newsrv->trackit;
3034 sname = strrchr(pname, '/');
3035
3036 if (sname)
3037 *sname++ = '\0';
3038 else {
3039 sname = pname;
3040 pname = NULL;
3041 }
3042
3043 if (pname) {
3044 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3045 if (!px) {
3046 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3047 file, proxy_type_str(curproxy), curproxy->id,
3048 newsrv->id, pname);
3049 return -1;
3050 }
3051 } else
3052 px = curproxy;
3053
3054 srv = findserver(px, sname);
3055 if (!srv) {
3056 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3057 file, proxy_type_str(curproxy), curproxy->id,
3058 newsrv->id, sname);
3059 return -1;
3060 }
3061
3062 if (!(srv->state & SRV_CHECKED)) {
3063 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3064 "tracing as it does not have checks enabled.\n",
3065 file, proxy_type_str(curproxy), curproxy->id,
3066 newsrv->id, px->id, srv->id);
3067 return -1;
3068 }
3069
3070 if (curproxy != px &&
3071 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3072 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3073 "tracing: disable-on-404 option inconsistency.\n",
3074 file, proxy_type_str(curproxy), curproxy->id,
3075 newsrv->id, px->id, srv->id);
3076 return -1;
3077 }
3078
3079 newsrv->tracked = srv;
3080 newsrv->tracknext = srv->tracknext;
3081 srv->tracknext = newsrv;
3082
3083 free(newsrv->trackit);
3084 }
3085
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 newsrv = newsrv->next;
3087 }
3088
Willy Tarreaue6b98942007-10-29 01:09:36 +01003089 /* adjust this proxy's listeners */
3090 listener = curproxy->listen;
3091 while (listener) {
3092 if (curproxy->options & PR_O_TCP_NOLING)
3093 listener->options |= LI_O_NOLINGER;
3094 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003095 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003096 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003097 listener->accept = event_accept;
3098 listener->private = curproxy;
3099
3100 listener = listener->next;
3101 }
3102
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 curproxy = curproxy->next;
3104 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003105
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106 if (cfgerr > 0) {
3107 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003108 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003110
3111 /*
3112 * Recount currently required checks.
3113 */
3114
3115 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3116 int optnum;
3117
3118 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3119 if (!(curproxy->options & cfg_opts[optnum].val))
3120 continue;
3121
3122 global.last_checks |= cfg_opts[optnum].checks;
3123 }
3124 }
3125
Willy Tarreau6daf3432008-01-22 16:44:08 +01003126 if (cursection)
3127 free(cursection);
3128 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003129 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003130
3131 err:
3132 if (cursection)
3133 free(cursection);
3134 cursection = NULL;
3135 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136}
3137
3138
3139
3140/*
3141 * Local variables:
3142 * c-indent-level: 8
3143 * c-basic-offset: 8
3144 * End:
3145 */