blob: d9e01a7a4e2aca1ac8441da36d1f42cd643436a9 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau0b4ed902007-03-26 00:18:40 +02004 * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
27#include <common/config.h>
28#include <common/memory.h>
29#include <common/standard.h>
30#include <common/time.h>
31#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020032
33#include <types/capture.h>
34#include <types/global.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010035#include <types/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <types/polling.h>
37#include <types/proxy.h>
38#include <types/queue.h>
39
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010045#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020046#include <proto/log.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010047#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <proto/server.h>
49#include <proto/task.h>
50
51
Willy Tarreauf3c69202006-07-09 16:42:34 +020052/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
53 * ssl-hello-chk option to ensure that the remote server speaks SSL.
54 *
55 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
56 */
57const char sslv3_client_hello_pkt[] = {
58 "\x16" /* ContentType : 0x16 = Hanshake */
59 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
60 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
61 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
62 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
63 "\x03\x00" /* Hello Version : 0x0300 = v3 */
64 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
65 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
66 "\x00" /* Session ID length : empty (no session ID) */
67 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
68 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
69 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
70 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
71 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
72 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
73 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
74 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
75 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
76 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
77 "\x00\x38" "\x00\x39" "\x00\x3A"
78 "\x01" /* Compression Length : 0x01 = 1 byte for types */
79 "\x00" /* Compression Type : 0x00 = NULL compression */
80};
81
Willy Tarreau13943ab2006-12-31 00:24:10 +010082/* some of the most common options which are also the easiest to handle */
83static const struct {
84 const char *name;
85 unsigned int val;
86 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010087 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010088} cfg_opts[] =
89{
90#ifdef TPROXY
91 { "transparent", PR_O_TRANSP, PR_CAP_FE },
92#endif
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
94 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010095 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
Alexandre Cassen87ea5482007-10-11 20:48:58 +020096 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010097 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
98 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
99 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
100 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
101 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
102 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
103 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
104 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
105 { "forceclose", PR_O_FORCE_CLO | PR_O_HTTP_CLOSE, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100106#ifdef CONFIG_HAP_TCPSPLICE
107 { "tcpsplice", PR_O_TCPSPLICE , PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
108#endif
109
Willy Tarreau13943ab2006-12-31 00:24:10 +0100110 { NULL, 0, 0 }
111};
112
Willy Tarreaubaaee002006-06-26 02:48:02 +0200113
114static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
115int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
116int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
117
118/*
119 * converts <str> to a list of listeners which are dynamically allocated.
120 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
121 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
122 * - <port> is a numerical port from 1 to 65535 ;
123 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
124 * This can be repeated as many times as necessary, separated by a coma.
125 * The <tail> argument is a pointer to a current list which should be appended
126 * to the tail of the new list. The pointer to the new list is returned.
127 */
128static struct listener *str2listener(char *str, struct listener *tail)
129{
130 struct listener *l;
131 char *c, *next, *range, *dupstr;
132 int port, end;
133
134 next = dupstr = strdup(str);
135
136 while (next && *next) {
137 struct sockaddr_storage ss;
138
139 str = next;
140 /* 1) look for the end of the first address */
141 if ((next = strrchr(str, ',')) != NULL) {
142 *next++ = 0;
143 }
144
145 /* 2) look for the addr/port delimiter, it's the last colon. */
146 if ((range = strrchr(str, ':')) == NULL) {
147 Alert("Missing port number: '%s'\n", str);
148 goto fail;
149 }
150
151 *range++ = 0;
152
153 if (strrchr(str, ':') != NULL) {
154 /* IPv6 address contains ':' */
155 memset(&ss, 0, sizeof(ss));
156 ss.ss_family = AF_INET6;
157
158 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
159 Alert("Invalid server address: '%s'\n", str);
160 goto fail;
161 }
162 }
163 else {
164 memset(&ss, 0, sizeof(ss));
165 ss.ss_family = AF_INET;
166
167 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
168 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
169 }
170 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
171 struct hostent *he;
172
173 if ((he = gethostbyname(str)) == NULL) {
174 Alert("Invalid server name: '%s'\n", str);
175 goto fail;
176 }
177 else
178 ((struct sockaddr_in *)&ss)->sin_addr =
179 *(struct in_addr *) *(he->h_addr_list);
180 }
181 }
182
183 /* 3) look for the port-end delimiter */
184 if ((c = strchr(range, '-')) != NULL) {
185 *c++ = 0;
186 end = atol(c);
187 }
188 else {
189 end = atol(range);
190 }
191
192 port = atol(range);
193
194 if (port < 1 || port > 65535) {
195 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
196 goto fail;
197 }
198
199 if (end < 1 || end > 65535) {
200 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
201 goto fail;
202 }
203
204 for (; port <= end; port++) {
205 l = (struct listener *)calloc(1, sizeof(struct listener));
206 l->next = tail;
207 tail = l;
208
209 l->fd = -1;
210 l->addr = ss;
211 if (ss.ss_family == AF_INET6)
212 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
213 else
214 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
215
216 } /* end for(port) */
217 } /* end while(next) */
218 free(dupstr);
219 return tail;
220 fail:
221 free(dupstr);
222 return NULL;
223}
224
Willy Tarreau977b8e42006-12-29 14:19:17 +0100225/*
226 * Sends a warning if proxy <proxy> does not have at least one of the
227 * capabilities in <cap>. An optionnal <hint> may be added at the end
228 * of the warning to help the user. Returns 1 if a warning was emitted
229 * or 0 if the condition is valid.
230 */
231int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
232{
233 char *msg;
234
235 switch (cap) {
236 case PR_CAP_BE: msg = "no backend"; break;
237 case PR_CAP_FE: msg = "no frontend"; break;
238 case PR_CAP_RS: msg = "no ruleset"; break;
239 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
240 default: msg = "not enough"; break;
241 }
242
243 if (!(proxy->cap & cap)) {
244 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100245 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100246 return 1;
247 }
248 return 0;
249}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
251/*
252 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
253 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200254int cfg_parse_global(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255{
256
257 if (!strcmp(args[0], "global")) { /* new section */
258 /* no option, nothing special to do */
259 return 0;
260 }
261 else if (!strcmp(args[0], "daemon")) {
262 global.mode |= MODE_DAEMON;
263 }
264 else if (!strcmp(args[0], "debug")) {
265 global.mode |= MODE_DEBUG;
266 }
267 else if (!strcmp(args[0], "noepoll")) {
268 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
269 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200270 else if (!strcmp(args[0], "nosepoll")) {
271 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
272 }
273 else if (!strcmp(args[0], "nokqueue")) {
274 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200276 else if (!strcmp(args[0], "nopoll")) {
277 cfg_polling_mechanism &= ~POLL_USE_POLL;
278 }
279 else if (!strcmp(args[0], "quiet")) {
280 global.mode |= MODE_QUIET;
281 }
282 else if (!strcmp(args[0], "stats")) {
Willy Tarreaufbee7132007-10-18 13:53:22 +0200283 memcpy(trash, "error near 'stats'", 19);
284 if (stats_parse_global((const char **)args + 1, trash, sizeof(trash)) < 0) {
285 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
286 return -1;
287 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200289 else if (!strcmp(args[0], "tune.maxpollevents")) {
290 if (global.tune.maxpollevents != 0) {
291 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
292 return 0;
293 }
294 if (*(args[1]) == 0) {
295 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
296 return -1;
297 }
298 global.tune.maxpollevents = atol(args[1]);
299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300 else if (!strcmp(args[0], "uid")) {
301 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200302 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200303 return 0;
304 }
305 if (*(args[1]) == 0) {
306 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
307 return -1;
308 }
309 global.uid = atol(args[1]);
310 }
311 else if (!strcmp(args[0], "gid")) {
312 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200313 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200314 return 0;
315 }
316 if (*(args[1]) == 0) {
317 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
318 return -1;
319 }
320 global.gid = atol(args[1]);
321 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200322 /* user/group name handling */
323 else if (!strcmp(args[0], "user")) {
324 struct passwd *ha_user;
325 if (global.uid != 0) {
326 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
327 return 0;
328 }
329 errno = 0;
330 ha_user = getpwnam(args[1]);
331 if (ha_user != NULL) {
332 global.uid = (int)ha_user->pw_uid;
333 }
334 else {
335 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
336 exit(1);
337 }
338 }
339 else if (!strcmp(args[0], "group")) {
340 struct group *ha_group;
341 if (global.gid != 0) {
342 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
343 return 0;
344 }
345 errno = 0;
346 ha_group = getgrnam(args[1]);
347 if (ha_group != NULL) {
348 global.gid = (int)ha_group->gr_gid;
349 }
350 else {
351 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
352 exit(1);
353 }
354 }
355 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200356 else if (!strcmp(args[0], "nbproc")) {
357 if (global.nbproc != 0) {
358 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
359 return 0;
360 }
361 if (*(args[1]) == 0) {
362 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
363 return -1;
364 }
365 global.nbproc = atol(args[1]);
366 }
367 else if (!strcmp(args[0], "maxconn")) {
368 if (global.maxconn != 0) {
369 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
370 return 0;
371 }
372 if (*(args[1]) == 0) {
373 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
374 return -1;
375 }
376 global.maxconn = atol(args[1]);
377#ifdef SYSTEM_MAXCONN
378 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
379 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);
380 global.maxconn = DEFAULT_MAXCONN;
381 }
382#endif /* SYSTEM_MAXCONN */
383 }
384 else if (!strcmp(args[0], "ulimit-n")) {
385 if (global.rlimit_nofile != 0) {
386 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
387 return 0;
388 }
389 if (*(args[1]) == 0) {
390 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
391 return -1;
392 }
393 global.rlimit_nofile = atol(args[1]);
394 }
395 else if (!strcmp(args[0], "chroot")) {
396 if (global.chroot != NULL) {
397 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
398 return 0;
399 }
400 if (*(args[1]) == 0) {
401 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
402 return -1;
403 }
404 global.chroot = strdup(args[1]);
405 }
406 else if (!strcmp(args[0], "pidfile")) {
407 if (global.pidfile != NULL) {
408 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
409 return 0;
410 }
411 if (*(args[1]) == 0) {
412 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
413 return -1;
414 }
415 global.pidfile = strdup(args[1]);
416 }
417 else if (!strcmp(args[0], "log")) { /* syslog server address */
418 struct sockaddr_in *sa;
419 int facility, level;
420
421 if (*(args[1]) == 0 || *(args[2]) == 0) {
422 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
423 return -1;
424 }
425
426 facility = get_log_facility(args[2]);
427 if (facility < 0) {
428 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
429 exit(1);
430 }
431
432 level = 7; /* max syslog level = debug */
433 if (*(args[3])) {
434 level = get_log_level(args[3]);
435 if (level < 0) {
436 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
437 exit(1);
438 }
439 }
440
441 sa = str2sa(args[1]);
442 if (!sa->sin_port)
443 sa->sin_port = htons(SYSLOG_PORT);
444
445 if (global.logfac1 == -1) {
446 global.logsrv1 = *sa;
447 global.logfac1 = facility;
448 global.loglev1 = level;
449 }
450 else if (global.logfac2 == -1) {
451 global.logsrv2 = *sa;
452 global.logfac2 = facility;
453 global.loglev2 = level;
454 }
455 else {
456 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
457 return -1;
458 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200459 }
460 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
461 if (global.spread_checks != 0) {
462 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
463 return 0;
464 }
465 if (*(args[1]) == 0) {
466 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
467 return -1;
468 }
469 global.spread_checks = atol(args[1]);
470 if (global.spread_checks < 0 || global.spread_checks > 50) {
471 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
472 return -1;
473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200474 }
475 else {
476 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
477 return -1;
478 }
479 return 0;
480}
481
482
483static void init_default_instance()
484{
485 memset(&defproxy, 0, sizeof(defproxy));
486 defproxy.mode = PR_MODE_TCP;
487 defproxy.state = PR_STNEW;
488 defproxy.maxconn = cfg_maxpconn;
489 defproxy.conn_retries = CONN_RETRIES;
490 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaufdd0f552007-09-17 11:12:40 +0200491 tv_eternity(&defproxy.clitimeout);
492 tv_eternity(&defproxy.contimeout);
493 tv_eternity(&defproxy.srvtimeout);
494 tv_eternity(&defproxy.appsession_timeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200495}
496
497/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100498 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
499 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200500 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200501int cfg_parse_listen(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200502{
503 static struct proxy *curproxy = NULL;
504 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200505 const char *err;
Willy Tarreauee991362007-05-14 14:37:50 +0200506 int rc, val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200507
Willy Tarreau977b8e42006-12-29 14:19:17 +0100508 if (!strcmp(args[0], "listen"))
509 rc = PR_CAP_LISTEN;
510 else if (!strcmp(args[0], "frontend"))
511 rc = PR_CAP_FE | PR_CAP_RS;
512 else if (!strcmp(args[0], "backend"))
513 rc = PR_CAP_BE | PR_CAP_RS;
514 else if (!strcmp(args[0], "ruleset"))
515 rc = PR_CAP_RS;
516 else
517 rc = PR_CAP_NONE;
518
519 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520 if (!*args[1]) {
521 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
522 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
523 file, linenum, args[0]);
524 return -1;
525 }
526
527 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
528 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
529 return -1;
530 }
531
532 curproxy->next = proxy;
533 proxy = curproxy;
534 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200535 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200536 LIST_INIT(&curproxy->block_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200537 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538
Willy Tarreauee991362007-05-14 14:37:50 +0200539 /* Timeouts are defined as -1, so we cannot use the zeroed area
540 * as a default value.
541 */
542 tv_eternity(&curproxy->clitimeout);
543 tv_eternity(&curproxy->srvtimeout);
544 tv_eternity(&curproxy->contimeout);
545 tv_eternity(&curproxy->appsession_timeout);
546
Willy Tarreaubaaee002006-06-26 02:48:02 +0200547 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100548 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200549
550 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100551 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552 curproxy->listen = str2listener(args[2], curproxy->listen);
553 if (!curproxy->listen)
554 return -1;
555 global.maxsock++;
556 }
557
558 /* set default values */
559 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200560 curproxy->options = defproxy.options;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200561 curproxy->except_net = defproxy.except_net;
562 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200563
Willy Tarreau977b8e42006-12-29 14:19:17 +0100564 if (curproxy->cap & PR_CAP_FE) {
565 curproxy->maxconn = defproxy.maxconn;
566
567 /* initialize error relocations */
568 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
569 if (defproxy.errmsg[rc].str)
570 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
571 }
572
573 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
574 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575
Willy Tarreau977b8e42006-12-29 14:19:17 +0100576 if (curproxy->cap & PR_CAP_BE) {
577 curproxy->fullconn = defproxy.fullconn;
578 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579
Willy Tarreau977b8e42006-12-29 14:19:17 +0100580 if (defproxy.check_req)
581 curproxy->check_req = strdup(defproxy.check_req);
582 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200583
Willy Tarreau977b8e42006-12-29 14:19:17 +0100584 if (defproxy.cookie_name)
585 curproxy->cookie_name = strdup(defproxy.cookie_name);
586 curproxy->cookie_len = defproxy.cookie_len;
587 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200588
Willy Tarreau977b8e42006-12-29 14:19:17 +0100589 if (curproxy->cap & PR_CAP_RS) {
590 if (defproxy.capture_name)
591 curproxy->capture_name = strdup(defproxy.capture_name);
592 curproxy->capture_namelen = defproxy.capture_namelen;
593 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100594 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595
Willy Tarreau977b8e42006-12-29 14:19:17 +0100596 if (curproxy->cap & PR_CAP_FE) {
597 curproxy->clitimeout = defproxy.clitimeout;
598 curproxy->uri_auth = defproxy.uri_auth;
599 curproxy->mon_net = defproxy.mon_net;
600 curproxy->mon_mask = defproxy.mon_mask;
601 if (defproxy.monitor_uri)
602 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
603 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100604 if (defproxy.defbe.name)
605 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100606 }
607
608 if (curproxy->cap & PR_CAP_BE) {
609 curproxy->contimeout = defproxy.contimeout;
610 curproxy->srvtimeout = defproxy.srvtimeout;
611 curproxy->source_addr = defproxy.source_addr;
612 }
613
Willy Tarreaubaaee002006-06-26 02:48:02 +0200614 curproxy->mode = defproxy.mode;
615 curproxy->logfac1 = defproxy.logfac1;
616 curproxy->logsrv1 = defproxy.logsrv1;
617 curproxy->loglev1 = defproxy.loglev1;
618 curproxy->logfac2 = defproxy.logfac2;
619 curproxy->logsrv2 = defproxy.logsrv2;
620 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200621 curproxy->grace = defproxy.grace;
Willy Tarreau1c47f852006-07-09 08:22:27 +0200622
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 return 0;
624 }
625 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
626 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100627 /* FIXME-20070101: we should do this too at the end of the
628 * config parsing to free all default values.
629 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 if (defproxy.check_req) free(defproxy.check_req);
631 if (defproxy.cookie_name) free(defproxy.cookie_name);
632 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200633 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100634 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100635
636 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
637 if (defproxy.errmsg[rc].len)
638 free(defproxy.errmsg[rc].str);
639 }
640
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641 /* we cannot free uri_auth because it might already be used */
642 init_default_instance();
643 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100644 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200645 return 0;
646 }
647 else if (curproxy == NULL) {
648 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
649 return -1;
650 }
651
Willy Tarreau977b8e42006-12-29 14:19:17 +0100652
653 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200654 if (!strcmp(args[0], "bind")) { /* new listen addresses */
655 if (curproxy == &defproxy) {
656 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
657 return -1;
658 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100659 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
660 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661
662 if (strchr(args[1], ':') == NULL) {
663 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
664 file, linenum, args[0]);
665 return -1;
666 }
667 curproxy->listen = str2listener(args[1], curproxy->listen);
668 if (!curproxy->listen)
669 return -1;
670 global.maxsock++;
671 return 0;
672 }
673 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
674 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
675 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
676 file, linenum, args[0]);
677 return -1;
678 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100679 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
680 return 0;
681
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 /* flush useless bits */
683 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
684 return 0;
685 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200686 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100687 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
688 return 0;
689
Willy Tarreau1c47f852006-07-09 08:22:27 +0200690 if (!*args[1]) {
691 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
692 file, linenum, args[0]);
693 return -1;
694 }
695
696 if (curproxy->monitor_uri != NULL)
697 free(curproxy->monitor_uri);
698
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100699 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200700 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100701 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200702 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
703
704 return 0;
705 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200706 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
707 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
708 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
709 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
710 else {
711 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
712 return -1;
713 }
714 }
715 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
716 curproxy->state = PR_STSTOPPED;
717 }
718 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
719 curproxy->state = PR_STNEW;
720 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200721 else if (!strcmp(args[0], "acl")) { /* add an ACL */
722 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
723 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
724 file, linenum, args[1]);
725 return -1;
726 }
727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200728 else if (!strcmp(args[0], "cookie")) { /* cookie name */
729 int cur_arg;
730 // if (curproxy == &defproxy) {
731 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
732 // return -1;
733 // }
734
Willy Tarreau977b8e42006-12-29 14:19:17 +0100735 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
736 return 0;
737
Willy Tarreaubaaee002006-06-26 02:48:02 +0200738 if (curproxy->cookie_name != NULL) {
739 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
740 // file, linenum);
741 // return 0;
742 free(curproxy->cookie_name);
743 }
744
745 if (*(args[1]) == 0) {
746 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
747 file, linenum, args[0]);
748 return -1;
749 }
750 curproxy->cookie_name = strdup(args[1]);
751 curproxy->cookie_len = strlen(curproxy->cookie_name);
752
753 cur_arg = 2;
754 while (*(args[cur_arg])) {
755 if (!strcmp(args[cur_arg], "rewrite")) {
756 curproxy->options |= PR_O_COOK_RW;
757 }
758 else if (!strcmp(args[cur_arg], "indirect")) {
759 curproxy->options |= PR_O_COOK_IND;
760 }
761 else if (!strcmp(args[cur_arg], "insert")) {
762 curproxy->options |= PR_O_COOK_INS;
763 }
764 else if (!strcmp(args[cur_arg], "nocache")) {
765 curproxy->options |= PR_O_COOK_NOC;
766 }
767 else if (!strcmp(args[cur_arg], "postonly")) {
768 curproxy->options |= PR_O_COOK_POST;
769 }
770 else if (!strcmp(args[cur_arg], "prefix")) {
771 curproxy->options |= PR_O_COOK_PFX;
772 }
773 else {
774 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
775 file, linenum, args[0]);
776 return -1;
777 }
778 cur_arg++;
779 }
780 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
781 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
782 file, linenum);
783 return -1;
784 }
785
786 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
787 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
788 file, linenum);
789 return -1;
790 }
791 }/* end else if (!strcmp(args[0], "cookie")) */
792 else if (!strcmp(args[0], "appsession")) { /* cookie name */
793 // if (curproxy == &defproxy) {
794 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
795 // return -1;
796 // }
797
Willy Tarreau977b8e42006-12-29 14:19:17 +0100798 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
799 return 0;
800
Willy Tarreaubaaee002006-06-26 02:48:02 +0200801 if (curproxy->appsession_name != NULL) {
802 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
803 // file, linenum);
804 // return 0;
805 free(curproxy->appsession_name);
806 }
807
808 if (*(args[5]) == 0) {
809 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
810 file, linenum, args[0]);
811 return -1;
812 }
813 have_appsession = 1;
814 curproxy->appsession_name = strdup(args[1]);
815 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
816 curproxy->appsession_len = atoi(args[3]);
Willy Tarreauee991362007-05-14 14:37:50 +0200817 val = atoi(args[5]);
818 if (val > 0)
819 __tv_from_ms(&curproxy->appsession_timeout, val);
820 else
821 tv_eternity(&curproxy->appsession_timeout);
822
Willy Tarreau51041c72007-09-09 21:56:53 +0200823 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
824 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200825 return -1;
826 }
827 } /* Url App Session */
828 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100829 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
830 return 0;
831
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
833 // if (curproxy == &defproxy) {
834 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
835 // return -1;
836 // }
837
838 if (curproxy->capture_name != NULL) {
839 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
840 // file, linenum, args[0]);
841 // return 0;
842 free(curproxy->capture_name);
843 }
844
845 if (*(args[4]) == 0) {
846 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
847 file, linenum, args[0]);
848 return -1;
849 }
850 curproxy->capture_name = strdup(args[2]);
851 curproxy->capture_namelen = strlen(curproxy->capture_name);
852 curproxy->capture_len = atol(args[4]);
853 if (curproxy->capture_len >= CAPTURE_LEN) {
854 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
855 file, linenum, CAPTURE_LEN - 1);
856 curproxy->capture_len = CAPTURE_LEN - 1;
857 }
858 curproxy->to_log |= LW_COOKIE;
859 }
860 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
861 struct cap_hdr *hdr;
862
863 if (curproxy == &defproxy) {
864 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
865 return -1;
866 }
867
868 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
869 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
870 file, linenum, args[0], args[1]);
871 return -1;
872 }
873
874 hdr = calloc(sizeof(struct cap_hdr), 1);
875 hdr->next = curproxy->req_cap;
876 hdr->name = strdup(args[3]);
877 hdr->namelen = strlen(args[3]);
878 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200879 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200880 hdr->index = curproxy->nb_req_cap++;
881 curproxy->req_cap = hdr;
882 curproxy->to_log |= LW_REQHDR;
883 }
884 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
885 struct cap_hdr *hdr;
886
887 if (curproxy == &defproxy) {
888 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
889 return -1;
890 }
891
892 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
893 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
894 file, linenum, args[0], args[1]);
895 return -1;
896 }
897 hdr = calloc(sizeof(struct cap_hdr), 1);
898 hdr->next = curproxy->rsp_cap;
899 hdr->name = strdup(args[3]);
900 hdr->namelen = strlen(args[3]);
901 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200902 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200903 hdr->index = curproxy->nb_rsp_cap++;
904 curproxy->rsp_cap = hdr;
905 curproxy->to_log |= LW_RSPHDR;
906 }
907 else {
908 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
909 file, linenum, args[0]);
910 return -1;
911 }
912 }
913 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200914 if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200915 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
916 return 0;
917 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100918 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
919 return 0;
920
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921 if (*(args[1]) == 0) {
922 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
923 file, linenum, args[0]);
924 return -1;
925 }
Willy Tarreauee991362007-05-14 14:37:50 +0200926 val = atoi(args[1]);
927 if (val > 0)
928 __tv_from_ms(&curproxy->contimeout, val);
929 else
930 tv_eternity(&curproxy->contimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 }
932 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200933 if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
935 file, linenum, args[0]);
936 return 0;
937 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100938 else if (warnifnotcap(curproxy, PR_CAP_FE, 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->clitimeout, val);
949 else
950 tv_eternity(&curproxy->clitimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 }
952 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200953 if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
955 return 0;
956 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100957 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
958 return 0;
959
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960 if (*(args[1]) == 0) {
961 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
962 file, linenum, args[0]);
963 return -1;
964 }
Willy Tarreauee991362007-05-14 14:37:50 +0200965 val = atoi(args[1]);
966 if (val > 0)
967 __tv_from_ms(&curproxy->srvtimeout, val);
968 else
969 tv_eternity(&curproxy->srvtimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 }
971 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100972 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
973 return 0;
974
Willy Tarreaubaaee002006-06-26 02:48:02 +0200975 if (*(args[1]) == 0) {
976 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
977 file, linenum, args[0]);
978 return -1;
979 }
980 curproxy->conn_retries = atol(args[1]);
981 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200982 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
983 int pol = ACL_COND_NONE;
984 struct acl_cond *cond;
985
986 if (!strcmp(args[1], "if"))
987 pol = ACL_COND_IF;
988 else if (!strcmp(args[1], "unless"))
989 pol = ACL_COND_UNLESS;
990
991 if (pol == ACL_COND_NONE) {
992 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
993 file, linenum, args[0]);
994 return -1;
995 }
996
997 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
998 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
999 file, linenum);
1000 return -1;
1001 }
1002 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1003 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001004 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1005 int pol = ACL_COND_NONE;
1006 struct acl_cond *cond;
1007 struct switching_rule *rule;
1008
1009 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1010 return 0;
1011
1012 if (*(args[1]) == 0) {
1013 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1014 return -1;
1015 }
1016
1017 if (!strcmp(args[2], "if"))
1018 pol = ACL_COND_IF;
1019 else if (!strcmp(args[2], "unless"))
1020 pol = ACL_COND_UNLESS;
1021
1022 if (pol == ACL_COND_NONE) {
1023 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1024 file, linenum, args[0]);
1025 return -1;
1026 }
1027
1028 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1029 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1030 file, linenum);
1031 return -1;
1032 }
1033
1034 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1035 rule->cond = cond;
1036 rule->be.name = strdup(args[1]);
1037 LIST_INIT(&rule->list);
1038 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1039 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001040 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001041 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1042 return 0;
1043
Willy Tarreaubaaee002006-06-26 02:48:02 +02001044 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1045 curproxy->uri_auth = NULL; /* we must detach from the default config */
1046
1047 if (*(args[1]) == 0) {
1048 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1049 return -1;
1050 } else if (!strcmp(args[1], "uri")) {
1051 if (*(args[2]) == 0) {
1052 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1053 return -1;
1054 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1055 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1056 return -1;
1057 }
1058 } else if (!strcmp(args[1], "realm")) {
1059 if (*(args[2]) == 0) {
1060 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1061 return -1;
1062 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1063 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1064 return -1;
1065 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001066 } else if (!strcmp(args[1], "refresh")) {
1067 int interval = atoi(args[2]);
1068
1069 if (interval < 0) {
1070 Alert("parsing [%s:%d] : 'refresh' needs a positive interval in seconds.\n", file, linenum);
1071 return -1;
1072 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1073 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1074 return -1;
1075 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001076 } else if (!strcmp(args[1], "auth")) {
1077 if (*(args[2]) == 0) {
1078 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1079 return -1;
1080 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1081 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1082 return -1;
1083 }
1084 } else if (!strcmp(args[1], "scope")) {
1085 if (*(args[2]) == 0) {
1086 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1087 return -1;
1088 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1089 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1090 return -1;
1091 }
1092 } else if (!strcmp(args[1], "enable")) {
1093 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1094 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1095 return -1;
1096 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001097 } else if (!strcmp(args[1], "hide-version")) {
1098 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1099 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1100 return -1;
1101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001103 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104 file, linenum, args[0]);
1105 return -1;
1106 }
1107 }
1108 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001109 int optnum;
1110
Willy Tarreaubaaee002006-06-26 02:48:02 +02001111 if (*(args[1]) == 0) {
1112 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
1113 return -1;
1114 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001115
1116 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1117 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1118 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1119 return 0;
1120 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001121 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001122 return 0;
1123 }
1124 }
1125
1126 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 /* generate a complete HTTP log */
1128 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1129 else if (!strcmp(args[1], "tcplog"))
1130 /* generate a detailed TCP log */
1131 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132 else if (!strcmp(args[1], "tcpka")) {
1133 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001134 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1135 return 0;
1136
1137 if (curproxy->cap & PR_CAP_FE)
1138 curproxy->options |= PR_O_TCP_CLI_KA;
1139 if (curproxy->cap & PR_CAP_BE)
1140 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 }
1142 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001143 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1144 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001145 /* use HTTP request to check servers' health */
1146 if (curproxy->check_req != NULL) {
1147 free(curproxy->check_req);
1148 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001149 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001150 curproxy->options &= ~PR_O_SMTP_CHK;
1151 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001152 if (!*args[2]) { /* no argument */
1153 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1154 curproxy->check_len = strlen(DEF_CHECK_REQ);
1155 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001156 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157 curproxy->check_req = (char *)malloc(reqlen);
1158 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1159 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1160 } else { /* more arguments : METHOD URI [HTTP_VER] */
1161 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1162 if (*args[4])
1163 reqlen += strlen(args[4]);
1164 else
1165 reqlen += strlen("HTTP/1.0");
1166
1167 curproxy->check_req = (char *)malloc(reqlen);
1168 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1169 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1170 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001171 }
1172 else if (!strcmp(args[1], "ssl-hello-chk")) {
1173 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001174 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1175 return 0;
1176
Willy Tarreauf3c69202006-07-09 16:42:34 +02001177 if (curproxy->check_req != NULL) {
1178 free(curproxy->check_req);
1179 }
1180 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001181 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001182 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001183 }
Willy Tarreau23677902007-05-08 23:50:35 +02001184 else if (!strcmp(args[1], "smtpchk")) {
1185 /* use SMTP request to check servers' health */
1186 if (curproxy->check_req != NULL) {
1187 free(curproxy->check_req);
1188 }
1189 curproxy->options &= ~PR_O_HTTP_CHK;
1190 curproxy->options &= ~PR_O_SSL3_CHK;
1191 curproxy->options |= PR_O_SMTP_CHK;
1192
1193 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1194 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1195 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1196 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1197 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1198 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1199 curproxy->check_req = (char *)malloc(reqlen);
1200 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1201 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1202 } else {
1203 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1204 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1205 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1206 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1207 }
1208 }
1209 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001210 else if (!strcmp(args[1], "forwardfor")) {
1211 /* insert x-forwarded-for field, but not for the
1212 * IP address listed as an except.
1213 */
1214 if (*(args[2])) {
1215 if (!strcmp(args[2], "except")) {
1216 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1217 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1218 file, linenum, args[0]);
1219 return -1;
1220 }
1221 /* flush useless bits */
1222 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1223 } else {
1224 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1225 file, linenum, args[0]);
1226 return -1;
1227 }
1228 }
1229 curproxy->options |= PR_O_FWDFOR;
1230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001231 else {
1232 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1233 return -1;
1234 }
1235 return 0;
1236 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001237 else if (!strcmp(args[0], "default_backend")) {
1238 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1239 return 0;
1240
1241 if (*(args[1]) == 0) {
1242 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1243 return -1;
1244 }
1245 if (curproxy->defbe.name)
1246 free(curproxy->defbe.name);
1247 curproxy->defbe.name = strdup(args[1]);
1248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001249 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001250 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1251 return 0;
1252
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 /* enable reconnections to dispatch */
1254 curproxy->options |= PR_O_REDISP;
1255 }
1256#ifdef TPROXY
1257 else if (!strcmp(args[0], "transparent")) {
1258 /* enable transparent proxy connections */
1259 curproxy->options |= PR_O_TRANSP;
1260 }
1261#endif
1262 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001263 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1264 return 0;
1265
Willy Tarreaubaaee002006-06-26 02:48:02 +02001266 if (*(args[1]) == 0) {
1267 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1268 return -1;
1269 }
1270 curproxy->maxconn = atol(args[1]);
1271 }
Willy Tarreau86034312006-12-29 00:10:33 +01001272 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001273 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1274 return 0;
1275
Willy Tarreau86034312006-12-29 00:10:33 +01001276 if (*(args[1]) == 0) {
1277 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1278 return -1;
1279 }
1280 curproxy->fullconn = atol(args[1]);
1281 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001282 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1283 if (*(args[1]) == 0) {
1284 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1285 return -1;
1286 }
1287 curproxy->grace = atol(args[1]);
1288 }
1289 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1290 if (curproxy == &defproxy) {
1291 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1292 return -1;
1293 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001294 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1295 return 0;
1296
Willy Tarreaubaaee002006-06-26 02:48:02 +02001297 if (strchr(args[1], ':') == NULL) {
1298 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1299 return -1;
1300 }
1301 curproxy->dispatch_addr = *str2sa(args[1]);
1302 }
1303 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001304 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1305 return 0;
1306
Willy Tarreaubaaee002006-06-26 02:48:02 +02001307 if (*(args[1])) {
1308 if (!strcmp(args[1], "roundrobin")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001309 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001310 curproxy->options |= PR_O_BALANCE_RR;
1311 }
1312 else if (!strcmp(args[1], "source")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001313 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001314 curproxy->options |= PR_O_BALANCE_SH;
1315 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001316 else if (!strcmp(args[1], "uri")) {
1317 curproxy->options &= ~PR_O_BALANCE;
1318 curproxy->options |= PR_O_BALANCE_UH;
1319 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001320 else {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001321 Alert("parsing [%s:%d] : '%s' only supports 'roundrobin', 'source' and 'uri' options.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001322 return -1;
1323 }
1324 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001325 else {/* if no option is set, use round-robin by default */
1326 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001327 curproxy->options |= PR_O_BALANCE_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001328 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001329 }
1330 else if (!strcmp(args[0], "server")) { /* server address */
1331 int cur_arg;
1332 char *rport;
1333 char *raddr;
1334 short realport;
1335 int do_check;
1336
1337 if (curproxy == &defproxy) {
1338 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1339 return -1;
1340 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001341 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1342 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001343
1344 if (!*args[2]) {
1345 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1346 file, linenum, args[0]);
1347 return -1;
1348 }
1349 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1350 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1351 return -1;
1352 }
1353
1354 /* the servers are linked backwards first */
1355 newsrv->next = curproxy->srv;
1356 curproxy->srv = newsrv;
1357 newsrv->proxy = curproxy;
1358
1359 LIST_INIT(&newsrv->pendconns);
1360 do_check = 0;
1361 newsrv->state = SRV_RUNNING; /* early server setup */
1362 newsrv->id = strdup(args[1]);
1363
1364 /* several ways to check the port component :
1365 * - IP => port=+0, relative
1366 * - IP: => port=+0, relative
1367 * - IP:N => port=N, absolute
1368 * - IP:+N => port=+N, relative
1369 * - IP:-N => port=-N, relative
1370 */
1371 raddr = strdup(args[2]);
1372 rport = strchr(raddr, ':');
1373 if (rport) {
1374 *rport++ = 0;
1375 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001376 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001377 newsrv->state |= SRV_MAPPORTS;
1378 } else {
1379 realport = 0;
1380 newsrv->state |= SRV_MAPPORTS;
1381 }
1382
1383 newsrv->addr = *str2sa(raddr);
1384 newsrv->addr.sin_port = htons(realport);
1385 free(raddr);
1386
1387 newsrv->curfd = -1; /* no health-check in progress */
1388 newsrv->inter = DEF_CHKINTR;
1389 newsrv->rise = DEF_RISETIME;
1390 newsrv->fall = DEF_FALLTIME;
1391 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001392 newsrv->uweight = 1;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001393
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 cur_arg = 3;
1395 while (*args[cur_arg]) {
1396 if (!strcmp(args[cur_arg], "cookie")) {
1397 newsrv->cookie = strdup(args[cur_arg + 1]);
1398 newsrv->cklen = strlen(args[cur_arg + 1]);
1399 cur_arg += 2;
1400 }
1401 else if (!strcmp(args[cur_arg], "rise")) {
1402 newsrv->rise = atol(args[cur_arg + 1]);
1403 newsrv->health = newsrv->rise;
1404 cur_arg += 2;
1405 }
1406 else if (!strcmp(args[cur_arg], "fall")) {
1407 newsrv->fall = atol(args[cur_arg + 1]);
1408 cur_arg += 2;
1409 }
1410 else if (!strcmp(args[cur_arg], "inter")) {
1411 newsrv->inter = atol(args[cur_arg + 1]);
1412 cur_arg += 2;
1413 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001414 else if (!strcmp(args[cur_arg], "addr")) {
1415 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001416 cur_arg += 2;
1417 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418 else if (!strcmp(args[cur_arg], "port")) {
1419 newsrv->check_port = atol(args[cur_arg + 1]);
1420 cur_arg += 2;
1421 }
1422 else if (!strcmp(args[cur_arg], "backup")) {
1423 newsrv->state |= SRV_BACKUP;
1424 cur_arg ++;
1425 }
1426 else if (!strcmp(args[cur_arg], "weight")) {
1427 int w;
1428 w = atol(args[cur_arg + 1]);
1429 if (w < 1 || w > 256) {
1430 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1431 file, linenum, newsrv->id, w);
1432 return -1;
1433 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001434 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435 cur_arg += 2;
1436 }
1437 else if (!strcmp(args[cur_arg], "minconn")) {
1438 newsrv->minconn = atol(args[cur_arg + 1]);
1439 cur_arg += 2;
1440 }
1441 else if (!strcmp(args[cur_arg], "maxconn")) {
1442 newsrv->maxconn = atol(args[cur_arg + 1]);
1443 cur_arg += 2;
1444 }
1445 else if (!strcmp(args[cur_arg], "check")) {
1446 global.maxsock++;
1447 do_check = 1;
1448 cur_arg += 1;
1449 }
1450 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1451 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001452#ifdef CONFIG_HAP_CTTPROXY
1453 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1454 file, linenum, "source", "usesrc");
1455#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1457 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001458#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 return -1;
1460 }
1461 newsrv->state |= SRV_BIND_SRC;
1462 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1463 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001464 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001465#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001466 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001467 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1468 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001469 return -1;
1470 }
1471 if (!*args[cur_arg + 1]) {
1472 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1473 file, linenum, "usesrc");
1474 return -1;
1475 }
1476 if (!strcmp(args[cur_arg + 1], "client")) {
1477 newsrv->state |= SRV_TPROXY_CLI;
1478 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1479 newsrv->state |= SRV_TPROXY_CIP;
1480 } else {
1481 newsrv->state |= SRV_TPROXY_ADDR;
1482 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1483 }
1484 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1485 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001486#else /* no CTTPROXY support */
1487 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1488 file, linenum, "usesrc");
1489 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001490#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001491 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001493#ifdef CONFIG_HAP_CTTPROXY
1494 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1495 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1496 file, linenum, "usesrc", "source");
1497 return -1;
1498 }
1499#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500 else {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001501 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 +02001502 file, linenum, newsrv->id);
1503 return -1;
1504 }
1505 }
1506
1507 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001508 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1509 newsrv->check_port = newsrv->check_addr.sin_port;
1510
Willy Tarreaubaaee002006-06-26 02:48:02 +02001511 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1512 newsrv->check_port = realport; /* by default */
1513 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001514 /* not yet valid, because no port was set on
1515 * the server either. We'll check if we have
1516 * a known port on the first listener.
1517 */
1518 struct listener *l;
1519 l = curproxy->listen;
1520 if (l) {
1521 int port;
1522 port = (l->addr.ss_family == AF_INET6)
1523 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1524 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1525 newsrv->check_port = port;
1526 }
1527 }
1528 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1530 file, linenum, newsrv->id);
1531 return -1;
1532 }
1533 newsrv->state |= SRV_CHECKED;
1534 }
1535
1536 if (newsrv->state & SRV_BACKUP)
1537 curproxy->srv_bck++;
1538 else
1539 curproxy->srv_act++;
1540 }
1541 else if (!strcmp(args[0], "log")) { /* syslog server address */
1542 struct sockaddr_in *sa;
1543 int facility;
1544
1545 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1546 curproxy->logfac1 = global.logfac1;
1547 curproxy->logsrv1 = global.logsrv1;
1548 curproxy->loglev1 = global.loglev1;
1549 curproxy->logfac2 = global.logfac2;
1550 curproxy->logsrv2 = global.logsrv2;
1551 curproxy->loglev2 = global.loglev2;
1552 }
1553 else if (*(args[1]) && *(args[2])) {
1554 int level;
1555
1556 facility = get_log_facility(args[2]);
1557 if (facility < 0) {
1558 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1559 exit(1);
1560 }
1561
1562 level = 7; /* max syslog level = debug */
1563 if (*(args[3])) {
1564 level = get_log_level(args[3]);
1565 if (level < 0) {
1566 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1567 exit(1);
1568 }
1569 }
1570
1571 sa = str2sa(args[1]);
1572 if (!sa->sin_port)
1573 sa->sin_port = htons(SYSLOG_PORT);
1574
1575 if (curproxy->logfac1 == -1) {
1576 curproxy->logsrv1 = *sa;
1577 curproxy->logfac1 = facility;
1578 curproxy->loglev1 = level;
1579 }
1580 else if (curproxy->logfac2 == -1) {
1581 curproxy->logsrv2 = *sa;
1582 curproxy->logfac2 = facility;
1583 curproxy->loglev2 = level;
1584 }
1585 else {
1586 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1587 return -1;
1588 }
1589 }
1590 else {
1591 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1592 file, linenum);
1593 return -1;
1594 }
1595 }
1596 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001597 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1598 return 0;
1599
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001601#ifdef CONFIG_HAP_CTTPROXY
1602 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1603 file, linenum, "source", "usesrc");
1604#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1606 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001607#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001608 return -1;
1609 }
1610
1611 curproxy->source_addr = *str2sa(args[1]);
1612 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001613 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001614#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001615 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1616 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1617 file, linenum, "usesrc");
1618 return -1;
1619 }
1620 if (!*args[3]) {
1621 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1622 file, linenum, "usesrc");
1623 return -1;
1624 }
1625
1626 if (!strcmp(args[3], "client")) {
1627 curproxy->options |= PR_O_TPXY_CLI;
1628 } else if (!strcmp(args[3], "clientip")) {
1629 curproxy->options |= PR_O_TPXY_CIP;
1630 } else {
1631 curproxy->options |= PR_O_TPXY_ADDR;
1632 curproxy->tproxy_addr = *str2sa(args[3]);
1633 }
1634 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001635#else /* no CTTPROXY support */
1636 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1637 file, linenum, "usesrc");
1638 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001639#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001641 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001642#ifdef CONFIG_HAP_CTTPROXY
1643 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1644 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1645 file, linenum, "usesrc", "source");
1646 return -1;
1647 }
1648#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1650 regex_t *preg;
1651 if (curproxy == &defproxy) {
1652 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1653 return -1;
1654 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001655 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1656 return 0;
1657
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 if (*(args[1]) == 0 || *(args[2]) == 0) {
1659 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1660 file, linenum, args[0]);
1661 return -1;
1662 }
1663
1664 preg = calloc(1, sizeof(regex_t));
1665 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1666 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1667 return -1;
1668 }
1669
1670 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1671 if (err) {
1672 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1673 file, linenum, *err);
1674 return -1;
1675 }
1676 }
1677 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1678 regex_t *preg;
1679 if (curproxy == &defproxy) {
1680 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1681 return -1;
1682 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001683 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1684 return 0;
1685
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 if (*(args[1]) == 0) {
1687 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1688 return -1;
1689 }
1690
1691 preg = calloc(1, sizeof(regex_t));
1692 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1693 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1694 return -1;
1695 }
1696
1697 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1698 }
1699 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1700 regex_t *preg;
1701 if (curproxy == &defproxy) {
1702 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1703 return -1;
1704 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001705 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1706 return 0;
1707
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 if (*(args[1]) == 0) {
1709 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1710 return -1;
1711 }
1712
1713 preg = calloc(1, sizeof(regex_t));
1714 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1715 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1716 return -1;
1717 }
1718
1719 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1720 }
1721 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1722 regex_t *preg;
1723 if (curproxy == &defproxy) {
1724 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1725 return -1;
1726 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001727 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1728 return 0;
1729
Willy Tarreaubaaee002006-06-26 02:48:02 +02001730 if (*(args[1]) == 0) {
1731 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1732 return -1;
1733 }
1734
1735 preg = calloc(1, sizeof(regex_t));
1736 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1737 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1738 return -1;
1739 }
1740
1741 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1742 }
1743 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1744 regex_t *preg;
1745 if (curproxy == &defproxy) {
1746 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1747 return -1;
1748 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001749 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1750 return 0;
1751
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752 if (*(args[1]) == 0) {
1753 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1754 return -1;
1755 }
1756
1757 preg = calloc(1, sizeof(regex_t));
1758 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1759 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1760 return -1;
1761 }
1762
1763 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1764 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001765 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1766 regex_t *preg;
1767 if (curproxy == &defproxy) {
1768 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1769 return -1;
1770 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001771 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1772 return 0;
1773
Willy Tarreaub8750a82006-09-03 09:56:00 +02001774 if (*(args[1]) == 0) {
1775 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1776 return -1;
1777 }
1778
1779 preg = calloc(1, sizeof(regex_t));
1780 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1781 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1782 return -1;
1783 }
1784
1785 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1786 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001787 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1788 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001789 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001790 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1791 return -1;
1792 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001793 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1794 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001795
Willy Tarreau977b8e42006-12-29 14:19:17 +01001796 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001797 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1798 file, linenum, args[0]);
1799 return -1;
1800 }
1801
1802 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001803 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001804 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1805 }
1806
1807 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1808 }
1809 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1810 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001811 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001812 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1813 return -1;
1814 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001815 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1816 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001817
Willy Tarreau977b8e42006-12-29 14:19:17 +01001818 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001819 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1820 file, linenum, args[0]);
1821 return -1;
1822 }
1823
1824 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001825 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001826 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1827 }
1828
1829 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1830 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001831 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1832 regex_t *preg;
1833 if (curproxy == &defproxy) {
1834 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1835 return -1;
1836 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001837 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1838 return 0;
1839
Willy Tarreaubaaee002006-06-26 02:48:02 +02001840 if (*(args[1]) == 0 || *(args[2]) == 0) {
1841 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1842 file, linenum, args[0]);
1843 return -1;
1844 }
1845
1846 preg = calloc(1, sizeof(regex_t));
1847 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1848 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1849 return -1;
1850 }
1851
1852 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1853 if (err) {
1854 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1855 file, linenum, *err);
1856 return -1;
1857 }
1858 }
1859 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1860 regex_t *preg;
1861 if (curproxy == &defproxy) {
1862 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1863 return -1;
1864 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001865 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1866 return 0;
1867
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 if (*(args[1]) == 0) {
1869 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1870 return -1;
1871 }
1872
1873 preg = calloc(1, sizeof(regex_t));
1874 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1875 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1876 return -1;
1877 }
1878
1879 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1880 }
1881 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1882 regex_t *preg;
1883 if (curproxy == &defproxy) {
1884 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1885 return -1;
1886 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001887 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1888 return 0;
1889
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890 if (*(args[1]) == 0) {
1891 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1892 return -1;
1893 }
1894
1895 preg = calloc(1, sizeof(regex_t));
1896 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1897 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1898 return -1;
1899 }
1900
1901 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1902 }
1903 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1904 regex_t *preg;
1905 if (curproxy == &defproxy) {
1906 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1907 return -1;
1908 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001909 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1910 return 0;
1911
Willy Tarreaubaaee002006-06-26 02:48:02 +02001912 if (*(args[1]) == 0) {
1913 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1914 return -1;
1915 }
1916
1917 preg = calloc(1, sizeof(regex_t));
1918 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1919 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1920 return -1;
1921 }
1922
1923 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1924 }
1925 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1926 regex_t *preg;
1927 if (curproxy == &defproxy) {
1928 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1929 return -1;
1930 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001931 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1932 return 0;
1933
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934 if (*(args[1]) == 0) {
1935 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1936 return -1;
1937 }
1938
1939 preg = calloc(1, sizeof(regex_t));
1940 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1941 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1942 return -1;
1943 }
1944
1945 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1946 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001947 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1948 regex_t *preg;
1949 if (curproxy == &defproxy) {
1950 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1951 return -1;
1952 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001953 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1954 return 0;
1955
Willy Tarreaub8750a82006-09-03 09:56:00 +02001956 if (*(args[1]) == 0) {
1957 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1958 return -1;
1959 }
1960
1961 preg = calloc(1, sizeof(regex_t));
1962 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1963 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1964 return -1;
1965 }
1966
1967 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001969 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1970 if (curproxy == &defproxy) {
1971 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1972 return -1;
1973 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001974 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1975 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976
1977 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
1978 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1979 return 0;
1980 }
1981
1982 if (*(args[1]) == 0) {
1983 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1984 return -1;
1985 }
1986
1987 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
1988 }
1989 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
1990 regex_t *preg;
1991
1992 if (*(args[1]) == 0 || *(args[2]) == 0) {
1993 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1994 file, linenum, args[0]);
1995 return -1;
1996 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001997 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1998 return 0;
1999
Willy Tarreaubaaee002006-06-26 02:48:02 +02002000 preg = calloc(1, sizeof(regex_t));
2001 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2002 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2003 return -1;
2004 }
2005
2006 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2007 if (err) {
2008 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2009 file, linenum, *err);
2010 return -1;
2011 }
2012 }
2013 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2014 regex_t *preg;
2015 if (curproxy == &defproxy) {
2016 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2017 return -1;
2018 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002019 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2020 return 0;
2021
Willy Tarreaubaaee002006-06-26 02:48:02 +02002022 if (*(args[1]) == 0) {
2023 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2024 return -1;
2025 }
2026
2027 preg = calloc(1, sizeof(regex_t));
2028 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2029 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2030 return -1;
2031 }
2032
2033 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2034 if (err) {
2035 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2036 file, linenum, *err);
2037 return -1;
2038 }
2039 }
2040 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2041 regex_t *preg;
2042 if (curproxy == &defproxy) {
2043 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2044 return -1;
2045 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002046 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2047 return 0;
2048
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049 if (*(args[1]) == 0) {
2050 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2051 return -1;
2052 }
2053
2054 preg = calloc(1, sizeof(regex_t));
2055 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2056 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2057 return -1;
2058 }
2059
2060 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2061 if (err) {
2062 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2063 file, linenum, *err);
2064 return -1;
2065 }
2066 }
2067 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2068 regex_t *preg;
2069 if (curproxy == &defproxy) {
2070 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2071 return -1;
2072 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002073 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2074 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002075
2076 if (*(args[1]) == 0 || *(args[2]) == 0) {
2077 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2078 file, linenum, args[0]);
2079 return -1;
2080 }
2081
2082 preg = calloc(1, sizeof(regex_t));
2083 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2084 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2085 return -1;
2086 }
2087
2088 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2089 if (err) {
2090 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2091 file, linenum, *err);
2092 return -1;
2093 }
2094 }
2095 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2096 regex_t *preg;
2097 if (curproxy == &defproxy) {
2098 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2099 return -1;
2100 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002101 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2102 return 0;
2103
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 if (*(args[1]) == 0) {
2105 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2106 return -1;
2107 }
2108
2109 preg = calloc(1, sizeof(regex_t));
2110 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2111 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2112 return -1;
2113 }
2114
2115 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2116 if (err) {
2117 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2118 file, linenum, *err);
2119 return -1;
2120 }
2121 }
2122 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2123 regex_t *preg;
2124 if (curproxy == &defproxy) {
2125 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2126 return -1;
2127 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002128 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2129 return 0;
2130
Willy Tarreaubaaee002006-06-26 02:48:02 +02002131 if (*(args[1]) == 0) {
2132 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2133 return -1;
2134 }
2135
2136 preg = calloc(1, sizeof(regex_t));
2137 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2138 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2139 return -1;
2140 }
2141
2142 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2143 if (err) {
2144 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2145 file, linenum, *err);
2146 return -1;
2147 }
2148 }
2149 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2150 if (curproxy == &defproxy) {
2151 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2152 return -1;
2153 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002154 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2155 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156
2157 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2158 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2159 return 0;
2160 }
2161
2162 if (*(args[1]) == 0) {
2163 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2164 return -1;
2165 }
2166
2167 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2168 }
2169 else if (!strcmp(args[0], "errorloc") ||
2170 !strcmp(args[0], "errorloc302") ||
2171 !strcmp(args[0], "errorloc303")) { /* error location */
2172 int errnum, errlen;
2173 char *err;
2174
Willy Tarreau977b8e42006-12-29 14:19:17 +01002175 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2176 return 0;
2177
Willy Tarreaubaaee002006-06-26 02:48:02 +02002178 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002179 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002180 return -1;
2181 }
2182
2183 errnum = atol(args[1]);
2184 if (!strcmp(args[0], "errorloc303")) {
2185 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2186 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2187 } else {
2188 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2189 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2190 }
2191
Willy Tarreau0f772532006-12-23 20:51:41 +01002192 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2193 if (http_err_codes[rc] == errnum) {
2194 if (curproxy->errmsg[rc].str)
2195 free(curproxy->errmsg[rc].str);
2196 curproxy->errmsg[rc].str = err;
2197 curproxy->errmsg[rc].len = errlen;
2198 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002199 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002200 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002201
2202 if (rc >= HTTP_ERR_SIZE) {
2203 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2204 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002205 free(err);
2206 }
2207 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002208 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2209 int errnum, errlen, fd;
2210 char *err;
2211 struct stat stat;
2212
2213 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2214 return 0;
2215
2216 if (*(args[2]) == 0) {
2217 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2218 return -1;
2219 }
2220
2221 fd = open(args[2], O_RDONLY);
2222 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2223 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2224 file, linenum, args[2], args[1]);
2225 if (fd >= 0)
2226 close(fd);
2227 return -1;
2228 }
2229
2230 if (stat.st_size <= BUFSIZE) {
2231 errlen = stat.st_size;
2232 } else {
2233 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2234 file, linenum, args[2], BUFSIZE);
2235 errlen = BUFSIZE;
2236 }
2237
2238 err = malloc(errlen); /* malloc() must succeed during parsing */
2239 errnum = read(fd, err, errlen);
2240 if (errnum != errlen) {
2241 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2242 file, linenum, args[2], args[1]);
2243 close(fd);
2244 free(err);
2245 return -1;
2246 }
2247 close(fd);
2248
2249 errnum = atol(args[1]);
2250 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2251 if (http_err_codes[rc] == errnum) {
2252 if (curproxy->errmsg[rc].str)
2253 free(curproxy->errmsg[rc].str);
2254 curproxy->errmsg[rc].str = err;
2255 curproxy->errmsg[rc].len = errlen;
2256 break;
2257 }
2258 }
2259
2260 if (rc >= HTTP_ERR_SIZE) {
2261 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2262 file, linenum, errnum);
2263 free(err);
2264 }
2265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 else {
2267 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2268 return -1;
2269 }
2270 return 0;
2271}
2272
2273
2274/*
2275 * This function reads and parses the configuration file given in the argument.
2276 * returns 0 if OK, -1 if error.
2277 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002278int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279{
2280 char thisline[256];
2281 char *line;
2282 FILE *f;
2283 int linenum = 0;
2284 char *end;
Willy Tarreau540abe42007-05-02 20:50:16 +02002285 char *args[MAX_LINE_ARGS + 1];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 int arg;
2287 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 int confsect = CFG_NONE;
2289
2290 struct proxy *curproxy = NULL;
2291 struct server *newsrv = NULL;
2292
2293 if ((f=fopen(file,"r")) == NULL)
2294 return -1;
2295
2296 init_default_instance();
2297
2298 while (fgets(line = thisline, sizeof(thisline), f) != NULL) {
2299 linenum++;
2300
2301 end = line + strlen(line);
2302
2303 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002304 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002305 line++;
2306
2307 arg = 0;
2308 args[arg] = line;
2309
2310 while (*line && arg < MAX_LINE_ARGS) {
2311 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2312 * C equivalent value. Other combinations left unchanged (eg: \1).
2313 */
2314 if (*line == '\\') {
2315 int skip = 0;
2316 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2317 *line = line[1];
2318 skip = 1;
2319 }
2320 else if (line[1] == 'r') {
2321 *line = '\r';
2322 skip = 1;
2323 }
2324 else if (line[1] == 'n') {
2325 *line = '\n';
2326 skip = 1;
2327 }
2328 else if (line[1] == 't') {
2329 *line = '\t';
2330 skip = 1;
2331 }
2332 else if (line[1] == 'x') {
2333 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2334 unsigned char hex1, hex2;
2335 hex1 = toupper(line[2]) - '0';
2336 hex2 = toupper(line[3]) - '0';
2337 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2338 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2339 *line = (hex1<<4) + hex2;
2340 skip = 3;
2341 }
2342 else {
2343 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2344 return -1;
2345 }
2346 }
2347 if (skip) {
2348 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2349 end -= skip;
2350 }
2351 line++;
2352 }
2353 else if (*line == '#' || *line == '\n' || *line == '\r') {
2354 /* end of string, end of loop */
2355 *line = 0;
2356 break;
2357 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002358 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 /* a non-escaped space is an argument separator */
2360 *line++ = 0;
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002361 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 line++;
2363 args[++arg] = line;
2364 }
2365 else {
2366 line++;
2367 }
2368 }
2369
2370 /* empty line */
2371 if (!**args)
2372 continue;
2373
Willy Tarreau540abe42007-05-02 20:50:16 +02002374 /* zero out remaining args and ensure that at least one entry
2375 * is zeroed out.
2376 */
2377 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 args[arg] = line;
2379 }
2380
Willy Tarreau977b8e42006-12-29 14:19:17 +01002381 if (!strcmp(args[0], "listen") ||
2382 !strcmp(args[0], "frontend") ||
2383 !strcmp(args[0], "backend") ||
2384 !strcmp(args[0], "ruleset") ||
2385 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 confsect = CFG_LISTEN;
2387 else if (!strcmp(args[0], "global")) /* global config */
2388 confsect = CFG_GLOBAL;
2389 /* else it's a section keyword */
2390
2391 switch (confsect) {
2392 case CFG_LISTEN:
2393 if (cfg_parse_listen(file, linenum, args) < 0)
2394 return -1;
2395 break;
2396 case CFG_GLOBAL:
2397 if (cfg_parse_global(file, linenum, args) < 0)
2398 return -1;
2399 break;
2400 default:
2401 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2402 return -1;
2403 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 }
2405 fclose(f);
2406
2407 /*
2408 * Now, check for the integrity of all that we have collected.
2409 */
2410
2411 /* will be needed further to delay some tasks */
2412 tv_now(&now);
2413
2414 if ((curproxy = proxy) == NULL) {
2415 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2416 file);
2417 return -1;
2418 }
2419
2420 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002421 struct switching_rule *rule;
2422
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423 if (curproxy->state == PR_STSTOPPED) {
2424 curproxy = curproxy->next;
2425 continue;
2426 }
2427
Willy Tarreau977b8e42006-12-29 14:19:17 +01002428 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2429 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 +01002430 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 cfgerr++;
2432 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002433 else if (curproxy->cap & PR_CAP_BE &&
2434 ((curproxy->mode != PR_MODE_HEALTH) &&
2435 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
2436 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2437 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 +01002438 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002439 cfgerr++;
2440 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002441
2442 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002444 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002445 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446 cfgerr++;
2447 }
2448#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2449 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002450 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002451 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 cfgerr++;
2453 }
2454#endif
2455 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002456 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002457 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458 }
2459 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002460
2461 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002462 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002463 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002464 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002467 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002468 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002469 }
2470 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002471 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002472 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002474 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002475 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002476 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002477 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002478 if (curproxy->options & PR_O_BALANCE_UH) {
2479 curproxy->options &= ~PR_O_BALANCE;
2480 curproxy->options |= PR_O_BALANCE_RR;
2481
2482 Warning("parsing %s : URI hash will be ignored for %s '%s'. Falling back to round robin.\n",
2483 file, proxy_type_str(curproxy), curproxy->id);
2484 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002486
2487 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2488 if ((newsrv = curproxy->srv) != NULL) {
2489 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2490 file, proxy_type_str(curproxy), curproxy->id);
2491 }
2492 }
2493
2494 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2496 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2497 file, curproxy->id);
2498 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002499 }
2500 }
2501
2502 /* if a default backend was specified, let's find it */
2503 if (curproxy->defbe.name) {
2504 struct proxy *target;
2505
2506 for (target = proxy; target != NULL; target = target->next) {
2507 if (strcmp(target->id, curproxy->defbe.name) == 0)
2508 break;
2509 }
2510 if (target == NULL) {
2511 Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n",
2512 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2513 cfgerr++;
2514 } else if (target == curproxy) {
2515 Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
2516 cfgerr++;
2517 } else if (!(target->cap & PR_CAP_BE)) {
2518 Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n",
2519 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2520 cfgerr++;
2521 } else if (target->mode != curproxy->mode) {
2522 Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
2523 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2524 cfgerr++;
2525 } else {
2526 free(curproxy->defbe.name);
2527 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002528 }
2529 }
2530
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002531 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002532 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2533 /* map jump target for ACT_SETBE in req_rep chain */
2534 struct hdr_exp *exp;
2535 struct proxy *target;
2536 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
2537 if (exp->action != ACT_SETBE)
2538 continue;
2539 for (target = proxy; target != NULL; target = target->next) {
2540 if (strcmp(target->id, exp->replace) == 0)
2541 break;
2542 }
2543 if (target == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002544 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002545 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaua496b602006-12-17 23:15:24 +01002546 cfgerr++;
2547 } else if (target == curproxy) {
2548 Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
2549 cfgerr++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002550 } else if (!(target->cap & PR_CAP_BE)) {
2551 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002552 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002553 cfgerr++;
2554 } else if (target->mode != PR_MODE_HTTP) {
2555 Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002556 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002557 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002558 } else {
2559 free((void *)exp->replace);
2560 exp->replace = (const char *)target;
2561 }
2562 }
2563 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002564
2565 /* find the target proxy for 'use_backend' rules */
2566 list_for_each_entry(rule, &curproxy->switching_rules, list) {
2567 /* map jump target for ACT_SETBE in req_rep chain */
2568 struct proxy *target;
2569
2570 for (target = proxy; target != NULL; target = target->next) {
2571 if (strcmp(target->id, rule->be.name) == 0)
2572 break;
2573 }
2574
2575 if (target == NULL) {
2576 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
2577 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2578 cfgerr++;
2579 } else if (target == curproxy) {
2580 Alert("parsing %s : loop detected for backend %s !\n", file, rule->be.name);
2581 cfgerr++;
2582 } else if (!(target->cap & PR_CAP_BE)) {
2583 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
2584 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2585 cfgerr++;
2586 } else if (target->mode != curproxy->mode) {
2587 Alert("parsing %s : backend '%s' referenced in %s '%s' is of different mode !\n",
2588 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2589 cfgerr++;
2590 } else {
2591 free((void *)rule->be.name);
2592 rule->be.backend = target;
2593 }
2594 }
2595
Willy Tarreau2738a142006-07-08 17:28:09 +02002596 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002597 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2598 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2599 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002600 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002601 " | While not properly invalid, you will certainly encounter various problems\n"
2602 " | with such a configuration. To fix this, please ensure that all following\n"
2603 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002604 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002605 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002606
2607 if (curproxy->options & PR_O_SSL3_CHK) {
2608 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2609 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2610 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2611 }
2612
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002613 /* The small pools required for the capture lists */
2614 if (curproxy->nb_req_cap)
2615 curproxy->req_cap_pool = create_pool("ptrcap",
2616 curproxy->nb_req_cap * sizeof(char *),
2617 MEM_F_SHARED);
2618 if (curproxy->nb_rsp_cap)
2619 curproxy->rsp_cap_pool = create_pool("ptrcap",
2620 curproxy->nb_rsp_cap * sizeof(char *),
2621 MEM_F_SHARED);
2622
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002623 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2624 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2625 MEM_F_SHARED);
2626
Willy Tarreau86034312006-12-29 00:10:33 +01002627 /* for backwards compatibility with "listen" instances, if
2628 * fullconn is not set but maxconn is set, then maxconn
2629 * is used.
2630 */
2631 if (!curproxy->fullconn)
2632 curproxy->fullconn = curproxy->maxconn;
2633
Willy Tarreaubaaee002006-06-26 02:48:02 +02002634 /* first, we will invert the servers list order */
2635 newsrv = NULL;
2636 while (curproxy->srv) {
2637 struct server *next;
2638
2639 next = curproxy->srv->next;
2640 curproxy->srv->next = newsrv;
2641 newsrv = curproxy->srv;
2642 if (!next)
2643 break;
2644 curproxy->srv = next;
2645 }
2646
2647 /* now, newsrv == curproxy->srv */
2648 if (newsrv) {
2649 struct server *srv;
2650 int pgcd;
2651 int act, bck;
2652
2653 /* We will factor the weights to reduce the table,
2654 * using Euclide's largest common divisor algorithm
2655 */
Willy Tarreau417fae02007-03-25 21:16:40 +02002656 pgcd = newsrv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2658 int t, w;
2659
Willy Tarreau417fae02007-03-25 21:16:40 +02002660 w = srv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002661 while (w) {
2662 t = pgcd % w;
2663 pgcd = w;
2664 w = t;
2665 }
2666 }
2667
2668 act = bck = 0;
2669 for (srv = newsrv; srv; srv = srv->next) {
Willy Tarreau417fae02007-03-25 21:16:40 +02002670 srv->eweight = srv->uweight / pgcd;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002671 if (srv->state & SRV_BACKUP)
Willy Tarreau417fae02007-03-25 21:16:40 +02002672 bck += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673 else
Willy Tarreau417fae02007-03-25 21:16:40 +02002674 act += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002675 }
2676
2677 /* this is the largest map we will ever need for this servers list */
2678 if (act < bck)
2679 act = bck;
2680
2681 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2682 /* recounts servers and their weights */
Willy Tarreau5af3a692007-07-24 23:32:33 +02002683 curproxy->map_state = PR_MAP_RECALC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 recount_servers(curproxy);
2685 recalc_server_map(curproxy);
2686 }
2687
2688 if (curproxy->options & PR_O_LOGASAP)
2689 curproxy->to_log &= ~LW_BYTES;
2690
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 /*
2692 * If this server supports a maxconn parameter, it needs a dedicated
2693 * tasks to fill the emptied slots when a connection leaves.
2694 */
2695 newsrv = curproxy->srv;
2696 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002697 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 /* Only 'minconn' was specified, or it was higher than or equal
2699 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2700 * this will avoid further useless expensive computations.
2701 */
2702 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002703 } else if (newsrv->maxconn && !newsrv->minconn) {
2704 /* minconn was not specified, so we set it to maxconn */
2705 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002706 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2707 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002708 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002709 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002710 }
2711
2712 if (newsrv->maxconn > 0) {
2713 struct task *t;
2714
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002715 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2717 return -1;
2718 }
2719
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002720 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002721 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002722 t->state = TASK_IDLE;
2723 t->process = process_srv_queue;
2724 t->context = newsrv;
2725 newsrv->queue_mgt = t;
2726
2727 /* never run it unless specifically woken up */
2728 tv_eternity(&t->expire);
2729 task_queue(t);
2730 }
2731 newsrv = newsrv->next;
2732 }
2733
Willy Tarreaubaaee002006-06-26 02:48:02 +02002734 curproxy = curproxy->next;
2735 }
2736 if (cfgerr > 0) {
2737 Alert("Errors found in configuration file, aborting.\n");
2738 return -1;
2739 }
2740 else
2741 return 0;
2742}
2743
2744
2745
2746/*
2747 * Local variables:
2748 * c-indent-level: 8
2749 * c-basic-offset: 8
2750 * End:
2751 */