blob: e361356bdffa5d85f92acf3f4b56dab879c4f29c [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 Tarreau0f772532006-12-23 20:51:41 +010044#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/log.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010046#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <proto/server.h>
48#include <proto/task.h>
49
50
Willy Tarreauf3c69202006-07-09 16:42:34 +020051/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
52 * ssl-hello-chk option to ensure that the remote server speaks SSL.
53 *
54 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
55 */
56const char sslv3_client_hello_pkt[] = {
57 "\x16" /* ContentType : 0x16 = Hanshake */
58 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
59 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
60 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
61 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
62 "\x03\x00" /* Hello Version : 0x0300 = v3 */
63 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
64 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
65 "\x00" /* Session ID length : empty (no session ID) */
66 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
67 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
68 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
69 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
70 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
71 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
72 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
73 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
74 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
75 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
76 "\x00\x38" "\x00\x39" "\x00\x3A"
77 "\x01" /* Compression Length : 0x01 = 1 byte for types */
78 "\x00" /* Compression Type : 0x00 = NULL compression */
79};
80
Willy Tarreau13943ab2006-12-31 00:24:10 +010081/* some of the most common options which are also the easiest to handle */
82static const struct {
83 const char *name;
84 unsigned int val;
85 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010086 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010087} cfg_opts[] =
88{
89#ifdef TPROXY
90 { "transparent", PR_O_TRANSP, PR_CAP_FE },
91#endif
Willy Tarreau4fee4e92007-01-06 21:09:17 +010092 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
93 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010094 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
95 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
96 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
97 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
98 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
99 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
100 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
101 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
102 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
103 { "forceclose", PR_O_FORCE_CLO | PR_O_HTTP_CLOSE, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100104#ifdef CONFIG_HAP_TCPSPLICE
105 { "tcpsplice", PR_O_TCPSPLICE , PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
106#endif
107
Willy Tarreau13943ab2006-12-31 00:24:10 +0100108 { NULL, 0, 0 }
109};
110
Willy Tarreaubaaee002006-06-26 02:48:02 +0200111
112static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
113int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
114int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
115
116/*
117 * converts <str> to a list of listeners which are dynamically allocated.
118 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
119 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
120 * - <port> is a numerical port from 1 to 65535 ;
121 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
122 * This can be repeated as many times as necessary, separated by a coma.
123 * The <tail> argument is a pointer to a current list which should be appended
124 * to the tail of the new list. The pointer to the new list is returned.
125 */
126static struct listener *str2listener(char *str, struct listener *tail)
127{
128 struct listener *l;
129 char *c, *next, *range, *dupstr;
130 int port, end;
131
132 next = dupstr = strdup(str);
133
134 while (next && *next) {
135 struct sockaddr_storage ss;
136
137 str = next;
138 /* 1) look for the end of the first address */
139 if ((next = strrchr(str, ',')) != NULL) {
140 *next++ = 0;
141 }
142
143 /* 2) look for the addr/port delimiter, it's the last colon. */
144 if ((range = strrchr(str, ':')) == NULL) {
145 Alert("Missing port number: '%s'\n", str);
146 goto fail;
147 }
148
149 *range++ = 0;
150
151 if (strrchr(str, ':') != NULL) {
152 /* IPv6 address contains ':' */
153 memset(&ss, 0, sizeof(ss));
154 ss.ss_family = AF_INET6;
155
156 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
157 Alert("Invalid server address: '%s'\n", str);
158 goto fail;
159 }
160 }
161 else {
162 memset(&ss, 0, sizeof(ss));
163 ss.ss_family = AF_INET;
164
165 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
166 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
167 }
168 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
169 struct hostent *he;
170
171 if ((he = gethostbyname(str)) == NULL) {
172 Alert("Invalid server name: '%s'\n", str);
173 goto fail;
174 }
175 else
176 ((struct sockaddr_in *)&ss)->sin_addr =
177 *(struct in_addr *) *(he->h_addr_list);
178 }
179 }
180
181 /* 3) look for the port-end delimiter */
182 if ((c = strchr(range, '-')) != NULL) {
183 *c++ = 0;
184 end = atol(c);
185 }
186 else {
187 end = atol(range);
188 }
189
190 port = atol(range);
191
192 if (port < 1 || port > 65535) {
193 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
194 goto fail;
195 }
196
197 if (end < 1 || end > 65535) {
198 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
199 goto fail;
200 }
201
202 for (; port <= end; port++) {
203 l = (struct listener *)calloc(1, sizeof(struct listener));
204 l->next = tail;
205 tail = l;
206
207 l->fd = -1;
208 l->addr = ss;
209 if (ss.ss_family == AF_INET6)
210 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
211 else
212 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
213
214 } /* end for(port) */
215 } /* end while(next) */
216 free(dupstr);
217 return tail;
218 fail:
219 free(dupstr);
220 return NULL;
221}
222
Willy Tarreau977b8e42006-12-29 14:19:17 +0100223/*
224 * Sends a warning if proxy <proxy> does not have at least one of the
225 * capabilities in <cap>. An optionnal <hint> may be added at the end
226 * of the warning to help the user. Returns 1 if a warning was emitted
227 * or 0 if the condition is valid.
228 */
229int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
230{
231 char *msg;
232
233 switch (cap) {
234 case PR_CAP_BE: msg = "no backend"; break;
235 case PR_CAP_FE: msg = "no frontend"; break;
236 case PR_CAP_RS: msg = "no ruleset"; break;
237 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
238 default: msg = "not enough"; break;
239 }
240
241 if (!(proxy->cap & cap)) {
242 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100243 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100244 return 1;
245 }
246 return 0;
247}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200248
249/*
250 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
251 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200252int cfg_parse_global(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200253{
254
255 if (!strcmp(args[0], "global")) { /* new section */
256 /* no option, nothing special to do */
257 return 0;
258 }
259 else if (!strcmp(args[0], "daemon")) {
260 global.mode |= MODE_DAEMON;
261 }
262 else if (!strcmp(args[0], "debug")) {
263 global.mode |= MODE_DEBUG;
264 }
265 else if (!strcmp(args[0], "noepoll")) {
266 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
267 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200268 else if (!strcmp(args[0], "nosepoll")) {
269 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
270 }
271 else if (!strcmp(args[0], "nokqueue")) {
272 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274 else if (!strcmp(args[0], "nopoll")) {
275 cfg_polling_mechanism &= ~POLL_USE_POLL;
276 }
277 else if (!strcmp(args[0], "quiet")) {
278 global.mode |= MODE_QUIET;
279 }
280 else if (!strcmp(args[0], "stats")) {
281 global.mode |= MODE_STATS;
282 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200283 else if (!strcmp(args[0], "tune.maxpollevents")) {
284 if (global.tune.maxpollevents != 0) {
285 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
286 return 0;
287 }
288 if (*(args[1]) == 0) {
289 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
290 return -1;
291 }
292 global.tune.maxpollevents = atol(args[1]);
293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 else if (!strcmp(args[0], "uid")) {
295 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200296 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 return 0;
298 }
299 if (*(args[1]) == 0) {
300 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
301 return -1;
302 }
303 global.uid = atol(args[1]);
304 }
305 else if (!strcmp(args[0], "gid")) {
306 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200307 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308 return 0;
309 }
310 if (*(args[1]) == 0) {
311 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
312 return -1;
313 }
314 global.gid = atol(args[1]);
315 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200316 /* user/group name handling */
317 else if (!strcmp(args[0], "user")) {
318 struct passwd *ha_user;
319 if (global.uid != 0) {
320 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
321 return 0;
322 }
323 errno = 0;
324 ha_user = getpwnam(args[1]);
325 if (ha_user != NULL) {
326 global.uid = (int)ha_user->pw_uid;
327 }
328 else {
329 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
330 exit(1);
331 }
332 }
333 else if (!strcmp(args[0], "group")) {
334 struct group *ha_group;
335 if (global.gid != 0) {
336 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
337 return 0;
338 }
339 errno = 0;
340 ha_group = getgrnam(args[1]);
341 if (ha_group != NULL) {
342 global.gid = (int)ha_group->gr_gid;
343 }
344 else {
345 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
346 exit(1);
347 }
348 }
349 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200350 else if (!strcmp(args[0], "nbproc")) {
351 if (global.nbproc != 0) {
352 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
353 return 0;
354 }
355 if (*(args[1]) == 0) {
356 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
357 return -1;
358 }
359 global.nbproc = atol(args[1]);
360 }
361 else if (!strcmp(args[0], "maxconn")) {
362 if (global.maxconn != 0) {
363 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
364 return 0;
365 }
366 if (*(args[1]) == 0) {
367 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
368 return -1;
369 }
370 global.maxconn = atol(args[1]);
371#ifdef SYSTEM_MAXCONN
372 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
373 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);
374 global.maxconn = DEFAULT_MAXCONN;
375 }
376#endif /* SYSTEM_MAXCONN */
377 }
378 else if (!strcmp(args[0], "ulimit-n")) {
379 if (global.rlimit_nofile != 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.rlimit_nofile = atol(args[1]);
388 }
389 else if (!strcmp(args[0], "chroot")) {
390 if (global.chroot != NULL) {
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 a directory as an argument.\n", file, linenum, args[0]);
396 return -1;
397 }
398 global.chroot = strdup(args[1]);
399 }
400 else if (!strcmp(args[0], "pidfile")) {
401 if (global.pidfile != NULL) {
402 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
403 return 0;
404 }
405 if (*(args[1]) == 0) {
406 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
407 return -1;
408 }
409 global.pidfile = strdup(args[1]);
410 }
411 else if (!strcmp(args[0], "log")) { /* syslog server address */
412 struct sockaddr_in *sa;
413 int facility, level;
414
415 if (*(args[1]) == 0 || *(args[2]) == 0) {
416 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
417 return -1;
418 }
419
420 facility = get_log_facility(args[2]);
421 if (facility < 0) {
422 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
423 exit(1);
424 }
425
426 level = 7; /* max syslog level = debug */
427 if (*(args[3])) {
428 level = get_log_level(args[3]);
429 if (level < 0) {
430 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
431 exit(1);
432 }
433 }
434
435 sa = str2sa(args[1]);
436 if (!sa->sin_port)
437 sa->sin_port = htons(SYSLOG_PORT);
438
439 if (global.logfac1 == -1) {
440 global.logsrv1 = *sa;
441 global.logfac1 = facility;
442 global.loglev1 = level;
443 }
444 else if (global.logfac2 == -1) {
445 global.logsrv2 = *sa;
446 global.logfac2 = facility;
447 global.loglev2 = level;
448 }
449 else {
450 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
451 return -1;
452 }
453
454 }
455 else {
456 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
457 return -1;
458 }
459 return 0;
460}
461
462
463static void init_default_instance()
464{
465 memset(&defproxy, 0, sizeof(defproxy));
466 defproxy.mode = PR_MODE_TCP;
467 defproxy.state = PR_STNEW;
468 defproxy.maxconn = cfg_maxpconn;
469 defproxy.conn_retries = CONN_RETRIES;
470 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaufdd0f552007-09-17 11:12:40 +0200471 tv_eternity(&defproxy.clitimeout);
472 tv_eternity(&defproxy.contimeout);
473 tv_eternity(&defproxy.srvtimeout);
474 tv_eternity(&defproxy.appsession_timeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475}
476
477/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100478 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
479 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200480 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200481int cfg_parse_listen(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200482{
483 static struct proxy *curproxy = NULL;
484 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200485 const char *err;
Willy Tarreauee991362007-05-14 14:37:50 +0200486 int rc, val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200487
Willy Tarreau977b8e42006-12-29 14:19:17 +0100488 if (!strcmp(args[0], "listen"))
489 rc = PR_CAP_LISTEN;
490 else if (!strcmp(args[0], "frontend"))
491 rc = PR_CAP_FE | PR_CAP_RS;
492 else if (!strcmp(args[0], "backend"))
493 rc = PR_CAP_BE | PR_CAP_RS;
494 else if (!strcmp(args[0], "ruleset"))
495 rc = PR_CAP_RS;
496 else
497 rc = PR_CAP_NONE;
498
499 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200500 if (!*args[1]) {
501 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
502 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
503 file, linenum, args[0]);
504 return -1;
505 }
506
507 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
508 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
509 return -1;
510 }
511
512 curproxy->next = proxy;
513 proxy = curproxy;
514 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200515 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200516 LIST_INIT(&curproxy->block_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200517 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518
Willy Tarreauee991362007-05-14 14:37:50 +0200519 /* Timeouts are defined as -1, so we cannot use the zeroed area
520 * as a default value.
521 */
522 tv_eternity(&curproxy->clitimeout);
523 tv_eternity(&curproxy->srvtimeout);
524 tv_eternity(&curproxy->contimeout);
525 tv_eternity(&curproxy->appsession_timeout);
526
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100528 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200529
530 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100531 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200532 curproxy->listen = str2listener(args[2], curproxy->listen);
533 if (!curproxy->listen)
534 return -1;
535 global.maxsock++;
536 }
537
538 /* set default values */
539 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200540 curproxy->options = defproxy.options;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200541 curproxy->except_net = defproxy.except_net;
542 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200543
Willy Tarreau977b8e42006-12-29 14:19:17 +0100544 if (curproxy->cap & PR_CAP_FE) {
545 curproxy->maxconn = defproxy.maxconn;
546
547 /* initialize error relocations */
548 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
549 if (defproxy.errmsg[rc].str)
550 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
551 }
552
553 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
554 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200555
Willy Tarreau977b8e42006-12-29 14:19:17 +0100556 if (curproxy->cap & PR_CAP_BE) {
557 curproxy->fullconn = defproxy.fullconn;
558 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200559
Willy Tarreau977b8e42006-12-29 14:19:17 +0100560 if (defproxy.check_req)
561 curproxy->check_req = strdup(defproxy.check_req);
562 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200563
Willy Tarreau977b8e42006-12-29 14:19:17 +0100564 if (defproxy.cookie_name)
565 curproxy->cookie_name = strdup(defproxy.cookie_name);
566 curproxy->cookie_len = defproxy.cookie_len;
567 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200568
Willy Tarreau977b8e42006-12-29 14:19:17 +0100569 if (curproxy->cap & PR_CAP_RS) {
570 if (defproxy.capture_name)
571 curproxy->capture_name = strdup(defproxy.capture_name);
572 curproxy->capture_namelen = defproxy.capture_namelen;
573 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100574 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575
Willy Tarreau977b8e42006-12-29 14:19:17 +0100576 if (curproxy->cap & PR_CAP_FE) {
577 curproxy->clitimeout = defproxy.clitimeout;
578 curproxy->uri_auth = defproxy.uri_auth;
579 curproxy->mon_net = defproxy.mon_net;
580 curproxy->mon_mask = defproxy.mon_mask;
581 if (defproxy.monitor_uri)
582 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
583 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100584 if (defproxy.defbe.name)
585 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100586 }
587
588 if (curproxy->cap & PR_CAP_BE) {
589 curproxy->contimeout = defproxy.contimeout;
590 curproxy->srvtimeout = defproxy.srvtimeout;
591 curproxy->source_addr = defproxy.source_addr;
592 }
593
Willy Tarreaubaaee002006-06-26 02:48:02 +0200594 curproxy->mode = defproxy.mode;
595 curproxy->logfac1 = defproxy.logfac1;
596 curproxy->logsrv1 = defproxy.logsrv1;
597 curproxy->loglev1 = defproxy.loglev1;
598 curproxy->logfac2 = defproxy.logfac2;
599 curproxy->logsrv2 = defproxy.logsrv2;
600 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 curproxy->grace = defproxy.grace;
Willy Tarreau1c47f852006-07-09 08:22:27 +0200602
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603 return 0;
604 }
605 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
606 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100607 /* FIXME-20070101: we should do this too at the end of the
608 * config parsing to free all default values.
609 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610 if (defproxy.check_req) free(defproxy.check_req);
611 if (defproxy.cookie_name) free(defproxy.cookie_name);
612 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200613 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100614 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100615
616 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
617 if (defproxy.errmsg[rc].len)
618 free(defproxy.errmsg[rc].str);
619 }
620
Willy Tarreaubaaee002006-06-26 02:48:02 +0200621 /* we cannot free uri_auth because it might already be used */
622 init_default_instance();
623 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100624 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200625 return 0;
626 }
627 else if (curproxy == NULL) {
628 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
629 return -1;
630 }
631
Willy Tarreau977b8e42006-12-29 14:19:17 +0100632
633 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 if (!strcmp(args[0], "bind")) { /* new listen addresses */
635 if (curproxy == &defproxy) {
636 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
637 return -1;
638 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100639 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
640 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641
642 if (strchr(args[1], ':') == NULL) {
643 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
644 file, linenum, args[0]);
645 return -1;
646 }
647 curproxy->listen = str2listener(args[1], curproxy->listen);
648 if (!curproxy->listen)
649 return -1;
650 global.maxsock++;
651 return 0;
652 }
653 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
654 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
655 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
656 file, linenum, args[0]);
657 return -1;
658 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100659 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
660 return 0;
661
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 /* flush useless bits */
663 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
664 return 0;
665 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200666 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100667 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
668 return 0;
669
Willy Tarreau1c47f852006-07-09 08:22:27 +0200670 if (!*args[1]) {
671 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
672 file, linenum, args[0]);
673 return -1;
674 }
675
676 if (curproxy->monitor_uri != NULL)
677 free(curproxy->monitor_uri);
678
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100679 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200680 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100681 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200682 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
683
684 return 0;
685 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200686 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
687 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
688 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
689 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
690 else {
691 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
692 return -1;
693 }
694 }
695 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
696 curproxy->state = PR_STSTOPPED;
697 }
698 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
699 curproxy->state = PR_STNEW;
700 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200701 else if (!strcmp(args[0], "acl")) { /* add an ACL */
702 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
703 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
704 file, linenum, args[1]);
705 return -1;
706 }
707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200708 else if (!strcmp(args[0], "cookie")) { /* cookie name */
709 int cur_arg;
710 // if (curproxy == &defproxy) {
711 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
712 // return -1;
713 // }
714
Willy Tarreau977b8e42006-12-29 14:19:17 +0100715 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
716 return 0;
717
Willy Tarreaubaaee002006-06-26 02:48:02 +0200718 if (curproxy->cookie_name != NULL) {
719 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
720 // file, linenum);
721 // return 0;
722 free(curproxy->cookie_name);
723 }
724
725 if (*(args[1]) == 0) {
726 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
727 file, linenum, args[0]);
728 return -1;
729 }
730 curproxy->cookie_name = strdup(args[1]);
731 curproxy->cookie_len = strlen(curproxy->cookie_name);
732
733 cur_arg = 2;
734 while (*(args[cur_arg])) {
735 if (!strcmp(args[cur_arg], "rewrite")) {
736 curproxy->options |= PR_O_COOK_RW;
737 }
738 else if (!strcmp(args[cur_arg], "indirect")) {
739 curproxy->options |= PR_O_COOK_IND;
740 }
741 else if (!strcmp(args[cur_arg], "insert")) {
742 curproxy->options |= PR_O_COOK_INS;
743 }
744 else if (!strcmp(args[cur_arg], "nocache")) {
745 curproxy->options |= PR_O_COOK_NOC;
746 }
747 else if (!strcmp(args[cur_arg], "postonly")) {
748 curproxy->options |= PR_O_COOK_POST;
749 }
750 else if (!strcmp(args[cur_arg], "prefix")) {
751 curproxy->options |= PR_O_COOK_PFX;
752 }
753 else {
754 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
755 file, linenum, args[0]);
756 return -1;
757 }
758 cur_arg++;
759 }
760 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
761 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
762 file, linenum);
763 return -1;
764 }
765
766 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
767 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
768 file, linenum);
769 return -1;
770 }
771 }/* end else if (!strcmp(args[0], "cookie")) */
772 else if (!strcmp(args[0], "appsession")) { /* cookie name */
773 // if (curproxy == &defproxy) {
774 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
775 // return -1;
776 // }
777
Willy Tarreau977b8e42006-12-29 14:19:17 +0100778 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
779 return 0;
780
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 if (curproxy->appsession_name != NULL) {
782 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
783 // file, linenum);
784 // return 0;
785 free(curproxy->appsession_name);
786 }
787
788 if (*(args[5]) == 0) {
789 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
790 file, linenum, args[0]);
791 return -1;
792 }
793 have_appsession = 1;
794 curproxy->appsession_name = strdup(args[1]);
795 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
796 curproxy->appsession_len = atoi(args[3]);
Willy Tarreauee991362007-05-14 14:37:50 +0200797 val = atoi(args[5]);
798 if (val > 0)
799 __tv_from_ms(&curproxy->appsession_timeout, val);
800 else
801 tv_eternity(&curproxy->appsession_timeout);
802
Willy Tarreau51041c72007-09-09 21:56:53 +0200803 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
804 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200805 return -1;
806 }
807 } /* Url App Session */
808 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100809 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
810 return 0;
811
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
813 // if (curproxy == &defproxy) {
814 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
815 // return -1;
816 // }
817
818 if (curproxy->capture_name != NULL) {
819 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
820 // file, linenum, args[0]);
821 // return 0;
822 free(curproxy->capture_name);
823 }
824
825 if (*(args[4]) == 0) {
826 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
827 file, linenum, args[0]);
828 return -1;
829 }
830 curproxy->capture_name = strdup(args[2]);
831 curproxy->capture_namelen = strlen(curproxy->capture_name);
832 curproxy->capture_len = atol(args[4]);
833 if (curproxy->capture_len >= CAPTURE_LEN) {
834 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
835 file, linenum, CAPTURE_LEN - 1);
836 curproxy->capture_len = CAPTURE_LEN - 1;
837 }
838 curproxy->to_log |= LW_COOKIE;
839 }
840 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
841 struct cap_hdr *hdr;
842
843 if (curproxy == &defproxy) {
844 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
845 return -1;
846 }
847
848 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
849 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
850 file, linenum, args[0], args[1]);
851 return -1;
852 }
853
854 hdr = calloc(sizeof(struct cap_hdr), 1);
855 hdr->next = curproxy->req_cap;
856 hdr->name = strdup(args[3]);
857 hdr->namelen = strlen(args[3]);
858 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200859 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200860 hdr->index = curproxy->nb_req_cap++;
861 curproxy->req_cap = hdr;
862 curproxy->to_log |= LW_REQHDR;
863 }
864 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
865 struct cap_hdr *hdr;
866
867 if (curproxy == &defproxy) {
868 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
869 return -1;
870 }
871
872 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
873 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
874 file, linenum, args[0], args[1]);
875 return -1;
876 }
877 hdr = calloc(sizeof(struct cap_hdr), 1);
878 hdr->next = curproxy->rsp_cap;
879 hdr->name = strdup(args[3]);
880 hdr->namelen = strlen(args[3]);
881 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200882 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200883 hdr->index = curproxy->nb_rsp_cap++;
884 curproxy->rsp_cap = hdr;
885 curproxy->to_log |= LW_RSPHDR;
886 }
887 else {
888 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
889 file, linenum, args[0]);
890 return -1;
891 }
892 }
893 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200894 if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
896 return 0;
897 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100898 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
899 return 0;
900
Willy Tarreaubaaee002006-06-26 02:48:02 +0200901 if (*(args[1]) == 0) {
902 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
903 file, linenum, args[0]);
904 return -1;
905 }
Willy Tarreauee991362007-05-14 14:37:50 +0200906 val = atoi(args[1]);
907 if (val > 0)
908 __tv_from_ms(&curproxy->contimeout, val);
909 else
910 tv_eternity(&curproxy->contimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200911 }
912 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200913 if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
915 file, linenum, args[0]);
916 return 0;
917 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100918 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
919 return 0;
920
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921 if (*(args[1]) == 0) {
922 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
923 file, linenum, args[0]);
924 return -1;
925 }
Willy Tarreauee991362007-05-14 14:37:50 +0200926 val = atoi(args[1]);
927 if (val > 0)
928 __tv_from_ms(&curproxy->clitimeout, val);
929 else
930 tv_eternity(&curproxy->clitimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 }
932 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200933 if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
935 return 0;
936 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100937 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
938 return 0;
939
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940 if (*(args[1]) == 0) {
941 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
942 file, linenum, args[0]);
943 return -1;
944 }
Willy Tarreauee991362007-05-14 14:37:50 +0200945 val = atoi(args[1]);
946 if (val > 0)
947 __tv_from_ms(&curproxy->srvtimeout, val);
948 else
949 tv_eternity(&curproxy->srvtimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950 }
951 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100952 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
953 return 0;
954
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 if (*(args[1]) == 0) {
956 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
957 file, linenum, args[0]);
958 return -1;
959 }
960 curproxy->conn_retries = atol(args[1]);
961 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200962 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
963 int pol = ACL_COND_NONE;
964 struct acl_cond *cond;
965
966 if (!strcmp(args[1], "if"))
967 pol = ACL_COND_IF;
968 else if (!strcmp(args[1], "unless"))
969 pol = ACL_COND_UNLESS;
970
971 if (pol == ACL_COND_NONE) {
972 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
973 file, linenum, args[0]);
974 return -1;
975 }
976
977 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
978 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
979 file, linenum);
980 return -1;
981 }
982 LIST_ADDQ(&curproxy->block_cond, &cond->list);
983 }
Willy Tarreau55ea7572007-06-17 19:56:27 +0200984 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
985 int pol = ACL_COND_NONE;
986 struct acl_cond *cond;
987 struct switching_rule *rule;
988
989 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
990 return 0;
991
992 if (*(args[1]) == 0) {
993 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
994 return -1;
995 }
996
997 if (!strcmp(args[2], "if"))
998 pol = ACL_COND_IF;
999 else if (!strcmp(args[2], "unless"))
1000 pol = ACL_COND_UNLESS;
1001
1002 if (pol == ACL_COND_NONE) {
1003 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1004 file, linenum, args[0]);
1005 return -1;
1006 }
1007
1008 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1009 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1010 file, linenum);
1011 return -1;
1012 }
1013
1014 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1015 rule->cond = cond;
1016 rule->be.name = strdup(args[1]);
1017 LIST_INIT(&rule->list);
1018 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001021 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1022 return 0;
1023
Willy Tarreaubaaee002006-06-26 02:48:02 +02001024 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1025 curproxy->uri_auth = NULL; /* we must detach from the default config */
1026
1027 if (*(args[1]) == 0) {
1028 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1029 return -1;
1030 } else if (!strcmp(args[1], "uri")) {
1031 if (*(args[2]) == 0) {
1032 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1033 return -1;
1034 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1035 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1036 return -1;
1037 }
1038 } else if (!strcmp(args[1], "realm")) {
1039 if (*(args[2]) == 0) {
1040 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1041 return -1;
1042 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1043 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1044 return -1;
1045 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001046 } else if (!strcmp(args[1], "refresh")) {
1047 int interval = atoi(args[2]);
1048
1049 if (interval < 0) {
1050 Alert("parsing [%s:%d] : 'refresh' needs a positive interval in seconds.\n", file, linenum);
1051 return -1;
1052 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1053 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1054 return -1;
1055 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 } else if (!strcmp(args[1], "auth")) {
1057 if (*(args[2]) == 0) {
1058 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1059 return -1;
1060 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1061 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1062 return -1;
1063 }
1064 } else if (!strcmp(args[1], "scope")) {
1065 if (*(args[2]) == 0) {
1066 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1067 return -1;
1068 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1069 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1070 return -1;
1071 }
1072 } else if (!strcmp(args[1], "enable")) {
1073 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1074 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1075 return -1;
1076 }
1077 } else {
1078 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'uri', 'realm', 'auth' or 'enable').\n",
1079 file, linenum, args[0]);
1080 return -1;
1081 }
1082 }
1083 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001084 int optnum;
1085
Willy Tarreaubaaee002006-06-26 02:48:02 +02001086 if (*(args[1]) == 0) {
1087 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
1088 return -1;
1089 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001090
1091 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1092 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1093 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1094 return 0;
1095 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001096 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001097 return 0;
1098 }
1099 }
1100
1101 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 /* generate a complete HTTP log */
1103 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1104 else if (!strcmp(args[1], "tcplog"))
1105 /* generate a detailed TCP log */
1106 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 else if (!strcmp(args[1], "tcpka")) {
1108 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001109 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1110 return 0;
1111
1112 if (curproxy->cap & PR_CAP_FE)
1113 curproxy->options |= PR_O_TCP_CLI_KA;
1114 if (curproxy->cap & PR_CAP_BE)
1115 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 }
1117 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001118 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1119 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 /* use HTTP request to check servers' health */
1121 if (curproxy->check_req != NULL) {
1122 free(curproxy->check_req);
1123 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001124 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001125 curproxy->options &= ~PR_O_SMTP_CHK;
1126 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 if (!*args[2]) { /* no argument */
1128 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1129 curproxy->check_len = strlen(DEF_CHECK_REQ);
1130 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001131 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132 curproxy->check_req = (char *)malloc(reqlen);
1133 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1134 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1135 } else { /* more arguments : METHOD URI [HTTP_VER] */
1136 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1137 if (*args[4])
1138 reqlen += strlen(args[4]);
1139 else
1140 reqlen += strlen("HTTP/1.0");
1141
1142 curproxy->check_req = (char *)malloc(reqlen);
1143 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1144 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1145 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001146 }
1147 else if (!strcmp(args[1], "ssl-hello-chk")) {
1148 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001149 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1150 return 0;
1151
Willy Tarreauf3c69202006-07-09 16:42:34 +02001152 if (curproxy->check_req != NULL) {
1153 free(curproxy->check_req);
1154 }
1155 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001156 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001157 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158 }
Willy Tarreau23677902007-05-08 23:50:35 +02001159 else if (!strcmp(args[1], "smtpchk")) {
1160 /* use SMTP request to check servers' health */
1161 if (curproxy->check_req != NULL) {
1162 free(curproxy->check_req);
1163 }
1164 curproxy->options &= ~PR_O_HTTP_CHK;
1165 curproxy->options &= ~PR_O_SSL3_CHK;
1166 curproxy->options |= PR_O_SMTP_CHK;
1167
1168 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1169 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1170 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1171 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1172 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1173 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1174 curproxy->check_req = (char *)malloc(reqlen);
1175 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1176 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1177 } else {
1178 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1179 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1180 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1181 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1182 }
1183 }
1184 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001185 else if (!strcmp(args[1], "forwardfor")) {
1186 /* insert x-forwarded-for field, but not for the
1187 * IP address listed as an except.
1188 */
1189 if (*(args[2])) {
1190 if (!strcmp(args[2], "except")) {
1191 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1192 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1193 file, linenum, args[0]);
1194 return -1;
1195 }
1196 /* flush useless bits */
1197 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1198 } else {
1199 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1200 file, linenum, args[0]);
1201 return -1;
1202 }
1203 }
1204 curproxy->options |= PR_O_FWDFOR;
1205 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001206 else {
1207 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1208 return -1;
1209 }
1210 return 0;
1211 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001212 else if (!strcmp(args[0], "default_backend")) {
1213 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1214 return 0;
1215
1216 if (*(args[1]) == 0) {
1217 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1218 return -1;
1219 }
1220 if (curproxy->defbe.name)
1221 free(curproxy->defbe.name);
1222 curproxy->defbe.name = strdup(args[1]);
1223 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001225 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1226 return 0;
1227
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 /* enable reconnections to dispatch */
1229 curproxy->options |= PR_O_REDISP;
1230 }
1231#ifdef TPROXY
1232 else if (!strcmp(args[0], "transparent")) {
1233 /* enable transparent proxy connections */
1234 curproxy->options |= PR_O_TRANSP;
1235 }
1236#endif
1237 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001238 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1239 return 0;
1240
Willy Tarreaubaaee002006-06-26 02:48:02 +02001241 if (*(args[1]) == 0) {
1242 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1243 return -1;
1244 }
1245 curproxy->maxconn = atol(args[1]);
1246 }
Willy Tarreau86034312006-12-29 00:10:33 +01001247 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001248 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1249 return 0;
1250
Willy Tarreau86034312006-12-29 00:10:33 +01001251 if (*(args[1]) == 0) {
1252 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1253 return -1;
1254 }
1255 curproxy->fullconn = atol(args[1]);
1256 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001257 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1258 if (*(args[1]) == 0) {
1259 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1260 return -1;
1261 }
1262 curproxy->grace = atol(args[1]);
1263 }
1264 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1265 if (curproxy == &defproxy) {
1266 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1267 return -1;
1268 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001269 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1270 return 0;
1271
Willy Tarreaubaaee002006-06-26 02:48:02 +02001272 if (strchr(args[1], ':') == NULL) {
1273 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1274 return -1;
1275 }
1276 curproxy->dispatch_addr = *str2sa(args[1]);
1277 }
1278 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001279 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1280 return 0;
1281
Willy Tarreaubaaee002006-06-26 02:48:02 +02001282 if (*(args[1])) {
1283 if (!strcmp(args[1], "roundrobin")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001284 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001285 curproxy->options |= PR_O_BALANCE_RR;
1286 }
1287 else if (!strcmp(args[1], "source")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001288 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001289 curproxy->options |= PR_O_BALANCE_SH;
1290 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001291 else if (!strcmp(args[1], "uri")) {
1292 curproxy->options &= ~PR_O_BALANCE;
1293 curproxy->options |= PR_O_BALANCE_UH;
1294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001295 else {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001296 Alert("parsing [%s:%d] : '%s' only supports 'roundrobin', 'source' and 'uri' options.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001297 return -1;
1298 }
1299 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001300 else {/* if no option is set, use round-robin by default */
1301 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001302 curproxy->options |= PR_O_BALANCE_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304 }
1305 else if (!strcmp(args[0], "server")) { /* server address */
1306 int cur_arg;
1307 char *rport;
1308 char *raddr;
1309 short realport;
1310 int do_check;
1311
1312 if (curproxy == &defproxy) {
1313 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1314 return -1;
1315 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001316 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1317 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318
1319 if (!*args[2]) {
1320 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1321 file, linenum, args[0]);
1322 return -1;
1323 }
1324 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1325 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1326 return -1;
1327 }
1328
1329 /* the servers are linked backwards first */
1330 newsrv->next = curproxy->srv;
1331 curproxy->srv = newsrv;
1332 newsrv->proxy = curproxy;
1333
1334 LIST_INIT(&newsrv->pendconns);
1335 do_check = 0;
1336 newsrv->state = SRV_RUNNING; /* early server setup */
1337 newsrv->id = strdup(args[1]);
1338
1339 /* several ways to check the port component :
1340 * - IP => port=+0, relative
1341 * - IP: => port=+0, relative
1342 * - IP:N => port=N, absolute
1343 * - IP:+N => port=+N, relative
1344 * - IP:-N => port=-N, relative
1345 */
1346 raddr = strdup(args[2]);
1347 rport = strchr(raddr, ':');
1348 if (rport) {
1349 *rport++ = 0;
1350 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001351 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001352 newsrv->state |= SRV_MAPPORTS;
1353 } else {
1354 realport = 0;
1355 newsrv->state |= SRV_MAPPORTS;
1356 }
1357
1358 newsrv->addr = *str2sa(raddr);
1359 newsrv->addr.sin_port = htons(realport);
1360 free(raddr);
1361
1362 newsrv->curfd = -1; /* no health-check in progress */
1363 newsrv->inter = DEF_CHKINTR;
1364 newsrv->rise = DEF_RISETIME;
1365 newsrv->fall = DEF_FALLTIME;
1366 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001367 newsrv->uweight = 1;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001368
Willy Tarreaubaaee002006-06-26 02:48:02 +02001369 cur_arg = 3;
1370 while (*args[cur_arg]) {
1371 if (!strcmp(args[cur_arg], "cookie")) {
1372 newsrv->cookie = strdup(args[cur_arg + 1]);
1373 newsrv->cklen = strlen(args[cur_arg + 1]);
1374 cur_arg += 2;
1375 }
1376 else if (!strcmp(args[cur_arg], "rise")) {
1377 newsrv->rise = atol(args[cur_arg + 1]);
1378 newsrv->health = newsrv->rise;
1379 cur_arg += 2;
1380 }
1381 else if (!strcmp(args[cur_arg], "fall")) {
1382 newsrv->fall = atol(args[cur_arg + 1]);
1383 cur_arg += 2;
1384 }
1385 else if (!strcmp(args[cur_arg], "inter")) {
1386 newsrv->inter = atol(args[cur_arg + 1]);
1387 cur_arg += 2;
1388 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001389 else if (!strcmp(args[cur_arg], "addr")) {
1390 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001391 cur_arg += 2;
1392 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001393 else if (!strcmp(args[cur_arg], "port")) {
1394 newsrv->check_port = atol(args[cur_arg + 1]);
1395 cur_arg += 2;
1396 }
1397 else if (!strcmp(args[cur_arg], "backup")) {
1398 newsrv->state |= SRV_BACKUP;
1399 cur_arg ++;
1400 }
1401 else if (!strcmp(args[cur_arg], "weight")) {
1402 int w;
1403 w = atol(args[cur_arg + 1]);
1404 if (w < 1 || w > 256) {
1405 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1406 file, linenum, newsrv->id, w);
1407 return -1;
1408 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001409 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410 cur_arg += 2;
1411 }
1412 else if (!strcmp(args[cur_arg], "minconn")) {
1413 newsrv->minconn = atol(args[cur_arg + 1]);
1414 cur_arg += 2;
1415 }
1416 else if (!strcmp(args[cur_arg], "maxconn")) {
1417 newsrv->maxconn = atol(args[cur_arg + 1]);
1418 cur_arg += 2;
1419 }
1420 else if (!strcmp(args[cur_arg], "check")) {
1421 global.maxsock++;
1422 do_check = 1;
1423 cur_arg += 1;
1424 }
1425 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1426 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001427#ifdef CONFIG_HAP_CTTPROXY
1428 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1429 file, linenum, "source", "usesrc");
1430#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1432 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001433#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001434 return -1;
1435 }
1436 newsrv->state |= SRV_BIND_SRC;
1437 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1438 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001439 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001440#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001441 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001442 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1443 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001444 return -1;
1445 }
1446 if (!*args[cur_arg + 1]) {
1447 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1448 file, linenum, "usesrc");
1449 return -1;
1450 }
1451 if (!strcmp(args[cur_arg + 1], "client")) {
1452 newsrv->state |= SRV_TPROXY_CLI;
1453 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1454 newsrv->state |= SRV_TPROXY_CIP;
1455 } else {
1456 newsrv->state |= SRV_TPROXY_ADDR;
1457 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1458 }
1459 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1460 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001461#else /* no CTTPROXY support */
1462 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1463 file, linenum, "usesrc");
1464 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001465#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001466 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001468#ifdef CONFIG_HAP_CTTPROXY
1469 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1470 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1471 file, linenum, "usesrc", "source");
1472 return -1;
1473 }
1474#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001475 else {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001476 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn' and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001477 file, linenum, newsrv->id);
1478 return -1;
1479 }
1480 }
1481
1482 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001483 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1484 newsrv->check_port = newsrv->check_addr.sin_port;
1485
Willy Tarreaubaaee002006-06-26 02:48:02 +02001486 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1487 newsrv->check_port = realport; /* by default */
1488 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001489 /* not yet valid, because no port was set on
1490 * the server either. We'll check if we have
1491 * a known port on the first listener.
1492 */
1493 struct listener *l;
1494 l = curproxy->listen;
1495 if (l) {
1496 int port;
1497 port = (l->addr.ss_family == AF_INET6)
1498 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1499 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1500 newsrv->check_port = port;
1501 }
1502 }
1503 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001504 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1505 file, linenum, newsrv->id);
1506 return -1;
1507 }
1508 newsrv->state |= SRV_CHECKED;
1509 }
1510
1511 if (newsrv->state & SRV_BACKUP)
1512 curproxy->srv_bck++;
1513 else
1514 curproxy->srv_act++;
1515 }
1516 else if (!strcmp(args[0], "log")) { /* syslog server address */
1517 struct sockaddr_in *sa;
1518 int facility;
1519
1520 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1521 curproxy->logfac1 = global.logfac1;
1522 curproxy->logsrv1 = global.logsrv1;
1523 curproxy->loglev1 = global.loglev1;
1524 curproxy->logfac2 = global.logfac2;
1525 curproxy->logsrv2 = global.logsrv2;
1526 curproxy->loglev2 = global.loglev2;
1527 }
1528 else if (*(args[1]) && *(args[2])) {
1529 int level;
1530
1531 facility = get_log_facility(args[2]);
1532 if (facility < 0) {
1533 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1534 exit(1);
1535 }
1536
1537 level = 7; /* max syslog level = debug */
1538 if (*(args[3])) {
1539 level = get_log_level(args[3]);
1540 if (level < 0) {
1541 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1542 exit(1);
1543 }
1544 }
1545
1546 sa = str2sa(args[1]);
1547 if (!sa->sin_port)
1548 sa->sin_port = htons(SYSLOG_PORT);
1549
1550 if (curproxy->logfac1 == -1) {
1551 curproxy->logsrv1 = *sa;
1552 curproxy->logfac1 = facility;
1553 curproxy->loglev1 = level;
1554 }
1555 else if (curproxy->logfac2 == -1) {
1556 curproxy->logsrv2 = *sa;
1557 curproxy->logfac2 = facility;
1558 curproxy->loglev2 = level;
1559 }
1560 else {
1561 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1562 return -1;
1563 }
1564 }
1565 else {
1566 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1567 file, linenum);
1568 return -1;
1569 }
1570 }
1571 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001572 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1573 return 0;
1574
Willy Tarreaubaaee002006-06-26 02:48:02 +02001575 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001576#ifdef CONFIG_HAP_CTTPROXY
1577 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1578 file, linenum, "source", "usesrc");
1579#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1581 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001582#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 return -1;
1584 }
1585
1586 curproxy->source_addr = *str2sa(args[1]);
1587 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001588 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001589#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001590 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1591 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1592 file, linenum, "usesrc");
1593 return -1;
1594 }
1595 if (!*args[3]) {
1596 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1597 file, linenum, "usesrc");
1598 return -1;
1599 }
1600
1601 if (!strcmp(args[3], "client")) {
1602 curproxy->options |= PR_O_TPXY_CLI;
1603 } else if (!strcmp(args[3], "clientip")) {
1604 curproxy->options |= PR_O_TPXY_CIP;
1605 } else {
1606 curproxy->options |= PR_O_TPXY_ADDR;
1607 curproxy->tproxy_addr = *str2sa(args[3]);
1608 }
1609 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001610#else /* no CTTPROXY support */
1611 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1612 file, linenum, "usesrc");
1613 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001614#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001615 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001616 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001617#ifdef CONFIG_HAP_CTTPROXY
1618 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1619 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1620 file, linenum, "usesrc", "source");
1621 return -1;
1622 }
1623#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1625 regex_t *preg;
1626 if (curproxy == &defproxy) {
1627 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1628 return -1;
1629 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001630 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1631 return 0;
1632
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 if (*(args[1]) == 0 || *(args[2]) == 0) {
1634 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1635 file, linenum, args[0]);
1636 return -1;
1637 }
1638
1639 preg = calloc(1, sizeof(regex_t));
1640 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1641 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1642 return -1;
1643 }
1644
1645 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1646 if (err) {
1647 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1648 file, linenum, *err);
1649 return -1;
1650 }
1651 }
1652 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1653 regex_t *preg;
1654 if (curproxy == &defproxy) {
1655 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1656 return -1;
1657 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001658 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1659 return 0;
1660
Willy Tarreaubaaee002006-06-26 02:48:02 +02001661 if (*(args[1]) == 0) {
1662 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1663 return -1;
1664 }
1665
1666 preg = calloc(1, sizeof(regex_t));
1667 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1668 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1669 return -1;
1670 }
1671
1672 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1673 }
1674 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1675 regex_t *preg;
1676 if (curproxy == &defproxy) {
1677 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1678 return -1;
1679 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001680 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1681 return 0;
1682
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 if (*(args[1]) == 0) {
1684 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1685 return -1;
1686 }
1687
1688 preg = calloc(1, sizeof(regex_t));
1689 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1690 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1691 return -1;
1692 }
1693
1694 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1695 }
1696 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1697 regex_t *preg;
1698 if (curproxy == &defproxy) {
1699 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1700 return -1;
1701 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001702 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1703 return 0;
1704
Willy Tarreaubaaee002006-06-26 02:48:02 +02001705 if (*(args[1]) == 0) {
1706 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1707 return -1;
1708 }
1709
1710 preg = calloc(1, sizeof(regex_t));
1711 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1712 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1713 return -1;
1714 }
1715
1716 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1717 }
1718 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1719 regex_t *preg;
1720 if (curproxy == &defproxy) {
1721 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1722 return -1;
1723 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001724 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1725 return 0;
1726
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 if (*(args[1]) == 0) {
1728 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1729 return -1;
1730 }
1731
1732 preg = calloc(1, sizeof(regex_t));
1733 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1734 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1735 return -1;
1736 }
1737
1738 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1739 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001740 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1741 regex_t *preg;
1742 if (curproxy == &defproxy) {
1743 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1744 return -1;
1745 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001746 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1747 return 0;
1748
Willy Tarreaub8750a82006-09-03 09:56:00 +02001749 if (*(args[1]) == 0) {
1750 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1751 return -1;
1752 }
1753
1754 preg = calloc(1, sizeof(regex_t));
1755 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1756 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1757 return -1;
1758 }
1759
1760 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1761 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001762 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1763 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001764 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001765 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1766 return -1;
1767 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001768 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1769 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001770
Willy Tarreau977b8e42006-12-29 14:19:17 +01001771 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001772 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1773 file, linenum, args[0]);
1774 return -1;
1775 }
1776
1777 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001778 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001779 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1780 }
1781
1782 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1783 }
1784 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1785 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001786 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001787 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1788 return -1;
1789 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001790 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1791 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001792
Willy Tarreau977b8e42006-12-29 14:19:17 +01001793 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001794 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1795 file, linenum, args[0]);
1796 return -1;
1797 }
1798
1799 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001800 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001801 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1802 }
1803
1804 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1805 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001806 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1807 regex_t *preg;
1808 if (curproxy == &defproxy) {
1809 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1810 return -1;
1811 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001812 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1813 return 0;
1814
Willy Tarreaubaaee002006-06-26 02:48:02 +02001815 if (*(args[1]) == 0 || *(args[2]) == 0) {
1816 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1817 file, linenum, args[0]);
1818 return -1;
1819 }
1820
1821 preg = calloc(1, sizeof(regex_t));
1822 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1823 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1824 return -1;
1825 }
1826
1827 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1828 if (err) {
1829 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1830 file, linenum, *err);
1831 return -1;
1832 }
1833 }
1834 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1835 regex_t *preg;
1836 if (curproxy == &defproxy) {
1837 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1838 return -1;
1839 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001840 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1841 return 0;
1842
Willy Tarreaubaaee002006-06-26 02:48:02 +02001843 if (*(args[1]) == 0) {
1844 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1845 return -1;
1846 }
1847
1848 preg = calloc(1, sizeof(regex_t));
1849 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1850 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1851 return -1;
1852 }
1853
1854 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1855 }
1856 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1857 regex_t *preg;
1858 if (curproxy == &defproxy) {
1859 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1860 return -1;
1861 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001862 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1863 return 0;
1864
Willy Tarreaubaaee002006-06-26 02:48:02 +02001865 if (*(args[1]) == 0) {
1866 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1867 return -1;
1868 }
1869
1870 preg = calloc(1, sizeof(regex_t));
1871 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1872 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1873 return -1;
1874 }
1875
1876 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1877 }
1878 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1879 regex_t *preg;
1880 if (curproxy == &defproxy) {
1881 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1882 return -1;
1883 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001884 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1885 return 0;
1886
Willy Tarreaubaaee002006-06-26 02:48:02 +02001887 if (*(args[1]) == 0) {
1888 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1889 return -1;
1890 }
1891
1892 preg = calloc(1, sizeof(regex_t));
1893 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1894 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1895 return -1;
1896 }
1897
1898 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1899 }
1900 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1901 regex_t *preg;
1902 if (curproxy == &defproxy) {
1903 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1904 return -1;
1905 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001906 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1907 return 0;
1908
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909 if (*(args[1]) == 0) {
1910 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1911 return -1;
1912 }
1913
1914 preg = calloc(1, sizeof(regex_t));
1915 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1916 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1917 return -1;
1918 }
1919
1920 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1921 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001922 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1923 regex_t *preg;
1924 if (curproxy == &defproxy) {
1925 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1926 return -1;
1927 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001928 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1929 return 0;
1930
Willy Tarreaub8750a82006-09-03 09:56:00 +02001931 if (*(args[1]) == 0) {
1932 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1933 return -1;
1934 }
1935
1936 preg = calloc(1, sizeof(regex_t));
1937 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1938 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1939 return -1;
1940 }
1941
1942 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1945 if (curproxy == &defproxy) {
1946 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1947 return -1;
1948 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001949 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1950 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001951
1952 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
1953 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1954 return 0;
1955 }
1956
1957 if (*(args[1]) == 0) {
1958 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1959 return -1;
1960 }
1961
1962 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
1963 }
1964 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
1965 regex_t *preg;
1966
1967 if (*(args[1]) == 0 || *(args[2]) == 0) {
1968 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1969 file, linenum, args[0]);
1970 return -1;
1971 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001972 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1973 return 0;
1974
Willy Tarreaubaaee002006-06-26 02:48:02 +02001975 preg = calloc(1, sizeof(regex_t));
1976 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1977 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1978 return -1;
1979 }
1980
1981 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1982 if (err) {
1983 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1984 file, linenum, *err);
1985 return -1;
1986 }
1987 }
1988 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
1989 regex_t *preg;
1990 if (curproxy == &defproxy) {
1991 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1992 return -1;
1993 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001994 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1995 return 0;
1996
Willy Tarreaubaaee002006-06-26 02:48:02 +02001997 if (*(args[1]) == 0) {
1998 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1999 return -1;
2000 }
2001
2002 preg = calloc(1, sizeof(regex_t));
2003 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2004 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2005 return -1;
2006 }
2007
2008 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2009 if (err) {
2010 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2011 file, linenum, *err);
2012 return -1;
2013 }
2014 }
2015 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a 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 <search> 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 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2036 if (err) {
2037 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2038 file, linenum, *err);
2039 return -1;
2040 }
2041 }
2042 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2043 regex_t *preg;
2044 if (curproxy == &defproxy) {
2045 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2046 return -1;
2047 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002048 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2049 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002050
2051 if (*(args[1]) == 0 || *(args[2]) == 0) {
2052 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2053 file, linenum, args[0]);
2054 return -1;
2055 }
2056
2057 preg = calloc(1, sizeof(regex_t));
2058 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2059 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2060 return -1;
2061 }
2062
2063 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2064 if (err) {
2065 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2066 file, linenum, *err);
2067 return -1;
2068 }
2069 }
2070 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2071 regex_t *preg;
2072 if (curproxy == &defproxy) {
2073 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2074 return -1;
2075 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002076 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2077 return 0;
2078
Willy Tarreaubaaee002006-06-26 02:48:02 +02002079 if (*(args[1]) == 0) {
2080 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2081 return -1;
2082 }
2083
2084 preg = calloc(1, sizeof(regex_t));
2085 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2086 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2087 return -1;
2088 }
2089
2090 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2091 if (err) {
2092 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2093 file, linenum, *err);
2094 return -1;
2095 }
2096 }
2097 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2098 regex_t *preg;
2099 if (curproxy == &defproxy) {
2100 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2101 return -1;
2102 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002103 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2104 return 0;
2105
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 if (*(args[1]) == 0) {
2107 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2108 return -1;
2109 }
2110
2111 preg = calloc(1, sizeof(regex_t));
2112 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2113 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2114 return -1;
2115 }
2116
2117 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2118 if (err) {
2119 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2120 file, linenum, *err);
2121 return -1;
2122 }
2123 }
2124 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2125 if (curproxy == &defproxy) {
2126 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2127 return -1;
2128 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002129 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2130 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002131
2132 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2133 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2134 return 0;
2135 }
2136
2137 if (*(args[1]) == 0) {
2138 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2139 return -1;
2140 }
2141
2142 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2143 }
2144 else if (!strcmp(args[0], "errorloc") ||
2145 !strcmp(args[0], "errorloc302") ||
2146 !strcmp(args[0], "errorloc303")) { /* error location */
2147 int errnum, errlen;
2148 char *err;
2149
Willy Tarreau977b8e42006-12-29 14:19:17 +01002150 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2151 return 0;
2152
Willy Tarreaubaaee002006-06-26 02:48:02 +02002153 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002154 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155 return -1;
2156 }
2157
2158 errnum = atol(args[1]);
2159 if (!strcmp(args[0], "errorloc303")) {
2160 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2161 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2162 } else {
2163 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2164 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2165 }
2166
Willy Tarreau0f772532006-12-23 20:51:41 +01002167 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2168 if (http_err_codes[rc] == errnum) {
2169 if (curproxy->errmsg[rc].str)
2170 free(curproxy->errmsg[rc].str);
2171 curproxy->errmsg[rc].str = err;
2172 curproxy->errmsg[rc].len = errlen;
2173 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002174 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002175 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002176
2177 if (rc >= HTTP_ERR_SIZE) {
2178 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2179 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002180 free(err);
2181 }
2182 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002183 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2184 int errnum, errlen, fd;
2185 char *err;
2186 struct stat stat;
2187
2188 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2189 return 0;
2190
2191 if (*(args[2]) == 0) {
2192 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2193 return -1;
2194 }
2195
2196 fd = open(args[2], O_RDONLY);
2197 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2198 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2199 file, linenum, args[2], args[1]);
2200 if (fd >= 0)
2201 close(fd);
2202 return -1;
2203 }
2204
2205 if (stat.st_size <= BUFSIZE) {
2206 errlen = stat.st_size;
2207 } else {
2208 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2209 file, linenum, args[2], BUFSIZE);
2210 errlen = BUFSIZE;
2211 }
2212
2213 err = malloc(errlen); /* malloc() must succeed during parsing */
2214 errnum = read(fd, err, errlen);
2215 if (errnum != errlen) {
2216 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2217 file, linenum, args[2], args[1]);
2218 close(fd);
2219 free(err);
2220 return -1;
2221 }
2222 close(fd);
2223
2224 errnum = atol(args[1]);
2225 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2226 if (http_err_codes[rc] == errnum) {
2227 if (curproxy->errmsg[rc].str)
2228 free(curproxy->errmsg[rc].str);
2229 curproxy->errmsg[rc].str = err;
2230 curproxy->errmsg[rc].len = errlen;
2231 break;
2232 }
2233 }
2234
2235 if (rc >= HTTP_ERR_SIZE) {
2236 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2237 file, linenum, errnum);
2238 free(err);
2239 }
2240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241 else {
2242 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2243 return -1;
2244 }
2245 return 0;
2246}
2247
2248
2249/*
2250 * This function reads and parses the configuration file given in the argument.
2251 * returns 0 if OK, -1 if error.
2252 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002253int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254{
2255 char thisline[256];
2256 char *line;
2257 FILE *f;
2258 int linenum = 0;
2259 char *end;
Willy Tarreau540abe42007-05-02 20:50:16 +02002260 char *args[MAX_LINE_ARGS + 1];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 int arg;
2262 int cfgerr = 0;
Willy Tarreau80587432006-12-24 17:47:20 +01002263 int nbchk, mininter;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264 int confsect = CFG_NONE;
2265
2266 struct proxy *curproxy = NULL;
2267 struct server *newsrv = NULL;
2268
2269 if ((f=fopen(file,"r")) == NULL)
2270 return -1;
2271
2272 init_default_instance();
2273
2274 while (fgets(line = thisline, sizeof(thisline), f) != NULL) {
2275 linenum++;
2276
2277 end = line + strlen(line);
2278
2279 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002280 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002281 line++;
2282
2283 arg = 0;
2284 args[arg] = line;
2285
2286 while (*line && arg < MAX_LINE_ARGS) {
2287 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2288 * C equivalent value. Other combinations left unchanged (eg: \1).
2289 */
2290 if (*line == '\\') {
2291 int skip = 0;
2292 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2293 *line = line[1];
2294 skip = 1;
2295 }
2296 else if (line[1] == 'r') {
2297 *line = '\r';
2298 skip = 1;
2299 }
2300 else if (line[1] == 'n') {
2301 *line = '\n';
2302 skip = 1;
2303 }
2304 else if (line[1] == 't') {
2305 *line = '\t';
2306 skip = 1;
2307 }
2308 else if (line[1] == 'x') {
2309 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2310 unsigned char hex1, hex2;
2311 hex1 = toupper(line[2]) - '0';
2312 hex2 = toupper(line[3]) - '0';
2313 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2314 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2315 *line = (hex1<<4) + hex2;
2316 skip = 3;
2317 }
2318 else {
2319 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2320 return -1;
2321 }
2322 }
2323 if (skip) {
2324 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2325 end -= skip;
2326 }
2327 line++;
2328 }
2329 else if (*line == '#' || *line == '\n' || *line == '\r') {
2330 /* end of string, end of loop */
2331 *line = 0;
2332 break;
2333 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002334 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 /* a non-escaped space is an argument separator */
2336 *line++ = 0;
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002337 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002338 line++;
2339 args[++arg] = line;
2340 }
2341 else {
2342 line++;
2343 }
2344 }
2345
2346 /* empty line */
2347 if (!**args)
2348 continue;
2349
Willy Tarreau540abe42007-05-02 20:50:16 +02002350 /* zero out remaining args and ensure that at least one entry
2351 * is zeroed out.
2352 */
2353 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 args[arg] = line;
2355 }
2356
Willy Tarreau977b8e42006-12-29 14:19:17 +01002357 if (!strcmp(args[0], "listen") ||
2358 !strcmp(args[0], "frontend") ||
2359 !strcmp(args[0], "backend") ||
2360 !strcmp(args[0], "ruleset") ||
2361 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 confsect = CFG_LISTEN;
2363 else if (!strcmp(args[0], "global")) /* global config */
2364 confsect = CFG_GLOBAL;
2365 /* else it's a section keyword */
2366
2367 switch (confsect) {
2368 case CFG_LISTEN:
2369 if (cfg_parse_listen(file, linenum, args) < 0)
2370 return -1;
2371 break;
2372 case CFG_GLOBAL:
2373 if (cfg_parse_global(file, linenum, args) < 0)
2374 return -1;
2375 break;
2376 default:
2377 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2378 return -1;
2379 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 }
2381 fclose(f);
2382
2383 /*
2384 * Now, check for the integrity of all that we have collected.
2385 */
2386
2387 /* will be needed further to delay some tasks */
2388 tv_now(&now);
2389
2390 if ((curproxy = proxy) == NULL) {
2391 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2392 file);
2393 return -1;
2394 }
2395
2396 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002397 struct switching_rule *rule;
2398
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 if (curproxy->state == PR_STSTOPPED) {
2400 curproxy = curproxy->next;
2401 continue;
2402 }
2403
Willy Tarreau977b8e42006-12-29 14:19:17 +01002404 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2405 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 +01002406 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002407 cfgerr++;
2408 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002409 else if (curproxy->cap & PR_CAP_BE &&
2410 ((curproxy->mode != PR_MODE_HEALTH) &&
2411 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
2412 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2413 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 +01002414 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 cfgerr++;
2416 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002417
2418 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002420 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002421 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 cfgerr++;
2423 }
2424#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2425 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002426 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002427 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 cfgerr++;
2429 }
2430#endif
2431 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002432 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002433 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 }
2435 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002436
2437 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002439 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002440 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002443 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002444 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445 }
2446 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002447 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002448 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002449 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002450 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002451 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002452 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002453 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002454 if (curproxy->options & PR_O_BALANCE_UH) {
2455 curproxy->options &= ~PR_O_BALANCE;
2456 curproxy->options |= PR_O_BALANCE_RR;
2457
2458 Warning("parsing %s : URI hash will be ignored for %s '%s'. Falling back to round robin.\n",
2459 file, proxy_type_str(curproxy), curproxy->id);
2460 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002462
2463 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2464 if ((newsrv = curproxy->srv) != NULL) {
2465 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2466 file, proxy_type_str(curproxy), curproxy->id);
2467 }
2468 }
2469
2470 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2472 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2473 file, curproxy->id);
2474 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002475 }
2476 }
2477
2478 /* if a default backend was specified, let's find it */
2479 if (curproxy->defbe.name) {
2480 struct proxy *target;
2481
2482 for (target = proxy; target != NULL; target = target->next) {
2483 if (strcmp(target->id, curproxy->defbe.name) == 0)
2484 break;
2485 }
2486 if (target == NULL) {
2487 Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n",
2488 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2489 cfgerr++;
2490 } else if (target == curproxy) {
2491 Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
2492 cfgerr++;
2493 } else if (!(target->cap & PR_CAP_BE)) {
2494 Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n",
2495 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2496 cfgerr++;
2497 } else if (target->mode != curproxy->mode) {
2498 Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
2499 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2500 cfgerr++;
2501 } else {
2502 free(curproxy->defbe.name);
2503 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504 }
2505 }
2506
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002507 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002508 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2509 /* map jump target for ACT_SETBE in req_rep chain */
2510 struct hdr_exp *exp;
2511 struct proxy *target;
2512 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
2513 if (exp->action != ACT_SETBE)
2514 continue;
2515 for (target = proxy; target != NULL; target = target->next) {
2516 if (strcmp(target->id, exp->replace) == 0)
2517 break;
2518 }
2519 if (target == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002520 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002521 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaua496b602006-12-17 23:15:24 +01002522 cfgerr++;
2523 } else if (target == curproxy) {
2524 Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
2525 cfgerr++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002526 } else if (!(target->cap & PR_CAP_BE)) {
2527 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002528 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002529 cfgerr++;
2530 } else if (target->mode != PR_MODE_HTTP) {
2531 Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002532 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002533 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002534 } else {
2535 free((void *)exp->replace);
2536 exp->replace = (const char *)target;
2537 }
2538 }
2539 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002540
2541 /* find the target proxy for 'use_backend' rules */
2542 list_for_each_entry(rule, &curproxy->switching_rules, list) {
2543 /* map jump target for ACT_SETBE in req_rep chain */
2544 struct proxy *target;
2545
2546 for (target = proxy; target != NULL; target = target->next) {
2547 if (strcmp(target->id, rule->be.name) == 0)
2548 break;
2549 }
2550
2551 if (target == NULL) {
2552 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
2553 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2554 cfgerr++;
2555 } else if (target == curproxy) {
2556 Alert("parsing %s : loop detected for backend %s !\n", file, rule->be.name);
2557 cfgerr++;
2558 } else if (!(target->cap & PR_CAP_BE)) {
2559 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
2560 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2561 cfgerr++;
2562 } else if (target->mode != curproxy->mode) {
2563 Alert("parsing %s : backend '%s' referenced in %s '%s' is of different mode !\n",
2564 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2565 cfgerr++;
2566 } else {
2567 free((void *)rule->be.name);
2568 rule->be.backend = target;
2569 }
2570 }
2571
Willy Tarreau2738a142006-07-08 17:28:09 +02002572 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002573 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2574 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2575 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002576 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002577 " | While not properly invalid, you will certainly encounter various problems\n"
2578 " | with such a configuration. To fix this, please ensure that all following\n"
2579 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002580 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002581 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002582
2583 if (curproxy->options & PR_O_SSL3_CHK) {
2584 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2585 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2586 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2587 }
2588
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002589 /* The small pools required for the capture lists */
2590 if (curproxy->nb_req_cap)
2591 curproxy->req_cap_pool = create_pool("ptrcap",
2592 curproxy->nb_req_cap * sizeof(char *),
2593 MEM_F_SHARED);
2594 if (curproxy->nb_rsp_cap)
2595 curproxy->rsp_cap_pool = create_pool("ptrcap",
2596 curproxy->nb_rsp_cap * sizeof(char *),
2597 MEM_F_SHARED);
2598
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002599 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2600 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2601 MEM_F_SHARED);
2602
Willy Tarreau86034312006-12-29 00:10:33 +01002603 /* for backwards compatibility with "listen" instances, if
2604 * fullconn is not set but maxconn is set, then maxconn
2605 * is used.
2606 */
2607 if (!curproxy->fullconn)
2608 curproxy->fullconn = curproxy->maxconn;
2609
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 /* first, we will invert the servers list order */
2611 newsrv = NULL;
2612 while (curproxy->srv) {
2613 struct server *next;
2614
2615 next = curproxy->srv->next;
2616 curproxy->srv->next = newsrv;
2617 newsrv = curproxy->srv;
2618 if (!next)
2619 break;
2620 curproxy->srv = next;
2621 }
2622
2623 /* now, newsrv == curproxy->srv */
2624 if (newsrv) {
2625 struct server *srv;
2626 int pgcd;
2627 int act, bck;
2628
2629 /* We will factor the weights to reduce the table,
2630 * using Euclide's largest common divisor algorithm
2631 */
Willy Tarreau417fae02007-03-25 21:16:40 +02002632 pgcd = newsrv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002633 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2634 int t, w;
2635
Willy Tarreau417fae02007-03-25 21:16:40 +02002636 w = srv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002637 while (w) {
2638 t = pgcd % w;
2639 pgcd = w;
2640 w = t;
2641 }
2642 }
2643
2644 act = bck = 0;
2645 for (srv = newsrv; srv; srv = srv->next) {
Willy Tarreau417fae02007-03-25 21:16:40 +02002646 srv->eweight = srv->uweight / pgcd;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 if (srv->state & SRV_BACKUP)
Willy Tarreau417fae02007-03-25 21:16:40 +02002648 bck += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 else
Willy Tarreau417fae02007-03-25 21:16:40 +02002650 act += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651 }
2652
2653 /* this is the largest map we will ever need for this servers list */
2654 if (act < bck)
2655 act = bck;
2656
2657 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2658 /* recounts servers and their weights */
Willy Tarreau5af3a692007-07-24 23:32:33 +02002659 curproxy->map_state = PR_MAP_RECALC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002660 recount_servers(curproxy);
2661 recalc_server_map(curproxy);
2662 }
2663
2664 if (curproxy->options & PR_O_LOGASAP)
2665 curproxy->to_log &= ~LW_BYTES;
2666
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667 /*
2668 * If this server supports a maxconn parameter, it needs a dedicated
2669 * tasks to fill the emptied slots when a connection leaves.
2670 */
2671 newsrv = curproxy->srv;
2672 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002673 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002674 /* Only 'minconn' was specified, or it was higher than or equal
2675 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2676 * this will avoid further useless expensive computations.
2677 */
2678 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002679 } else if (newsrv->maxconn && !newsrv->minconn) {
2680 /* minconn was not specified, so we set it to maxconn */
2681 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002682 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2683 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002684 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002685 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686 }
2687
2688 if (newsrv->maxconn > 0) {
2689 struct task *t;
2690
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002691 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2693 return -1;
2694 }
2695
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002696 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002697 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 t->state = TASK_IDLE;
2699 t->process = process_srv_queue;
2700 t->context = newsrv;
2701 newsrv->queue_mgt = t;
2702
2703 /* never run it unless specifically woken up */
2704 tv_eternity(&t->expire);
2705 task_queue(t);
2706 }
2707 newsrv = newsrv->next;
2708 }
2709
2710 /* now we'll start this proxy's health checks if any */
2711 /* 1- count the checkers to run simultaneously */
2712 nbchk = 0;
2713 mininter = 0;
2714 newsrv = curproxy->srv;
2715 while (newsrv != NULL) {
2716 if (newsrv->state & SRV_CHECKED) {
2717 if (!mininter || mininter > newsrv->inter)
2718 mininter = newsrv->inter;
2719 nbchk++;
2720 }
2721 newsrv = newsrv->next;
2722 }
2723
2724 /* 2- start them as far as possible from each others while respecting
2725 * their own intervals. For this, we will start them after their own
2726 * interval added to the min interval divided by the number of servers,
2727 * weighted by the server's position in the list.
2728 */
2729 if (nbchk > 0) {
2730 struct task *t;
2731 int srvpos;
2732
2733 newsrv = curproxy->srv;
2734 srvpos = 0;
2735 while (newsrv != NULL) {
2736 /* should this server be checked ? */
2737 if (newsrv->state & SRV_CHECKED) {
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002738 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002739 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2740 return -1;
2741 }
2742
Willy Tarreau964c9362007-01-07 00:38:00 +01002743 t->wq = NULL;
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002744 t->qlist.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002745 t->state = TASK_IDLE;
2746 t->process = process_chk;
2747 t->context = newsrv;
2748
2749 /* check this every ms */
Willy Tarreau42aae5c2007-04-29 17:43:56 +02002750 tv_ms_add(&t->expire, &now,
2751 newsrv->inter + mininter * srvpos / nbchk);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002752 task_queue(t);
2753 //task_wakeup(&rq, t);
2754 srvpos++;
2755 }
2756 newsrv = newsrv->next;
2757 }
2758 }
2759
2760 curproxy = curproxy->next;
2761 }
2762 if (cfgerr > 0) {
2763 Alert("Errors found in configuration file, aborting.\n");
2764 return -1;
2765 }
2766 else
2767 return 0;
2768}
2769
2770
2771
2772/*
2773 * Local variables:
2774 * c-indent-level: 8
2775 * c-basic-offset: 8
2776 * End:
2777 */