blob: 19b2ee71adf53aecdcd843067329f0592ad21766 [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 },
Alexandre Cassen87ea5482007-10-11 20:48:58 +020095 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010096 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
97 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
98 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
99 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
100 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
101 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
102 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
103 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
104 { "forceclose", PR_O_FORCE_CLO | PR_O_HTTP_CLOSE, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100105#ifdef CONFIG_HAP_TCPSPLICE
106 { "tcpsplice", PR_O_TCPSPLICE , PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
107#endif
108
Willy Tarreau13943ab2006-12-31 00:24:10 +0100109 { NULL, 0, 0 }
110};
111
Willy Tarreaubaaee002006-06-26 02:48:02 +0200112
113static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
114int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
115int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
116
117/*
118 * converts <str> to a list of listeners which are dynamically allocated.
119 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
120 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
121 * - <port> is a numerical port from 1 to 65535 ;
122 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
123 * This can be repeated as many times as necessary, separated by a coma.
124 * The <tail> argument is a pointer to a current list which should be appended
125 * to the tail of the new list. The pointer to the new list is returned.
126 */
127static struct listener *str2listener(char *str, struct listener *tail)
128{
129 struct listener *l;
130 char *c, *next, *range, *dupstr;
131 int port, end;
132
133 next = dupstr = strdup(str);
134
135 while (next && *next) {
136 struct sockaddr_storage ss;
137
138 str = next;
139 /* 1) look for the end of the first address */
140 if ((next = strrchr(str, ',')) != NULL) {
141 *next++ = 0;
142 }
143
144 /* 2) look for the addr/port delimiter, it's the last colon. */
145 if ((range = strrchr(str, ':')) == NULL) {
146 Alert("Missing port number: '%s'\n", str);
147 goto fail;
148 }
149
150 *range++ = 0;
151
152 if (strrchr(str, ':') != NULL) {
153 /* IPv6 address contains ':' */
154 memset(&ss, 0, sizeof(ss));
155 ss.ss_family = AF_INET6;
156
157 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
158 Alert("Invalid server address: '%s'\n", str);
159 goto fail;
160 }
161 }
162 else {
163 memset(&ss, 0, sizeof(ss));
164 ss.ss_family = AF_INET;
165
166 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
167 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
168 }
169 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
170 struct hostent *he;
171
172 if ((he = gethostbyname(str)) == NULL) {
173 Alert("Invalid server name: '%s'\n", str);
174 goto fail;
175 }
176 else
177 ((struct sockaddr_in *)&ss)->sin_addr =
178 *(struct in_addr *) *(he->h_addr_list);
179 }
180 }
181
182 /* 3) look for the port-end delimiter */
183 if ((c = strchr(range, '-')) != NULL) {
184 *c++ = 0;
185 end = atol(c);
186 }
187 else {
188 end = atol(range);
189 }
190
191 port = atol(range);
192
193 if (port < 1 || port > 65535) {
194 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
195 goto fail;
196 }
197
198 if (end < 1 || end > 65535) {
199 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
200 goto fail;
201 }
202
203 for (; port <= end; port++) {
204 l = (struct listener *)calloc(1, sizeof(struct listener));
205 l->next = tail;
206 tail = l;
207
208 l->fd = -1;
209 l->addr = ss;
210 if (ss.ss_family == AF_INET6)
211 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
212 else
213 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
214
215 } /* end for(port) */
216 } /* end while(next) */
217 free(dupstr);
218 return tail;
219 fail:
220 free(dupstr);
221 return NULL;
222}
223
Willy Tarreau977b8e42006-12-29 14:19:17 +0100224/*
225 * Sends a warning if proxy <proxy> does not have at least one of the
226 * capabilities in <cap>. An optionnal <hint> may be added at the end
227 * of the warning to help the user. Returns 1 if a warning was emitted
228 * or 0 if the condition is valid.
229 */
230int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
231{
232 char *msg;
233
234 switch (cap) {
235 case PR_CAP_BE: msg = "no backend"; break;
236 case PR_CAP_FE: msg = "no frontend"; break;
237 case PR_CAP_RS: msg = "no ruleset"; break;
238 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
239 default: msg = "not enough"; break;
240 }
241
242 if (!(proxy->cap & cap)) {
243 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100244 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100245 return 1;
246 }
247 return 0;
248}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249
250/*
251 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
252 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200253int cfg_parse_global(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254{
255
256 if (!strcmp(args[0], "global")) { /* new section */
257 /* no option, nothing special to do */
258 return 0;
259 }
260 else if (!strcmp(args[0], "daemon")) {
261 global.mode |= MODE_DAEMON;
262 }
263 else if (!strcmp(args[0], "debug")) {
264 global.mode |= MODE_DEBUG;
265 }
266 else if (!strcmp(args[0], "noepoll")) {
267 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
268 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200269 else if (!strcmp(args[0], "nosepoll")) {
270 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
271 }
272 else if (!strcmp(args[0], "nokqueue")) {
273 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275 else if (!strcmp(args[0], "nopoll")) {
276 cfg_polling_mechanism &= ~POLL_USE_POLL;
277 }
278 else if (!strcmp(args[0], "quiet")) {
279 global.mode |= MODE_QUIET;
280 }
281 else if (!strcmp(args[0], "stats")) {
282 global.mode |= MODE_STATS;
283 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200284 else if (!strcmp(args[0], "tune.maxpollevents")) {
285 if (global.tune.maxpollevents != 0) {
286 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
287 return 0;
288 }
289 if (*(args[1]) == 0) {
290 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
291 return -1;
292 }
293 global.tune.maxpollevents = atol(args[1]);
294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295 else if (!strcmp(args[0], "uid")) {
296 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200297 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 return 0;
299 }
300 if (*(args[1]) == 0) {
301 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
302 return -1;
303 }
304 global.uid = atol(args[1]);
305 }
306 else if (!strcmp(args[0], "gid")) {
307 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200308 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200309 return 0;
310 }
311 if (*(args[1]) == 0) {
312 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
313 return -1;
314 }
315 global.gid = atol(args[1]);
316 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200317 /* user/group name handling */
318 else if (!strcmp(args[0], "user")) {
319 struct passwd *ha_user;
320 if (global.uid != 0) {
321 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
322 return 0;
323 }
324 errno = 0;
325 ha_user = getpwnam(args[1]);
326 if (ha_user != NULL) {
327 global.uid = (int)ha_user->pw_uid;
328 }
329 else {
330 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
331 exit(1);
332 }
333 }
334 else if (!strcmp(args[0], "group")) {
335 struct group *ha_group;
336 if (global.gid != 0) {
337 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
338 return 0;
339 }
340 errno = 0;
341 ha_group = getgrnam(args[1]);
342 if (ha_group != NULL) {
343 global.gid = (int)ha_group->gr_gid;
344 }
345 else {
346 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
347 exit(1);
348 }
349 }
350 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200351 else if (!strcmp(args[0], "nbproc")) {
352 if (global.nbproc != 0) {
353 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
354 return 0;
355 }
356 if (*(args[1]) == 0) {
357 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
358 return -1;
359 }
360 global.nbproc = atol(args[1]);
361 }
362 else if (!strcmp(args[0], "maxconn")) {
363 if (global.maxconn != 0) {
364 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
365 return 0;
366 }
367 if (*(args[1]) == 0) {
368 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
369 return -1;
370 }
371 global.maxconn = atol(args[1]);
372#ifdef SYSTEM_MAXCONN
373 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
374 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);
375 global.maxconn = DEFAULT_MAXCONN;
376 }
377#endif /* SYSTEM_MAXCONN */
378 }
379 else if (!strcmp(args[0], "ulimit-n")) {
380 if (global.rlimit_nofile != 0) {
381 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
382 return 0;
383 }
384 if (*(args[1]) == 0) {
385 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
386 return -1;
387 }
388 global.rlimit_nofile = atol(args[1]);
389 }
390 else if (!strcmp(args[0], "chroot")) {
391 if (global.chroot != NULL) {
392 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
393 return 0;
394 }
395 if (*(args[1]) == 0) {
396 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
397 return -1;
398 }
399 global.chroot = strdup(args[1]);
400 }
401 else if (!strcmp(args[0], "pidfile")) {
402 if (global.pidfile != NULL) {
403 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
404 return 0;
405 }
406 if (*(args[1]) == 0) {
407 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
408 return -1;
409 }
410 global.pidfile = strdup(args[1]);
411 }
412 else if (!strcmp(args[0], "log")) { /* syslog server address */
413 struct sockaddr_in *sa;
414 int facility, level;
415
416 if (*(args[1]) == 0 || *(args[2]) == 0) {
417 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
418 return -1;
419 }
420
421 facility = get_log_facility(args[2]);
422 if (facility < 0) {
423 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
424 exit(1);
425 }
426
427 level = 7; /* max syslog level = debug */
428 if (*(args[3])) {
429 level = get_log_level(args[3]);
430 if (level < 0) {
431 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
432 exit(1);
433 }
434 }
435
436 sa = str2sa(args[1]);
437 if (!sa->sin_port)
438 sa->sin_port = htons(SYSLOG_PORT);
439
440 if (global.logfac1 == -1) {
441 global.logsrv1 = *sa;
442 global.logfac1 = facility;
443 global.loglev1 = level;
444 }
445 else if (global.logfac2 == -1) {
446 global.logsrv2 = *sa;
447 global.logfac2 = facility;
448 global.loglev2 = level;
449 }
450 else {
451 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
452 return -1;
453 }
454
455 }
456 else {
457 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
458 return -1;
459 }
460 return 0;
461}
462
463
464static void init_default_instance()
465{
466 memset(&defproxy, 0, sizeof(defproxy));
467 defproxy.mode = PR_MODE_TCP;
468 defproxy.state = PR_STNEW;
469 defproxy.maxconn = cfg_maxpconn;
470 defproxy.conn_retries = CONN_RETRIES;
471 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaufdd0f552007-09-17 11:12:40 +0200472 tv_eternity(&defproxy.clitimeout);
473 tv_eternity(&defproxy.contimeout);
474 tv_eternity(&defproxy.srvtimeout);
475 tv_eternity(&defproxy.appsession_timeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476}
477
478/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100479 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
480 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200482int cfg_parse_listen(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483{
484 static struct proxy *curproxy = NULL;
485 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200486 const char *err;
Willy Tarreauee991362007-05-14 14:37:50 +0200487 int rc, val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200488
Willy Tarreau977b8e42006-12-29 14:19:17 +0100489 if (!strcmp(args[0], "listen"))
490 rc = PR_CAP_LISTEN;
491 else if (!strcmp(args[0], "frontend"))
492 rc = PR_CAP_FE | PR_CAP_RS;
493 else if (!strcmp(args[0], "backend"))
494 rc = PR_CAP_BE | PR_CAP_RS;
495 else if (!strcmp(args[0], "ruleset"))
496 rc = PR_CAP_RS;
497 else
498 rc = PR_CAP_NONE;
499
500 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200501 if (!*args[1]) {
502 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
503 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
504 file, linenum, args[0]);
505 return -1;
506 }
507
508 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
509 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
510 return -1;
511 }
512
513 curproxy->next = proxy;
514 proxy = curproxy;
515 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200516 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200517 LIST_INIT(&curproxy->block_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200518 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200519
Willy Tarreauee991362007-05-14 14:37:50 +0200520 /* Timeouts are defined as -1, so we cannot use the zeroed area
521 * as a default value.
522 */
523 tv_eternity(&curproxy->clitimeout);
524 tv_eternity(&curproxy->srvtimeout);
525 tv_eternity(&curproxy->contimeout);
526 tv_eternity(&curproxy->appsession_timeout);
527
Willy Tarreaubaaee002006-06-26 02:48:02 +0200528 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100529 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530
531 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100532 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200533 curproxy->listen = str2listener(args[2], curproxy->listen);
534 if (!curproxy->listen)
535 return -1;
536 global.maxsock++;
537 }
538
539 /* set default values */
540 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541 curproxy->options = defproxy.options;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200542 curproxy->except_net = defproxy.except_net;
543 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200544
Willy Tarreau977b8e42006-12-29 14:19:17 +0100545 if (curproxy->cap & PR_CAP_FE) {
546 curproxy->maxconn = defproxy.maxconn;
547
548 /* initialize error relocations */
549 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
550 if (defproxy.errmsg[rc].str)
551 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
552 }
553
554 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
555 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200556
Willy Tarreau977b8e42006-12-29 14:19:17 +0100557 if (curproxy->cap & PR_CAP_BE) {
558 curproxy->fullconn = defproxy.fullconn;
559 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200560
Willy Tarreau977b8e42006-12-29 14:19:17 +0100561 if (defproxy.check_req)
562 curproxy->check_req = strdup(defproxy.check_req);
563 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200564
Willy Tarreau977b8e42006-12-29 14:19:17 +0100565 if (defproxy.cookie_name)
566 curproxy->cookie_name = strdup(defproxy.cookie_name);
567 curproxy->cookie_len = defproxy.cookie_len;
568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200569
Willy Tarreau977b8e42006-12-29 14:19:17 +0100570 if (curproxy->cap & PR_CAP_RS) {
571 if (defproxy.capture_name)
572 curproxy->capture_name = strdup(defproxy.capture_name);
573 curproxy->capture_namelen = defproxy.capture_namelen;
574 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100575 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200576
Willy Tarreau977b8e42006-12-29 14:19:17 +0100577 if (curproxy->cap & PR_CAP_FE) {
578 curproxy->clitimeout = defproxy.clitimeout;
579 curproxy->uri_auth = defproxy.uri_auth;
580 curproxy->mon_net = defproxy.mon_net;
581 curproxy->mon_mask = defproxy.mon_mask;
582 if (defproxy.monitor_uri)
583 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
584 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100585 if (defproxy.defbe.name)
586 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100587 }
588
589 if (curproxy->cap & PR_CAP_BE) {
590 curproxy->contimeout = defproxy.contimeout;
591 curproxy->srvtimeout = defproxy.srvtimeout;
592 curproxy->source_addr = defproxy.source_addr;
593 }
594
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 curproxy->mode = defproxy.mode;
596 curproxy->logfac1 = defproxy.logfac1;
597 curproxy->logsrv1 = defproxy.logsrv1;
598 curproxy->loglev1 = defproxy.loglev1;
599 curproxy->logfac2 = defproxy.logfac2;
600 curproxy->logsrv2 = defproxy.logsrv2;
601 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 curproxy->grace = defproxy.grace;
Willy Tarreau1c47f852006-07-09 08:22:27 +0200603
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604 return 0;
605 }
606 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
607 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100608 /* FIXME-20070101: we should do this too at the end of the
609 * config parsing to free all default values.
610 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 if (defproxy.check_req) free(defproxy.check_req);
612 if (defproxy.cookie_name) free(defproxy.cookie_name);
613 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200614 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100615 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100616
617 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
618 if (defproxy.errmsg[rc].len)
619 free(defproxy.errmsg[rc].str);
620 }
621
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622 /* we cannot free uri_auth because it might already be used */
623 init_default_instance();
624 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100625 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 return 0;
627 }
628 else if (curproxy == NULL) {
629 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
630 return -1;
631 }
632
Willy Tarreau977b8e42006-12-29 14:19:17 +0100633
634 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 if (!strcmp(args[0], "bind")) { /* new listen addresses */
636 if (curproxy == &defproxy) {
637 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
638 return -1;
639 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100640 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
641 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642
643 if (strchr(args[1], ':') == NULL) {
644 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
645 file, linenum, args[0]);
646 return -1;
647 }
648 curproxy->listen = str2listener(args[1], curproxy->listen);
649 if (!curproxy->listen)
650 return -1;
651 global.maxsock++;
652 return 0;
653 }
654 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
655 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
656 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
657 file, linenum, args[0]);
658 return -1;
659 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100660 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
661 return 0;
662
Willy Tarreaubaaee002006-06-26 02:48:02 +0200663 /* flush useless bits */
664 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
665 return 0;
666 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200667 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100668 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
669 return 0;
670
Willy Tarreau1c47f852006-07-09 08:22:27 +0200671 if (!*args[1]) {
672 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
673 file, linenum, args[0]);
674 return -1;
675 }
676
677 if (curproxy->monitor_uri != NULL)
678 free(curproxy->monitor_uri);
679
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100680 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200681 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100682 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200683 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
684
685 return 0;
686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200687 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
688 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
689 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
690 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
691 else {
692 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
693 return -1;
694 }
695 }
696 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
697 curproxy->state = PR_STSTOPPED;
698 }
699 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
700 curproxy->state = PR_STNEW;
701 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200702 else if (!strcmp(args[0], "acl")) { /* add an ACL */
703 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
704 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
705 file, linenum, args[1]);
706 return -1;
707 }
708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709 else if (!strcmp(args[0], "cookie")) { /* cookie name */
710 int cur_arg;
711 // if (curproxy == &defproxy) {
712 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
713 // return -1;
714 // }
715
Willy Tarreau977b8e42006-12-29 14:19:17 +0100716 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
717 return 0;
718
Willy Tarreaubaaee002006-06-26 02:48:02 +0200719 if (curproxy->cookie_name != NULL) {
720 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
721 // file, linenum);
722 // return 0;
723 free(curproxy->cookie_name);
724 }
725
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
728 file, linenum, args[0]);
729 return -1;
730 }
731 curproxy->cookie_name = strdup(args[1]);
732 curproxy->cookie_len = strlen(curproxy->cookie_name);
733
734 cur_arg = 2;
735 while (*(args[cur_arg])) {
736 if (!strcmp(args[cur_arg], "rewrite")) {
737 curproxy->options |= PR_O_COOK_RW;
738 }
739 else if (!strcmp(args[cur_arg], "indirect")) {
740 curproxy->options |= PR_O_COOK_IND;
741 }
742 else if (!strcmp(args[cur_arg], "insert")) {
743 curproxy->options |= PR_O_COOK_INS;
744 }
745 else if (!strcmp(args[cur_arg], "nocache")) {
746 curproxy->options |= PR_O_COOK_NOC;
747 }
748 else if (!strcmp(args[cur_arg], "postonly")) {
749 curproxy->options |= PR_O_COOK_POST;
750 }
751 else if (!strcmp(args[cur_arg], "prefix")) {
752 curproxy->options |= PR_O_COOK_PFX;
753 }
754 else {
755 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
756 file, linenum, args[0]);
757 return -1;
758 }
759 cur_arg++;
760 }
761 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
762 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
763 file, linenum);
764 return -1;
765 }
766
767 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
768 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
769 file, linenum);
770 return -1;
771 }
772 }/* end else if (!strcmp(args[0], "cookie")) */
773 else if (!strcmp(args[0], "appsession")) { /* cookie name */
774 // if (curproxy == &defproxy) {
775 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
776 // return -1;
777 // }
778
Willy Tarreau977b8e42006-12-29 14:19:17 +0100779 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
780 return 0;
781
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 if (curproxy->appsession_name != NULL) {
783 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
784 // file, linenum);
785 // return 0;
786 free(curproxy->appsession_name);
787 }
788
789 if (*(args[5]) == 0) {
790 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
791 file, linenum, args[0]);
792 return -1;
793 }
794 have_appsession = 1;
795 curproxy->appsession_name = strdup(args[1]);
796 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
797 curproxy->appsession_len = atoi(args[3]);
Willy Tarreauee991362007-05-14 14:37:50 +0200798 val = atoi(args[5]);
799 if (val > 0)
800 __tv_from_ms(&curproxy->appsession_timeout, val);
801 else
802 tv_eternity(&curproxy->appsession_timeout);
803
Willy Tarreau51041c72007-09-09 21:56:53 +0200804 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
805 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200806 return -1;
807 }
808 } /* Url App Session */
809 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100810 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
811 return 0;
812
Willy Tarreaubaaee002006-06-26 02:48:02 +0200813 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
814 // if (curproxy == &defproxy) {
815 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
816 // return -1;
817 // }
818
819 if (curproxy->capture_name != NULL) {
820 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
821 // file, linenum, args[0]);
822 // return 0;
823 free(curproxy->capture_name);
824 }
825
826 if (*(args[4]) == 0) {
827 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
828 file, linenum, args[0]);
829 return -1;
830 }
831 curproxy->capture_name = strdup(args[2]);
832 curproxy->capture_namelen = strlen(curproxy->capture_name);
833 curproxy->capture_len = atol(args[4]);
834 if (curproxy->capture_len >= CAPTURE_LEN) {
835 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
836 file, linenum, CAPTURE_LEN - 1);
837 curproxy->capture_len = CAPTURE_LEN - 1;
838 }
839 curproxy->to_log |= LW_COOKIE;
840 }
841 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
842 struct cap_hdr *hdr;
843
844 if (curproxy == &defproxy) {
845 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
846 return -1;
847 }
848
849 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
850 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
851 file, linenum, args[0], args[1]);
852 return -1;
853 }
854
855 hdr = calloc(sizeof(struct cap_hdr), 1);
856 hdr->next = curproxy->req_cap;
857 hdr->name = strdup(args[3]);
858 hdr->namelen = strlen(args[3]);
859 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200860 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200861 hdr->index = curproxy->nb_req_cap++;
862 curproxy->req_cap = hdr;
863 curproxy->to_log |= LW_REQHDR;
864 }
865 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
866 struct cap_hdr *hdr;
867
868 if (curproxy == &defproxy) {
869 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
870 return -1;
871 }
872
873 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
874 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
875 file, linenum, args[0], args[1]);
876 return -1;
877 }
878 hdr = calloc(sizeof(struct cap_hdr), 1);
879 hdr->next = curproxy->rsp_cap;
880 hdr->name = strdup(args[3]);
881 hdr->namelen = strlen(args[3]);
882 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200883 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884 hdr->index = curproxy->nb_rsp_cap++;
885 curproxy->rsp_cap = hdr;
886 curproxy->to_log |= LW_RSPHDR;
887 }
888 else {
889 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
890 file, linenum, args[0]);
891 return -1;
892 }
893 }
894 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200895 if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
897 return 0;
898 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100899 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
900 return 0;
901
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902 if (*(args[1]) == 0) {
903 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
904 file, linenum, args[0]);
905 return -1;
906 }
Willy Tarreauee991362007-05-14 14:37:50 +0200907 val = atoi(args[1]);
908 if (val > 0)
909 __tv_from_ms(&curproxy->contimeout, val);
910 else
911 tv_eternity(&curproxy->contimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200912 }
913 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200914 if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200915 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
916 file, linenum, args[0]);
917 return 0;
918 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100919 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
920 return 0;
921
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 if (*(args[1]) == 0) {
923 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
924 file, linenum, args[0]);
925 return -1;
926 }
Willy Tarreauee991362007-05-14 14:37:50 +0200927 val = atoi(args[1]);
928 if (val > 0)
929 __tv_from_ms(&curproxy->clitimeout, val);
930 else
931 tv_eternity(&curproxy->clitimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 }
933 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200934 if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
936 return 0;
937 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100938 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
939 return 0;
940
Willy Tarreaubaaee002006-06-26 02:48:02 +0200941 if (*(args[1]) == 0) {
942 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
943 file, linenum, args[0]);
944 return -1;
945 }
Willy Tarreauee991362007-05-14 14:37:50 +0200946 val = atoi(args[1]);
947 if (val > 0)
948 __tv_from_ms(&curproxy->srvtimeout, val);
949 else
950 tv_eternity(&curproxy->srvtimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 }
952 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100953 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
954 return 0;
955
Willy Tarreaubaaee002006-06-26 02:48:02 +0200956 if (*(args[1]) == 0) {
957 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
958 file, linenum, args[0]);
959 return -1;
960 }
961 curproxy->conn_retries = atol(args[1]);
962 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200963 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
964 int pol = ACL_COND_NONE;
965 struct acl_cond *cond;
966
967 if (!strcmp(args[1], "if"))
968 pol = ACL_COND_IF;
969 else if (!strcmp(args[1], "unless"))
970 pol = ACL_COND_UNLESS;
971
972 if (pol == ACL_COND_NONE) {
973 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
974 file, linenum, args[0]);
975 return -1;
976 }
977
978 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
979 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
980 file, linenum);
981 return -1;
982 }
983 LIST_ADDQ(&curproxy->block_cond, &cond->list);
984 }
Willy Tarreau55ea7572007-06-17 19:56:27 +0200985 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
986 int pol = ACL_COND_NONE;
987 struct acl_cond *cond;
988 struct switching_rule *rule;
989
990 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
991 return 0;
992
993 if (*(args[1]) == 0) {
994 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
995 return -1;
996 }
997
998 if (!strcmp(args[2], "if"))
999 pol = ACL_COND_IF;
1000 else if (!strcmp(args[2], "unless"))
1001 pol = ACL_COND_UNLESS;
1002
1003 if (pol == ACL_COND_NONE) {
1004 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1005 file, linenum, args[0]);
1006 return -1;
1007 }
1008
1009 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1010 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1011 file, linenum);
1012 return -1;
1013 }
1014
1015 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1016 rule->cond = cond;
1017 rule->be.name = strdup(args[1]);
1018 LIST_INIT(&rule->list);
1019 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1020 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001022 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1023 return 0;
1024
Willy Tarreaubaaee002006-06-26 02:48:02 +02001025 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1026 curproxy->uri_auth = NULL; /* we must detach from the default config */
1027
1028 if (*(args[1]) == 0) {
1029 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1030 return -1;
1031 } else if (!strcmp(args[1], "uri")) {
1032 if (*(args[2]) == 0) {
1033 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1034 return -1;
1035 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1036 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1037 return -1;
1038 }
1039 } else if (!strcmp(args[1], "realm")) {
1040 if (*(args[2]) == 0) {
1041 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1042 return -1;
1043 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1044 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1045 return -1;
1046 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001047 } else if (!strcmp(args[1], "refresh")) {
1048 int interval = atoi(args[2]);
1049
1050 if (interval < 0) {
1051 Alert("parsing [%s:%d] : 'refresh' needs a positive interval in seconds.\n", file, linenum);
1052 return -1;
1053 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1054 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1055 return -1;
1056 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001057 } else if (!strcmp(args[1], "auth")) {
1058 if (*(args[2]) == 0) {
1059 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1060 return -1;
1061 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1062 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1063 return -1;
1064 }
1065 } else if (!strcmp(args[1], "scope")) {
1066 if (*(args[2]) == 0) {
1067 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1068 return -1;
1069 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1070 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1071 return -1;
1072 }
1073 } else if (!strcmp(args[1], "enable")) {
1074 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1075 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1076 return -1;
1077 }
1078 } else {
1079 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'uri', 'realm', 'auth' or 'enable').\n",
1080 file, linenum, args[0]);
1081 return -1;
1082 }
1083 }
1084 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001085 int optnum;
1086
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 if (*(args[1]) == 0) {
1088 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
1089 return -1;
1090 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001091
1092 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1093 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1094 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1095 return 0;
1096 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001097 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001098 return 0;
1099 }
1100 }
1101
1102 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 /* generate a complete HTTP log */
1104 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1105 else if (!strcmp(args[1], "tcplog"))
1106 /* generate a detailed TCP log */
1107 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001108 else if (!strcmp(args[1], "tcpka")) {
1109 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001110 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1111 return 0;
1112
1113 if (curproxy->cap & PR_CAP_FE)
1114 curproxy->options |= PR_O_TCP_CLI_KA;
1115 if (curproxy->cap & PR_CAP_BE)
1116 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117 }
1118 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001119 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1120 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001121 /* use HTTP request to check servers' health */
1122 if (curproxy->check_req != NULL) {
1123 free(curproxy->check_req);
1124 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001125 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001126 curproxy->options &= ~PR_O_SMTP_CHK;
1127 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 if (!*args[2]) { /* no argument */
1129 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1130 curproxy->check_len = strlen(DEF_CHECK_REQ);
1131 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001132 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001133 curproxy->check_req = (char *)malloc(reqlen);
1134 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1135 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1136 } else { /* more arguments : METHOD URI [HTTP_VER] */
1137 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1138 if (*args[4])
1139 reqlen += strlen(args[4]);
1140 else
1141 reqlen += strlen("HTTP/1.0");
1142
1143 curproxy->check_req = (char *)malloc(reqlen);
1144 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1145 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1146 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001147 }
1148 else if (!strcmp(args[1], "ssl-hello-chk")) {
1149 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001150 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1151 return 0;
1152
Willy Tarreauf3c69202006-07-09 16:42:34 +02001153 if (curproxy->check_req != NULL) {
1154 free(curproxy->check_req);
1155 }
1156 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001157 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001158 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159 }
Willy Tarreau23677902007-05-08 23:50:35 +02001160 else if (!strcmp(args[1], "smtpchk")) {
1161 /* use SMTP request to check servers' health */
1162 if (curproxy->check_req != NULL) {
1163 free(curproxy->check_req);
1164 }
1165 curproxy->options &= ~PR_O_HTTP_CHK;
1166 curproxy->options &= ~PR_O_SSL3_CHK;
1167 curproxy->options |= PR_O_SMTP_CHK;
1168
1169 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1170 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1171 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1172 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1173 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1174 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1175 curproxy->check_req = (char *)malloc(reqlen);
1176 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1177 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1178 } else {
1179 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1180 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1181 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1182 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1183 }
1184 }
1185 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001186 else if (!strcmp(args[1], "forwardfor")) {
1187 /* insert x-forwarded-for field, but not for the
1188 * IP address listed as an except.
1189 */
1190 if (*(args[2])) {
1191 if (!strcmp(args[2], "except")) {
1192 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1193 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1194 file, linenum, args[0]);
1195 return -1;
1196 }
1197 /* flush useless bits */
1198 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1199 } else {
1200 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1201 file, linenum, args[0]);
1202 return -1;
1203 }
1204 }
1205 curproxy->options |= PR_O_FWDFOR;
1206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001207 else {
1208 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1209 return -1;
1210 }
1211 return 0;
1212 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001213 else if (!strcmp(args[0], "default_backend")) {
1214 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1215 return 0;
1216
1217 if (*(args[1]) == 0) {
1218 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1219 return -1;
1220 }
1221 if (curproxy->defbe.name)
1222 free(curproxy->defbe.name);
1223 curproxy->defbe.name = strdup(args[1]);
1224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001225 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001226 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1227 return 0;
1228
Willy Tarreaubaaee002006-06-26 02:48:02 +02001229 /* enable reconnections to dispatch */
1230 curproxy->options |= PR_O_REDISP;
1231 }
1232#ifdef TPROXY
1233 else if (!strcmp(args[0], "transparent")) {
1234 /* enable transparent proxy connections */
1235 curproxy->options |= PR_O_TRANSP;
1236 }
1237#endif
1238 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001239 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1240 return 0;
1241
Willy Tarreaubaaee002006-06-26 02:48:02 +02001242 if (*(args[1]) == 0) {
1243 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1244 return -1;
1245 }
1246 curproxy->maxconn = atol(args[1]);
1247 }
Willy Tarreau86034312006-12-29 00:10:33 +01001248 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001249 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1250 return 0;
1251
Willy Tarreau86034312006-12-29 00:10:33 +01001252 if (*(args[1]) == 0) {
1253 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1254 return -1;
1255 }
1256 curproxy->fullconn = atol(args[1]);
1257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1259 if (*(args[1]) == 0) {
1260 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1261 return -1;
1262 }
1263 curproxy->grace = atol(args[1]);
1264 }
1265 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1266 if (curproxy == &defproxy) {
1267 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1268 return -1;
1269 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001270 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1271 return 0;
1272
Willy Tarreaubaaee002006-06-26 02:48:02 +02001273 if (strchr(args[1], ':') == NULL) {
1274 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1275 return -1;
1276 }
1277 curproxy->dispatch_addr = *str2sa(args[1]);
1278 }
1279 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001280 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1281 return 0;
1282
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 if (*(args[1])) {
1284 if (!strcmp(args[1], "roundrobin")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001285 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001286 curproxy->options |= PR_O_BALANCE_RR;
1287 }
1288 else if (!strcmp(args[1], "source")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001289 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001290 curproxy->options |= PR_O_BALANCE_SH;
1291 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001292 else if (!strcmp(args[1], "uri")) {
1293 curproxy->options &= ~PR_O_BALANCE;
1294 curproxy->options |= PR_O_BALANCE_UH;
1295 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001296 else {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001297 Alert("parsing [%s:%d] : '%s' only supports 'roundrobin', 'source' and 'uri' options.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001298 return -1;
1299 }
1300 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001301 else {/* if no option is set, use round-robin by default */
1302 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001303 curproxy->options |= PR_O_BALANCE_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001304 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001305 }
1306 else if (!strcmp(args[0], "server")) { /* server address */
1307 int cur_arg;
1308 char *rport;
1309 char *raddr;
1310 short realport;
1311 int do_check;
1312
1313 if (curproxy == &defproxy) {
1314 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1315 return -1;
1316 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001317 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1318 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001319
1320 if (!*args[2]) {
1321 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1322 file, linenum, args[0]);
1323 return -1;
1324 }
1325 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1326 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1327 return -1;
1328 }
1329
1330 /* the servers are linked backwards first */
1331 newsrv->next = curproxy->srv;
1332 curproxy->srv = newsrv;
1333 newsrv->proxy = curproxy;
1334
1335 LIST_INIT(&newsrv->pendconns);
1336 do_check = 0;
1337 newsrv->state = SRV_RUNNING; /* early server setup */
1338 newsrv->id = strdup(args[1]);
1339
1340 /* several ways to check the port component :
1341 * - IP => port=+0, relative
1342 * - IP: => port=+0, relative
1343 * - IP:N => port=N, absolute
1344 * - IP:+N => port=+N, relative
1345 * - IP:-N => port=-N, relative
1346 */
1347 raddr = strdup(args[2]);
1348 rport = strchr(raddr, ':');
1349 if (rport) {
1350 *rport++ = 0;
1351 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001352 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 newsrv->state |= SRV_MAPPORTS;
1354 } else {
1355 realport = 0;
1356 newsrv->state |= SRV_MAPPORTS;
1357 }
1358
1359 newsrv->addr = *str2sa(raddr);
1360 newsrv->addr.sin_port = htons(realport);
1361 free(raddr);
1362
1363 newsrv->curfd = -1; /* no health-check in progress */
1364 newsrv->inter = DEF_CHKINTR;
1365 newsrv->rise = DEF_RISETIME;
1366 newsrv->fall = DEF_FALLTIME;
1367 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001368 newsrv->uweight = 1;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001369
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 cur_arg = 3;
1371 while (*args[cur_arg]) {
1372 if (!strcmp(args[cur_arg], "cookie")) {
1373 newsrv->cookie = strdup(args[cur_arg + 1]);
1374 newsrv->cklen = strlen(args[cur_arg + 1]);
1375 cur_arg += 2;
1376 }
1377 else if (!strcmp(args[cur_arg], "rise")) {
1378 newsrv->rise = atol(args[cur_arg + 1]);
1379 newsrv->health = newsrv->rise;
1380 cur_arg += 2;
1381 }
1382 else if (!strcmp(args[cur_arg], "fall")) {
1383 newsrv->fall = atol(args[cur_arg + 1]);
1384 cur_arg += 2;
1385 }
1386 else if (!strcmp(args[cur_arg], "inter")) {
1387 newsrv->inter = atol(args[cur_arg + 1]);
1388 cur_arg += 2;
1389 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001390 else if (!strcmp(args[cur_arg], "addr")) {
1391 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001392 cur_arg += 2;
1393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 else if (!strcmp(args[cur_arg], "port")) {
1395 newsrv->check_port = atol(args[cur_arg + 1]);
1396 cur_arg += 2;
1397 }
1398 else if (!strcmp(args[cur_arg], "backup")) {
1399 newsrv->state |= SRV_BACKUP;
1400 cur_arg ++;
1401 }
1402 else if (!strcmp(args[cur_arg], "weight")) {
1403 int w;
1404 w = atol(args[cur_arg + 1]);
1405 if (w < 1 || w > 256) {
1406 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1407 file, linenum, newsrv->id, w);
1408 return -1;
1409 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001410 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411 cur_arg += 2;
1412 }
1413 else if (!strcmp(args[cur_arg], "minconn")) {
1414 newsrv->minconn = atol(args[cur_arg + 1]);
1415 cur_arg += 2;
1416 }
1417 else if (!strcmp(args[cur_arg], "maxconn")) {
1418 newsrv->maxconn = atol(args[cur_arg + 1]);
1419 cur_arg += 2;
1420 }
1421 else if (!strcmp(args[cur_arg], "check")) {
1422 global.maxsock++;
1423 do_check = 1;
1424 cur_arg += 1;
1425 }
1426 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1427 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001428#ifdef CONFIG_HAP_CTTPROXY
1429 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1430 file, linenum, "source", "usesrc");
1431#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001432 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1433 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001434#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435 return -1;
1436 }
1437 newsrv->state |= SRV_BIND_SRC;
1438 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1439 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001440 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001441#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001442 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001443 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1444 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001445 return -1;
1446 }
1447 if (!*args[cur_arg + 1]) {
1448 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1449 file, linenum, "usesrc");
1450 return -1;
1451 }
1452 if (!strcmp(args[cur_arg + 1], "client")) {
1453 newsrv->state |= SRV_TPROXY_CLI;
1454 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1455 newsrv->state |= SRV_TPROXY_CIP;
1456 } else {
1457 newsrv->state |= SRV_TPROXY_ADDR;
1458 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1459 }
1460 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1461 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001462#else /* no CTTPROXY support */
1463 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1464 file, linenum, "usesrc");
1465 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001466#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001469#ifdef CONFIG_HAP_CTTPROXY
1470 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1471 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1472 file, linenum, "usesrc", "source");
1473 return -1;
1474 }
1475#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476 else {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001477 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 +02001478 file, linenum, newsrv->id);
1479 return -1;
1480 }
1481 }
1482
1483 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001484 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1485 newsrv->check_port = newsrv->check_addr.sin_port;
1486
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1488 newsrv->check_port = realport; /* by default */
1489 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001490 /* not yet valid, because no port was set on
1491 * the server either. We'll check if we have
1492 * a known port on the first listener.
1493 */
1494 struct listener *l;
1495 l = curproxy->listen;
1496 if (l) {
1497 int port;
1498 port = (l->addr.ss_family == AF_INET6)
1499 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1500 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1501 newsrv->check_port = port;
1502 }
1503 }
1504 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001505 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1506 file, linenum, newsrv->id);
1507 return -1;
1508 }
1509 newsrv->state |= SRV_CHECKED;
1510 }
1511
1512 if (newsrv->state & SRV_BACKUP)
1513 curproxy->srv_bck++;
1514 else
1515 curproxy->srv_act++;
1516 }
1517 else if (!strcmp(args[0], "log")) { /* syslog server address */
1518 struct sockaddr_in *sa;
1519 int facility;
1520
1521 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1522 curproxy->logfac1 = global.logfac1;
1523 curproxy->logsrv1 = global.logsrv1;
1524 curproxy->loglev1 = global.loglev1;
1525 curproxy->logfac2 = global.logfac2;
1526 curproxy->logsrv2 = global.logsrv2;
1527 curproxy->loglev2 = global.loglev2;
1528 }
1529 else if (*(args[1]) && *(args[2])) {
1530 int level;
1531
1532 facility = get_log_facility(args[2]);
1533 if (facility < 0) {
1534 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1535 exit(1);
1536 }
1537
1538 level = 7; /* max syslog level = debug */
1539 if (*(args[3])) {
1540 level = get_log_level(args[3]);
1541 if (level < 0) {
1542 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1543 exit(1);
1544 }
1545 }
1546
1547 sa = str2sa(args[1]);
1548 if (!sa->sin_port)
1549 sa->sin_port = htons(SYSLOG_PORT);
1550
1551 if (curproxy->logfac1 == -1) {
1552 curproxy->logsrv1 = *sa;
1553 curproxy->logfac1 = facility;
1554 curproxy->loglev1 = level;
1555 }
1556 else if (curproxy->logfac2 == -1) {
1557 curproxy->logsrv2 = *sa;
1558 curproxy->logfac2 = facility;
1559 curproxy->loglev2 = level;
1560 }
1561 else {
1562 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1563 return -1;
1564 }
1565 }
1566 else {
1567 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1568 file, linenum);
1569 return -1;
1570 }
1571 }
1572 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001573 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1574 return 0;
1575
Willy Tarreaubaaee002006-06-26 02:48:02 +02001576 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001577#ifdef CONFIG_HAP_CTTPROXY
1578 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1579 file, linenum, "source", "usesrc");
1580#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1582 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001583#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001584 return -1;
1585 }
1586
1587 curproxy->source_addr = *str2sa(args[1]);
1588 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001589 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001590#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001591 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1592 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1593 file, linenum, "usesrc");
1594 return -1;
1595 }
1596 if (!*args[3]) {
1597 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1598 file, linenum, "usesrc");
1599 return -1;
1600 }
1601
1602 if (!strcmp(args[3], "client")) {
1603 curproxy->options |= PR_O_TPXY_CLI;
1604 } else if (!strcmp(args[3], "clientip")) {
1605 curproxy->options |= PR_O_TPXY_CIP;
1606 } else {
1607 curproxy->options |= PR_O_TPXY_ADDR;
1608 curproxy->tproxy_addr = *str2sa(args[3]);
1609 }
1610 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001611#else /* no CTTPROXY support */
1612 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1613 file, linenum, "usesrc");
1614 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001615#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001616 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001617 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001618#ifdef CONFIG_HAP_CTTPROXY
1619 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1620 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1621 file, linenum, "usesrc", "source");
1622 return -1;
1623 }
1624#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1626 regex_t *preg;
1627 if (curproxy == &defproxy) {
1628 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1629 return -1;
1630 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001631 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1632 return 0;
1633
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634 if (*(args[1]) == 0 || *(args[2]) == 0) {
1635 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1636 file, linenum, args[0]);
1637 return -1;
1638 }
1639
1640 preg = calloc(1, sizeof(regex_t));
1641 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1642 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1643 return -1;
1644 }
1645
1646 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1647 if (err) {
1648 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1649 file, linenum, *err);
1650 return -1;
1651 }
1652 }
1653 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1654 regex_t *preg;
1655 if (curproxy == &defproxy) {
1656 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1657 return -1;
1658 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001659 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1660 return 0;
1661
Willy Tarreaubaaee002006-06-26 02:48:02 +02001662 if (*(args[1]) == 0) {
1663 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1664 return -1;
1665 }
1666
1667 preg = calloc(1, sizeof(regex_t));
1668 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1669 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1670 return -1;
1671 }
1672
1673 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1674 }
1675 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1676 regex_t *preg;
1677 if (curproxy == &defproxy) {
1678 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1679 return -1;
1680 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001681 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1682 return 0;
1683
Willy Tarreaubaaee002006-06-26 02:48:02 +02001684 if (*(args[1]) == 0) {
1685 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1686 return -1;
1687 }
1688
1689 preg = calloc(1, sizeof(regex_t));
1690 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1691 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1692 return -1;
1693 }
1694
1695 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1696 }
1697 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1698 regex_t *preg;
1699 if (curproxy == &defproxy) {
1700 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1701 return -1;
1702 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001703 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1704 return 0;
1705
Willy Tarreaubaaee002006-06-26 02:48:02 +02001706 if (*(args[1]) == 0) {
1707 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1708 return -1;
1709 }
1710
1711 preg = calloc(1, sizeof(regex_t));
1712 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1713 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1714 return -1;
1715 }
1716
1717 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1718 }
1719 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1720 regex_t *preg;
1721 if (curproxy == &defproxy) {
1722 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1723 return -1;
1724 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001725 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1726 return 0;
1727
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 if (*(args[1]) == 0) {
1729 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1730 return -1;
1731 }
1732
1733 preg = calloc(1, sizeof(regex_t));
1734 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1735 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1736 return -1;
1737 }
1738
1739 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1740 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001741 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1742 regex_t *preg;
1743 if (curproxy == &defproxy) {
1744 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1745 return -1;
1746 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001747 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1748 return 0;
1749
Willy Tarreaub8750a82006-09-03 09:56:00 +02001750 if (*(args[1]) == 0) {
1751 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1752 return -1;
1753 }
1754
1755 preg = calloc(1, sizeof(regex_t));
1756 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1757 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1758 return -1;
1759 }
1760
1761 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1762 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001763 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1764 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001765 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001766 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1767 return -1;
1768 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001769 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1770 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001771
Willy Tarreau977b8e42006-12-29 14:19:17 +01001772 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001773 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1774 file, linenum, args[0]);
1775 return -1;
1776 }
1777
1778 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001779 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001780 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1781 }
1782
1783 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1784 }
1785 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1786 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001787 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001788 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1789 return -1;
1790 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001791 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1792 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001793
Willy Tarreau977b8e42006-12-29 14:19:17 +01001794 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001795 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1796 file, linenum, args[0]);
1797 return -1;
1798 }
1799
1800 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001801 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001802 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1803 }
1804
1805 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1806 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001807 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1808 regex_t *preg;
1809 if (curproxy == &defproxy) {
1810 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1811 return -1;
1812 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001813 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1814 return 0;
1815
Willy Tarreaubaaee002006-06-26 02:48:02 +02001816 if (*(args[1]) == 0 || *(args[2]) == 0) {
1817 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1818 file, linenum, args[0]);
1819 return -1;
1820 }
1821
1822 preg = calloc(1, sizeof(regex_t));
1823 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1824 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1825 return -1;
1826 }
1827
1828 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1829 if (err) {
1830 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1831 file, linenum, *err);
1832 return -1;
1833 }
1834 }
1835 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1836 regex_t *preg;
1837 if (curproxy == &defproxy) {
1838 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1839 return -1;
1840 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001841 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1842 return 0;
1843
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844 if (*(args[1]) == 0) {
1845 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1846 return -1;
1847 }
1848
1849 preg = calloc(1, sizeof(regex_t));
1850 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1851 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1852 return -1;
1853 }
1854
1855 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1856 }
1857 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1858 regex_t *preg;
1859 if (curproxy == &defproxy) {
1860 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1861 return -1;
1862 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001863 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1864 return 0;
1865
Willy Tarreaubaaee002006-06-26 02:48:02 +02001866 if (*(args[1]) == 0) {
1867 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1868 return -1;
1869 }
1870
1871 preg = calloc(1, sizeof(regex_t));
1872 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1873 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1874 return -1;
1875 }
1876
1877 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1878 }
1879 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1880 regex_t *preg;
1881 if (curproxy == &defproxy) {
1882 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1883 return -1;
1884 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001885 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1886 return 0;
1887
Willy Tarreaubaaee002006-06-26 02:48:02 +02001888 if (*(args[1]) == 0) {
1889 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1890 return -1;
1891 }
1892
1893 preg = calloc(1, sizeof(regex_t));
1894 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1895 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1896 return -1;
1897 }
1898
1899 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1900 }
1901 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1902 regex_t *preg;
1903 if (curproxy == &defproxy) {
1904 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1905 return -1;
1906 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001907 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1908 return 0;
1909
Willy Tarreaubaaee002006-06-26 02:48:02 +02001910 if (*(args[1]) == 0) {
1911 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1912 return -1;
1913 }
1914
1915 preg = calloc(1, sizeof(regex_t));
1916 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1917 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1918 return -1;
1919 }
1920
1921 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1922 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001923 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1924 regex_t *preg;
1925 if (curproxy == &defproxy) {
1926 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1927 return -1;
1928 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001929 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1930 return 0;
1931
Willy Tarreaub8750a82006-09-03 09:56:00 +02001932 if (*(args[1]) == 0) {
1933 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1934 return -1;
1935 }
1936
1937 preg = calloc(1, sizeof(regex_t));
1938 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1939 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1940 return -1;
1941 }
1942
1943 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1946 if (curproxy == &defproxy) {
1947 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1948 return -1;
1949 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001950 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1951 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001952
1953 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
1954 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1955 return 0;
1956 }
1957
1958 if (*(args[1]) == 0) {
1959 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1960 return -1;
1961 }
1962
1963 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
1964 }
1965 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
1966 regex_t *preg;
1967
1968 if (*(args[1]) == 0 || *(args[2]) == 0) {
1969 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1970 file, linenum, args[0]);
1971 return -1;
1972 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001973 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1974 return 0;
1975
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976 preg = calloc(1, sizeof(regex_t));
1977 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1978 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1979 return -1;
1980 }
1981
1982 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1983 if (err) {
1984 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1985 file, linenum, *err);
1986 return -1;
1987 }
1988 }
1989 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
1990 regex_t *preg;
1991 if (curproxy == &defproxy) {
1992 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1993 return -1;
1994 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001995 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1996 return 0;
1997
Willy Tarreaubaaee002006-06-26 02:48:02 +02001998 if (*(args[1]) == 0) {
1999 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2000 return -1;
2001 }
2002
2003 preg = calloc(1, sizeof(regex_t));
2004 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2005 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2006 return -1;
2007 }
2008
2009 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2010 if (err) {
2011 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2012 file, linenum, *err);
2013 return -1;
2014 }
2015 }
2016 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2017 regex_t *preg;
2018 if (curproxy == &defproxy) {
2019 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2020 return -1;
2021 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002022 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2023 return 0;
2024
Willy Tarreaubaaee002006-06-26 02:48:02 +02002025 if (*(args[1]) == 0) {
2026 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2027 return -1;
2028 }
2029
2030 preg = calloc(1, sizeof(regex_t));
2031 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2032 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2033 return -1;
2034 }
2035
2036 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2037 if (err) {
2038 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2039 file, linenum, *err);
2040 return -1;
2041 }
2042 }
2043 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2044 regex_t *preg;
2045 if (curproxy == &defproxy) {
2046 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2047 return -1;
2048 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002049 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2050 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051
2052 if (*(args[1]) == 0 || *(args[2]) == 0) {
2053 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2054 file, linenum, args[0]);
2055 return -1;
2056 }
2057
2058 preg = calloc(1, sizeof(regex_t));
2059 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2060 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2061 return -1;
2062 }
2063
2064 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2065 if (err) {
2066 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2067 file, linenum, *err);
2068 return -1;
2069 }
2070 }
2071 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2072 regex_t *preg;
2073 if (curproxy == &defproxy) {
2074 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2075 return -1;
2076 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002077 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2078 return 0;
2079
Willy Tarreaubaaee002006-06-26 02:48:02 +02002080 if (*(args[1]) == 0) {
2081 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2082 return -1;
2083 }
2084
2085 preg = calloc(1, sizeof(regex_t));
2086 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2087 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2088 return -1;
2089 }
2090
2091 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2092 if (err) {
2093 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2094 file, linenum, *err);
2095 return -1;
2096 }
2097 }
2098 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2099 regex_t *preg;
2100 if (curproxy == &defproxy) {
2101 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2102 return -1;
2103 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002104 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2105 return 0;
2106
Willy Tarreaubaaee002006-06-26 02:48:02 +02002107 if (*(args[1]) == 0) {
2108 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2109 return -1;
2110 }
2111
2112 preg = calloc(1, sizeof(regex_t));
2113 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2114 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2115 return -1;
2116 }
2117
2118 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2119 if (err) {
2120 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2121 file, linenum, *err);
2122 return -1;
2123 }
2124 }
2125 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2126 if (curproxy == &defproxy) {
2127 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2128 return -1;
2129 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002130 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2131 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002132
2133 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2134 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2135 return 0;
2136 }
2137
2138 if (*(args[1]) == 0) {
2139 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2140 return -1;
2141 }
2142
2143 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2144 }
2145 else if (!strcmp(args[0], "errorloc") ||
2146 !strcmp(args[0], "errorloc302") ||
2147 !strcmp(args[0], "errorloc303")) { /* error location */
2148 int errnum, errlen;
2149 char *err;
2150
Willy Tarreau977b8e42006-12-29 14:19:17 +01002151 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2152 return 0;
2153
Willy Tarreaubaaee002006-06-26 02:48:02 +02002154 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002155 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156 return -1;
2157 }
2158
2159 errnum = atol(args[1]);
2160 if (!strcmp(args[0], "errorloc303")) {
2161 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2162 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2163 } else {
2164 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2165 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2166 }
2167
Willy Tarreau0f772532006-12-23 20:51:41 +01002168 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2169 if (http_err_codes[rc] == errnum) {
2170 if (curproxy->errmsg[rc].str)
2171 free(curproxy->errmsg[rc].str);
2172 curproxy->errmsg[rc].str = err;
2173 curproxy->errmsg[rc].len = errlen;
2174 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002175 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002176 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002177
2178 if (rc >= HTTP_ERR_SIZE) {
2179 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2180 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002181 free(err);
2182 }
2183 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002184 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2185 int errnum, errlen, fd;
2186 char *err;
2187 struct stat stat;
2188
2189 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2190 return 0;
2191
2192 if (*(args[2]) == 0) {
2193 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2194 return -1;
2195 }
2196
2197 fd = open(args[2], O_RDONLY);
2198 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2199 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2200 file, linenum, args[2], args[1]);
2201 if (fd >= 0)
2202 close(fd);
2203 return -1;
2204 }
2205
2206 if (stat.st_size <= BUFSIZE) {
2207 errlen = stat.st_size;
2208 } else {
2209 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2210 file, linenum, args[2], BUFSIZE);
2211 errlen = BUFSIZE;
2212 }
2213
2214 err = malloc(errlen); /* malloc() must succeed during parsing */
2215 errnum = read(fd, err, errlen);
2216 if (errnum != errlen) {
2217 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2218 file, linenum, args[2], args[1]);
2219 close(fd);
2220 free(err);
2221 return -1;
2222 }
2223 close(fd);
2224
2225 errnum = atol(args[1]);
2226 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2227 if (http_err_codes[rc] == errnum) {
2228 if (curproxy->errmsg[rc].str)
2229 free(curproxy->errmsg[rc].str);
2230 curproxy->errmsg[rc].str = err;
2231 curproxy->errmsg[rc].len = errlen;
2232 break;
2233 }
2234 }
2235
2236 if (rc >= HTTP_ERR_SIZE) {
2237 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2238 file, linenum, errnum);
2239 free(err);
2240 }
2241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 else {
2243 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2244 return -1;
2245 }
2246 return 0;
2247}
2248
2249
2250/*
2251 * This function reads and parses the configuration file given in the argument.
2252 * returns 0 if OK, -1 if error.
2253 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002254int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255{
2256 char thisline[256];
2257 char *line;
2258 FILE *f;
2259 int linenum = 0;
2260 char *end;
Willy Tarreau540abe42007-05-02 20:50:16 +02002261 char *args[MAX_LINE_ARGS + 1];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002262 int arg;
2263 int cfgerr = 0;
Willy Tarreau80587432006-12-24 17:47:20 +01002264 int nbchk, mininter;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 int confsect = CFG_NONE;
2266
2267 struct proxy *curproxy = NULL;
2268 struct server *newsrv = NULL;
2269
2270 if ((f=fopen(file,"r")) == NULL)
2271 return -1;
2272
2273 init_default_instance();
2274
2275 while (fgets(line = thisline, sizeof(thisline), f) != NULL) {
2276 linenum++;
2277
2278 end = line + strlen(line);
2279
2280 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002281 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 line++;
2283
2284 arg = 0;
2285 args[arg] = line;
2286
2287 while (*line && arg < MAX_LINE_ARGS) {
2288 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2289 * C equivalent value. Other combinations left unchanged (eg: \1).
2290 */
2291 if (*line == '\\') {
2292 int skip = 0;
2293 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2294 *line = line[1];
2295 skip = 1;
2296 }
2297 else if (line[1] == 'r') {
2298 *line = '\r';
2299 skip = 1;
2300 }
2301 else if (line[1] == 'n') {
2302 *line = '\n';
2303 skip = 1;
2304 }
2305 else if (line[1] == 't') {
2306 *line = '\t';
2307 skip = 1;
2308 }
2309 else if (line[1] == 'x') {
2310 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2311 unsigned char hex1, hex2;
2312 hex1 = toupper(line[2]) - '0';
2313 hex2 = toupper(line[3]) - '0';
2314 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2315 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2316 *line = (hex1<<4) + hex2;
2317 skip = 3;
2318 }
2319 else {
2320 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2321 return -1;
2322 }
2323 }
2324 if (skip) {
2325 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2326 end -= skip;
2327 }
2328 line++;
2329 }
2330 else if (*line == '#' || *line == '\n' || *line == '\r') {
2331 /* end of string, end of loop */
2332 *line = 0;
2333 break;
2334 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002335 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002336 /* a non-escaped space is an argument separator */
2337 *line++ = 0;
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002338 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 line++;
2340 args[++arg] = line;
2341 }
2342 else {
2343 line++;
2344 }
2345 }
2346
2347 /* empty line */
2348 if (!**args)
2349 continue;
2350
Willy Tarreau540abe42007-05-02 20:50:16 +02002351 /* zero out remaining args and ensure that at least one entry
2352 * is zeroed out.
2353 */
2354 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002355 args[arg] = line;
2356 }
2357
Willy Tarreau977b8e42006-12-29 14:19:17 +01002358 if (!strcmp(args[0], "listen") ||
2359 !strcmp(args[0], "frontend") ||
2360 !strcmp(args[0], "backend") ||
2361 !strcmp(args[0], "ruleset") ||
2362 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 confsect = CFG_LISTEN;
2364 else if (!strcmp(args[0], "global")) /* global config */
2365 confsect = CFG_GLOBAL;
2366 /* else it's a section keyword */
2367
2368 switch (confsect) {
2369 case CFG_LISTEN:
2370 if (cfg_parse_listen(file, linenum, args) < 0)
2371 return -1;
2372 break;
2373 case CFG_GLOBAL:
2374 if (cfg_parse_global(file, linenum, args) < 0)
2375 return -1;
2376 break;
2377 default:
2378 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2379 return -1;
2380 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 }
2382 fclose(f);
2383
2384 /*
2385 * Now, check for the integrity of all that we have collected.
2386 */
2387
2388 /* will be needed further to delay some tasks */
2389 tv_now(&now);
2390
2391 if ((curproxy = proxy) == NULL) {
2392 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2393 file);
2394 return -1;
2395 }
2396
2397 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002398 struct switching_rule *rule;
2399
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 if (curproxy->state == PR_STSTOPPED) {
2401 curproxy = curproxy->next;
2402 continue;
2403 }
2404
Willy Tarreau977b8e42006-12-29 14:19:17 +01002405 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2406 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 +01002407 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 cfgerr++;
2409 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002410 else if (curproxy->cap & PR_CAP_BE &&
2411 ((curproxy->mode != PR_MODE_HEALTH) &&
2412 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
2413 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2414 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 +01002415 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002416 cfgerr++;
2417 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002418
2419 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002421 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002422 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423 cfgerr++;
2424 }
2425#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2426 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002427 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002428 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 cfgerr++;
2430 }
2431#endif
2432 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002433 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002434 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 }
2436 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002437
2438 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002439 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002440 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002441 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002444 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002445 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446 }
2447 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002448 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002449 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002451 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002452 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002453 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002454 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002455 if (curproxy->options & PR_O_BALANCE_UH) {
2456 curproxy->options &= ~PR_O_BALANCE;
2457 curproxy->options |= PR_O_BALANCE_RR;
2458
2459 Warning("parsing %s : URI hash will be ignored for %s '%s'. Falling back to round robin.\n",
2460 file, proxy_type_str(curproxy), curproxy->id);
2461 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002462 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002463
2464 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2465 if ((newsrv = curproxy->srv) != NULL) {
2466 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2467 file, proxy_type_str(curproxy), curproxy->id);
2468 }
2469 }
2470
2471 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2473 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2474 file, curproxy->id);
2475 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002476 }
2477 }
2478
2479 /* if a default backend was specified, let's find it */
2480 if (curproxy->defbe.name) {
2481 struct proxy *target;
2482
2483 for (target = proxy; target != NULL; target = target->next) {
2484 if (strcmp(target->id, curproxy->defbe.name) == 0)
2485 break;
2486 }
2487 if (target == NULL) {
2488 Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n",
2489 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2490 cfgerr++;
2491 } else if (target == curproxy) {
2492 Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
2493 cfgerr++;
2494 } else if (!(target->cap & PR_CAP_BE)) {
2495 Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n",
2496 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2497 cfgerr++;
2498 } else if (target->mode != curproxy->mode) {
2499 Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
2500 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2501 cfgerr++;
2502 } else {
2503 free(curproxy->defbe.name);
2504 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002505 }
2506 }
2507
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002508 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002509 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2510 /* map jump target for ACT_SETBE in req_rep chain */
2511 struct hdr_exp *exp;
2512 struct proxy *target;
2513 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
2514 if (exp->action != ACT_SETBE)
2515 continue;
2516 for (target = proxy; target != NULL; target = target->next) {
2517 if (strcmp(target->id, exp->replace) == 0)
2518 break;
2519 }
2520 if (target == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002521 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002522 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaua496b602006-12-17 23:15:24 +01002523 cfgerr++;
2524 } else if (target == curproxy) {
2525 Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
2526 cfgerr++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002527 } else if (!(target->cap & PR_CAP_BE)) {
2528 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002529 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002530 cfgerr++;
2531 } else if (target->mode != PR_MODE_HTTP) {
2532 Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002533 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002534 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002535 } else {
2536 free((void *)exp->replace);
2537 exp->replace = (const char *)target;
2538 }
2539 }
2540 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002541
2542 /* find the target proxy for 'use_backend' rules */
2543 list_for_each_entry(rule, &curproxy->switching_rules, list) {
2544 /* map jump target for ACT_SETBE in req_rep chain */
2545 struct proxy *target;
2546
2547 for (target = proxy; target != NULL; target = target->next) {
2548 if (strcmp(target->id, rule->be.name) == 0)
2549 break;
2550 }
2551
2552 if (target == NULL) {
2553 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
2554 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2555 cfgerr++;
2556 } else if (target == curproxy) {
2557 Alert("parsing %s : loop detected for backend %s !\n", file, rule->be.name);
2558 cfgerr++;
2559 } else if (!(target->cap & PR_CAP_BE)) {
2560 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
2561 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2562 cfgerr++;
2563 } else if (target->mode != curproxy->mode) {
2564 Alert("parsing %s : backend '%s' referenced in %s '%s' is of different mode !\n",
2565 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2566 cfgerr++;
2567 } else {
2568 free((void *)rule->be.name);
2569 rule->be.backend = target;
2570 }
2571 }
2572
Willy Tarreau2738a142006-07-08 17:28:09 +02002573 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002574 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2575 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2576 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002577 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002578 " | While not properly invalid, you will certainly encounter various problems\n"
2579 " | with such a configuration. To fix this, please ensure that all following\n"
2580 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002581 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002582 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002583
2584 if (curproxy->options & PR_O_SSL3_CHK) {
2585 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2586 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2587 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2588 }
2589
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002590 /* The small pools required for the capture lists */
2591 if (curproxy->nb_req_cap)
2592 curproxy->req_cap_pool = create_pool("ptrcap",
2593 curproxy->nb_req_cap * sizeof(char *),
2594 MEM_F_SHARED);
2595 if (curproxy->nb_rsp_cap)
2596 curproxy->rsp_cap_pool = create_pool("ptrcap",
2597 curproxy->nb_rsp_cap * sizeof(char *),
2598 MEM_F_SHARED);
2599
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002600 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2601 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2602 MEM_F_SHARED);
2603
Willy Tarreau86034312006-12-29 00:10:33 +01002604 /* for backwards compatibility with "listen" instances, if
2605 * fullconn is not set but maxconn is set, then maxconn
2606 * is used.
2607 */
2608 if (!curproxy->fullconn)
2609 curproxy->fullconn = curproxy->maxconn;
2610
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 /* first, we will invert the servers list order */
2612 newsrv = NULL;
2613 while (curproxy->srv) {
2614 struct server *next;
2615
2616 next = curproxy->srv->next;
2617 curproxy->srv->next = newsrv;
2618 newsrv = curproxy->srv;
2619 if (!next)
2620 break;
2621 curproxy->srv = next;
2622 }
2623
2624 /* now, newsrv == curproxy->srv */
2625 if (newsrv) {
2626 struct server *srv;
2627 int pgcd;
2628 int act, bck;
2629
2630 /* We will factor the weights to reduce the table,
2631 * using Euclide's largest common divisor algorithm
2632 */
Willy Tarreau417fae02007-03-25 21:16:40 +02002633 pgcd = newsrv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002634 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2635 int t, w;
2636
Willy Tarreau417fae02007-03-25 21:16:40 +02002637 w = srv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002638 while (w) {
2639 t = pgcd % w;
2640 pgcd = w;
2641 w = t;
2642 }
2643 }
2644
2645 act = bck = 0;
2646 for (srv = newsrv; srv; srv = srv->next) {
Willy Tarreau417fae02007-03-25 21:16:40 +02002647 srv->eweight = srv->uweight / pgcd;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002648 if (srv->state & SRV_BACKUP)
Willy Tarreau417fae02007-03-25 21:16:40 +02002649 bck += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002650 else
Willy Tarreau417fae02007-03-25 21:16:40 +02002651 act += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002652 }
2653
2654 /* this is the largest map we will ever need for this servers list */
2655 if (act < bck)
2656 act = bck;
2657
2658 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2659 /* recounts servers and their weights */
Willy Tarreau5af3a692007-07-24 23:32:33 +02002660 curproxy->map_state = PR_MAP_RECALC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002661 recount_servers(curproxy);
2662 recalc_server_map(curproxy);
2663 }
2664
2665 if (curproxy->options & PR_O_LOGASAP)
2666 curproxy->to_log &= ~LW_BYTES;
2667
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668 /*
2669 * If this server supports a maxconn parameter, it needs a dedicated
2670 * tasks to fill the emptied slots when a connection leaves.
2671 */
2672 newsrv = curproxy->srv;
2673 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002674 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002675 /* Only 'minconn' was specified, or it was higher than or equal
2676 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2677 * this will avoid further useless expensive computations.
2678 */
2679 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002680 } else if (newsrv->maxconn && !newsrv->minconn) {
2681 /* minconn was not specified, so we set it to maxconn */
2682 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002683 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2684 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002685 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002686 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 }
2688
2689 if (newsrv->maxconn > 0) {
2690 struct task *t;
2691
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002692 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002693 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2694 return -1;
2695 }
2696
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002697 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002698 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 t->state = TASK_IDLE;
2700 t->process = process_srv_queue;
2701 t->context = newsrv;
2702 newsrv->queue_mgt = t;
2703
2704 /* never run it unless specifically woken up */
2705 tv_eternity(&t->expire);
2706 task_queue(t);
2707 }
2708 newsrv = newsrv->next;
2709 }
2710
2711 /* now we'll start this proxy's health checks if any */
2712 /* 1- count the checkers to run simultaneously */
2713 nbchk = 0;
2714 mininter = 0;
2715 newsrv = curproxy->srv;
2716 while (newsrv != NULL) {
2717 if (newsrv->state & SRV_CHECKED) {
2718 if (!mininter || mininter > newsrv->inter)
2719 mininter = newsrv->inter;
2720 nbchk++;
2721 }
2722 newsrv = newsrv->next;
2723 }
2724
2725 /* 2- start them as far as possible from each others while respecting
2726 * their own intervals. For this, we will start them after their own
2727 * interval added to the min interval divided by the number of servers,
2728 * weighted by the server's position in the list.
2729 */
2730 if (nbchk > 0) {
2731 struct task *t;
2732 int srvpos;
2733
2734 newsrv = curproxy->srv;
2735 srvpos = 0;
2736 while (newsrv != NULL) {
2737 /* should this server be checked ? */
2738 if (newsrv->state & SRV_CHECKED) {
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002739 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2741 return -1;
2742 }
2743
Willy Tarreau964c9362007-01-07 00:38:00 +01002744 t->wq = NULL;
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002745 t->qlist.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002746 t->state = TASK_IDLE;
2747 t->process = process_chk;
2748 t->context = newsrv;
2749
2750 /* check this every ms */
Willy Tarreau42aae5c2007-04-29 17:43:56 +02002751 tv_ms_add(&t->expire, &now,
2752 newsrv->inter + mininter * srvpos / nbchk);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 task_queue(t);
2754 //task_wakeup(&rq, t);
2755 srvpos++;
2756 }
2757 newsrv = newsrv->next;
2758 }
2759 }
2760
2761 curproxy = curproxy->next;
2762 }
2763 if (cfgerr > 0) {
2764 Alert("Errors found in configuration file, aborting.\n");
2765 return -1;
2766 }
2767 else
2768 return 0;
2769}
2770
2771
2772
2773/*
2774 * Local variables:
2775 * c-indent-level: 8
2776 * c-basic-offset: 8
2777 * End:
2778 */