blob: 0df66daae33338a2936e33027b8806f91d0f3b98 [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 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200526
527 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
528 /*
529 * If there are two proxies with the same name only following
530 * combinations are allowed:
531 *
532 * listen backend frontend ruleset
533 * listen - - - -
534 * backend - - OK -
535 * frontend - OK - -
536 * ruleset - - - -
537 */
538
539 if (!strcmp(curproxy->id, args[1]) &&
540 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
541 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100542 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
543 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200544 }
545 }
546
Willy Tarreaubaaee002006-06-26 02:48:02 +0200547 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
548 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
549 return -1;
550 }
551
552 curproxy->next = proxy;
553 proxy = curproxy;
554 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200555 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200556 LIST_INIT(&curproxy->block_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200557 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200558
Willy Tarreauee991362007-05-14 14:37:50 +0200559 /* Timeouts are defined as -1, so we cannot use the zeroed area
560 * as a default value.
561 */
562 tv_eternity(&curproxy->clitimeout);
563 tv_eternity(&curproxy->srvtimeout);
564 tv_eternity(&curproxy->contimeout);
565 tv_eternity(&curproxy->appsession_timeout);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200566
567 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200568 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100569 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200570
571 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100572 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200573 curproxy->listen = str2listener(args[2], curproxy->listen);
574 if (!curproxy->listen)
575 return -1;
576 global.maxsock++;
577 }
578
579 /* set default values */
580 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581 curproxy->options = defproxy.options;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200582 curproxy->except_net = defproxy.except_net;
583 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200584
Willy Tarreau977b8e42006-12-29 14:19:17 +0100585 if (curproxy->cap & PR_CAP_FE) {
586 curproxy->maxconn = defproxy.maxconn;
587
588 /* initialize error relocations */
589 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
590 if (defproxy.errmsg[rc].str)
591 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
592 }
593
594 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
595 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200596
Willy Tarreau977b8e42006-12-29 14:19:17 +0100597 if (curproxy->cap & PR_CAP_BE) {
598 curproxy->fullconn = defproxy.fullconn;
599 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600
Willy Tarreau977b8e42006-12-29 14:19:17 +0100601 if (defproxy.check_req)
602 curproxy->check_req = strdup(defproxy.check_req);
603 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604
Willy Tarreau977b8e42006-12-29 14:19:17 +0100605 if (defproxy.cookie_name)
606 curproxy->cookie_name = strdup(defproxy.cookie_name);
607 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100608
609 if (defproxy.url_param_name)
610 curproxy->url_param_name = strdup(defproxy.url_param_name);
611 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613
Willy Tarreau977b8e42006-12-29 14:19:17 +0100614 if (curproxy->cap & PR_CAP_RS) {
615 if (defproxy.capture_name)
616 curproxy->capture_name = strdup(defproxy.capture_name);
617 curproxy->capture_namelen = defproxy.capture_namelen;
618 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100619 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200620
Willy Tarreau977b8e42006-12-29 14:19:17 +0100621 if (curproxy->cap & PR_CAP_FE) {
622 curproxy->clitimeout = defproxy.clitimeout;
623 curproxy->uri_auth = defproxy.uri_auth;
624 curproxy->mon_net = defproxy.mon_net;
625 curproxy->mon_mask = defproxy.mon_mask;
626 if (defproxy.monitor_uri)
627 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
628 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100629 if (defproxy.defbe.name)
630 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100631 }
632
633 if (curproxy->cap & PR_CAP_BE) {
634 curproxy->contimeout = defproxy.contimeout;
635 curproxy->srvtimeout = defproxy.srvtimeout;
636 curproxy->source_addr = defproxy.source_addr;
637 }
638
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 curproxy->mode = defproxy.mode;
640 curproxy->logfac1 = defproxy.logfac1;
641 curproxy->logsrv1 = defproxy.logsrv1;
642 curproxy->loglev1 = defproxy.loglev1;
643 curproxy->logfac2 = defproxy.logfac2;
644 curproxy->logsrv2 = defproxy.logsrv2;
645 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646 curproxy->grace = defproxy.grace;
Willy Tarreau1c47f852006-07-09 08:22:27 +0200647
Willy Tarreaubaaee002006-06-26 02:48:02 +0200648 return 0;
649 }
650 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
651 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100652 /* FIXME-20070101: we should do this too at the end of the
653 * config parsing to free all default values.
654 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200655 if (defproxy.check_req) free(defproxy.check_req);
656 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100657 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200659 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100660 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100661
662 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
663 if (defproxy.errmsg[rc].len)
664 free(defproxy.errmsg[rc].str);
665 }
666
Willy Tarreaubaaee002006-06-26 02:48:02 +0200667 /* we cannot free uri_auth because it might already be used */
668 init_default_instance();
669 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100670 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671 return 0;
672 }
673 else if (curproxy == NULL) {
674 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
675 return -1;
676 }
677
Willy Tarreau977b8e42006-12-29 14:19:17 +0100678
679 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 if (!strcmp(args[0], "bind")) { /* new listen addresses */
681 if (curproxy == &defproxy) {
682 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
683 return -1;
684 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100685 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
686 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200687
688 if (strchr(args[1], ':') == NULL) {
689 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
690 file, linenum, args[0]);
691 return -1;
692 }
693 curproxy->listen = str2listener(args[1], curproxy->listen);
694 if (!curproxy->listen)
695 return -1;
696 global.maxsock++;
697 return 0;
698 }
699 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
700 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
701 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
702 file, linenum, args[0]);
703 return -1;
704 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100705 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
706 return 0;
707
Willy Tarreaubaaee002006-06-26 02:48:02 +0200708 /* flush useless bits */
709 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
710 return 0;
711 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200712 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100713 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
714 return 0;
715
Willy Tarreau1c47f852006-07-09 08:22:27 +0200716 if (!*args[1]) {
717 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
718 file, linenum, args[0]);
719 return -1;
720 }
721
722 if (curproxy->monitor_uri != NULL)
723 free(curproxy->monitor_uri);
724
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100725 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200726 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100727 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200728 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
729
730 return 0;
731 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200732 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
733 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
734 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
735 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
736 else {
737 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
738 return -1;
739 }
740 }
741 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
742 curproxy->state = PR_STSTOPPED;
743 }
744 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
745 curproxy->state = PR_STNEW;
746 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200747 else if (!strcmp(args[0], "acl")) { /* add an ACL */
748 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
749 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
750 file, linenum, args[1]);
751 return -1;
752 }
753 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200754 else if (!strcmp(args[0], "cookie")) { /* cookie name */
755 int cur_arg;
756 // if (curproxy == &defproxy) {
757 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
758 // return -1;
759 // }
760
Willy Tarreau977b8e42006-12-29 14:19:17 +0100761 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
762 return 0;
763
Willy Tarreaubaaee002006-06-26 02:48:02 +0200764 if (curproxy->cookie_name != NULL) {
765 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
766 // file, linenum);
767 // return 0;
768 free(curproxy->cookie_name);
769 }
770
771 if (*(args[1]) == 0) {
772 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
773 file, linenum, args[0]);
774 return -1;
775 }
776 curproxy->cookie_name = strdup(args[1]);
777 curproxy->cookie_len = strlen(curproxy->cookie_name);
778
779 cur_arg = 2;
780 while (*(args[cur_arg])) {
781 if (!strcmp(args[cur_arg], "rewrite")) {
782 curproxy->options |= PR_O_COOK_RW;
783 }
784 else if (!strcmp(args[cur_arg], "indirect")) {
785 curproxy->options |= PR_O_COOK_IND;
786 }
787 else if (!strcmp(args[cur_arg], "insert")) {
788 curproxy->options |= PR_O_COOK_INS;
789 }
790 else if (!strcmp(args[cur_arg], "nocache")) {
791 curproxy->options |= PR_O_COOK_NOC;
792 }
793 else if (!strcmp(args[cur_arg], "postonly")) {
794 curproxy->options |= PR_O_COOK_POST;
795 }
796 else if (!strcmp(args[cur_arg], "prefix")) {
797 curproxy->options |= PR_O_COOK_PFX;
798 }
799 else {
800 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
801 file, linenum, args[0]);
802 return -1;
803 }
804 cur_arg++;
805 }
806 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
807 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
808 file, linenum);
809 return -1;
810 }
811
812 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
813 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
814 file, linenum);
815 return -1;
816 }
817 }/* end else if (!strcmp(args[0], "cookie")) */
818 else if (!strcmp(args[0], "appsession")) { /* cookie name */
819 // if (curproxy == &defproxy) {
820 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
821 // return -1;
822 // }
823
Willy Tarreau977b8e42006-12-29 14:19:17 +0100824 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
825 return 0;
826
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 if (curproxy->appsession_name != NULL) {
828 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
829 // file, linenum);
830 // return 0;
831 free(curproxy->appsession_name);
832 }
833
834 if (*(args[5]) == 0) {
835 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
836 file, linenum, args[0]);
837 return -1;
838 }
839 have_appsession = 1;
840 curproxy->appsession_name = strdup(args[1]);
841 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
842 curproxy->appsession_len = atoi(args[3]);
Willy Tarreauee991362007-05-14 14:37:50 +0200843 val = atoi(args[5]);
844 if (val > 0)
845 __tv_from_ms(&curproxy->appsession_timeout, val);
846 else
847 tv_eternity(&curproxy->appsession_timeout);
848
Willy Tarreau51041c72007-09-09 21:56:53 +0200849 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
850 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200851 return -1;
852 }
853 } /* Url App Session */
854 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100855 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
856 return 0;
857
Willy Tarreaubaaee002006-06-26 02:48:02 +0200858 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
859 // if (curproxy == &defproxy) {
860 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
861 // return -1;
862 // }
863
864 if (curproxy->capture_name != NULL) {
865 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
866 // file, linenum, args[0]);
867 // return 0;
868 free(curproxy->capture_name);
869 }
870
871 if (*(args[4]) == 0) {
872 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
873 file, linenum, args[0]);
874 return -1;
875 }
876 curproxy->capture_name = strdup(args[2]);
877 curproxy->capture_namelen = strlen(curproxy->capture_name);
878 curproxy->capture_len = atol(args[4]);
879 if (curproxy->capture_len >= CAPTURE_LEN) {
880 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
881 file, linenum, CAPTURE_LEN - 1);
882 curproxy->capture_len = CAPTURE_LEN - 1;
883 }
884 curproxy->to_log |= LW_COOKIE;
885 }
886 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
887 struct cap_hdr *hdr;
888
889 if (curproxy == &defproxy) {
890 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
891 return -1;
892 }
893
894 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
895 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
896 file, linenum, args[0], args[1]);
897 return -1;
898 }
899
900 hdr = calloc(sizeof(struct cap_hdr), 1);
901 hdr->next = curproxy->req_cap;
902 hdr->name = strdup(args[3]);
903 hdr->namelen = strlen(args[3]);
904 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200905 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906 hdr->index = curproxy->nb_req_cap++;
907 curproxy->req_cap = hdr;
908 curproxy->to_log |= LW_REQHDR;
909 }
910 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
911 struct cap_hdr *hdr;
912
913 if (curproxy == &defproxy) {
914 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
915 return -1;
916 }
917
918 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
919 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
920 file, linenum, args[0], args[1]);
921 return -1;
922 }
923 hdr = calloc(sizeof(struct cap_hdr), 1);
924 hdr->next = curproxy->rsp_cap;
925 hdr->name = strdup(args[3]);
926 hdr->namelen = strlen(args[3]);
927 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200928 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 hdr->index = curproxy->nb_rsp_cap++;
930 curproxy->rsp_cap = hdr;
931 curproxy->to_log |= LW_RSPHDR;
932 }
933 else {
934 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
935 file, linenum, args[0]);
936 return -1;
937 }
938 }
939 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200940 if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200941 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
942 return 0;
943 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100944 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
945 return 0;
946
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947 if (*(args[1]) == 0) {
948 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
949 file, linenum, args[0]);
950 return -1;
951 }
Willy Tarreauee991362007-05-14 14:37:50 +0200952 val = atoi(args[1]);
953 if (val > 0)
954 __tv_from_ms(&curproxy->contimeout, val);
955 else
956 tv_eternity(&curproxy->contimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
958 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200959 if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
961 file, linenum, args[0]);
962 return 0;
963 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100964 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
965 return 0;
966
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 if (*(args[1]) == 0) {
968 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
969 file, linenum, args[0]);
970 return -1;
971 }
Willy Tarreauee991362007-05-14 14:37:50 +0200972 val = atoi(args[1]);
973 if (val > 0)
974 __tv_from_ms(&curproxy->clitimeout, val);
975 else
976 tv_eternity(&curproxy->clitimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977 }
978 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200979 if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
981 return 0;
982 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100983 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
984 return 0;
985
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 if (*(args[1]) == 0) {
987 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
988 file, linenum, args[0]);
989 return -1;
990 }
Willy Tarreauee991362007-05-14 14:37:50 +0200991 val = atoi(args[1]);
992 if (val > 0)
993 __tv_from_ms(&curproxy->srvtimeout, val);
994 else
995 tv_eternity(&curproxy->srvtimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200996 }
997 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100998 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
999 return 0;
1000
Willy Tarreaubaaee002006-06-26 02:48:02 +02001001 if (*(args[1]) == 0) {
1002 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1003 file, linenum, args[0]);
1004 return -1;
1005 }
1006 curproxy->conn_retries = atol(args[1]);
1007 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001008 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1009 int pol = ACL_COND_NONE;
1010 struct acl_cond *cond;
1011
1012 if (!strcmp(args[1], "if"))
1013 pol = ACL_COND_IF;
1014 else if (!strcmp(args[1], "unless"))
1015 pol = ACL_COND_UNLESS;
1016
1017 if (pol == ACL_COND_NONE) {
1018 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1019 file, linenum, args[0]);
1020 return -1;
1021 }
1022
1023 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1024 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1025 file, linenum);
1026 return -1;
1027 }
1028 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1029 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001030 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1031 int pol = ACL_COND_NONE;
1032 struct acl_cond *cond;
1033 struct switching_rule *rule;
1034
1035 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1036 return 0;
1037
1038 if (*(args[1]) == 0) {
1039 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1040 return -1;
1041 }
1042
1043 if (!strcmp(args[2], "if"))
1044 pol = ACL_COND_IF;
1045 else if (!strcmp(args[2], "unless"))
1046 pol = ACL_COND_UNLESS;
1047
1048 if (pol == ACL_COND_NONE) {
1049 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1050 file, linenum, args[0]);
1051 return -1;
1052 }
1053
1054 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1055 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1056 file, linenum);
1057 return -1;
1058 }
1059
1060 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1061 rule->cond = cond;
1062 rule->be.name = strdup(args[1]);
1063 LIST_INIT(&rule->list);
1064 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1065 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001067 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1068 return 0;
1069
Willy Tarreaubaaee002006-06-26 02:48:02 +02001070 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1071 curproxy->uri_auth = NULL; /* we must detach from the default config */
1072
1073 if (*(args[1]) == 0) {
1074 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1075 return -1;
1076 } else if (!strcmp(args[1], "uri")) {
1077 if (*(args[2]) == 0) {
1078 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1079 return -1;
1080 } else if (!stats_set_uri(&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], "realm")) {
1085 if (*(args[2]) == 0) {
1086 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1087 return -1;
1088 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1089 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1090 return -1;
1091 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001092 } else if (!strcmp(args[1], "refresh")) {
1093 int interval = atoi(args[2]);
1094
1095 if (interval < 0) {
1096 Alert("parsing [%s:%d] : 'refresh' needs a positive interval in seconds.\n", file, linenum);
1097 return -1;
1098 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1099 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1100 return -1;
1101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 } else if (!strcmp(args[1], "auth")) {
1103 if (*(args[2]) == 0) {
1104 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1105 return -1;
1106 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1107 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1108 return -1;
1109 }
1110 } else if (!strcmp(args[1], "scope")) {
1111 if (*(args[2]) == 0) {
1112 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1113 return -1;
1114 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1115 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1116 return -1;
1117 }
1118 } else if (!strcmp(args[1], "enable")) {
1119 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1120 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1121 return -1;
1122 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001123 } else if (!strcmp(args[1], "hide-version")) {
1124 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1125 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1126 return -1;
1127 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001129 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130 file, linenum, args[0]);
1131 return -1;
1132 }
1133 }
1134 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001135 int optnum;
1136
Willy Tarreaubaaee002006-06-26 02:48:02 +02001137 if (*(args[1]) == 0) {
1138 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
1139 return -1;
1140 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001141
1142 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1143 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1144 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1145 return 0;
1146 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001147 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001148 return 0;
1149 }
1150 }
1151
1152 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001153 /* generate a complete HTTP log */
1154 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1155 else if (!strcmp(args[1], "tcplog"))
1156 /* generate a detailed TCP log */
1157 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158 else if (!strcmp(args[1], "tcpka")) {
1159 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001160 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1161 return 0;
1162
1163 if (curproxy->cap & PR_CAP_FE)
1164 curproxy->options |= PR_O_TCP_CLI_KA;
1165 if (curproxy->cap & PR_CAP_BE)
1166 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167 }
1168 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001169 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1170 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001171 /* use HTTP request to check servers' health */
1172 if (curproxy->check_req != NULL) {
1173 free(curproxy->check_req);
1174 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001175 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001176 curproxy->options &= ~PR_O_SMTP_CHK;
1177 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178 if (!*args[2]) { /* no argument */
1179 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1180 curproxy->check_len = strlen(DEF_CHECK_REQ);
1181 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001182 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001183 curproxy->check_req = (char *)malloc(reqlen);
1184 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1185 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1186 } else { /* more arguments : METHOD URI [HTTP_VER] */
1187 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1188 if (*args[4])
1189 reqlen += strlen(args[4]);
1190 else
1191 reqlen += strlen("HTTP/1.0");
1192
1193 curproxy->check_req = (char *)malloc(reqlen);
1194 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1195 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1196 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001197 }
1198 else if (!strcmp(args[1], "ssl-hello-chk")) {
1199 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001200 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1201 return 0;
1202
Willy Tarreauf3c69202006-07-09 16:42:34 +02001203 if (curproxy->check_req != NULL) {
1204 free(curproxy->check_req);
1205 }
1206 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001207 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001208 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001209 }
Willy Tarreau23677902007-05-08 23:50:35 +02001210 else if (!strcmp(args[1], "smtpchk")) {
1211 /* use SMTP request to check servers' health */
1212 if (curproxy->check_req != NULL) {
1213 free(curproxy->check_req);
1214 }
1215 curproxy->options &= ~PR_O_HTTP_CHK;
1216 curproxy->options &= ~PR_O_SSL3_CHK;
1217 curproxy->options |= PR_O_SMTP_CHK;
1218
1219 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1220 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1221 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1222 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1223 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1224 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1225 curproxy->check_req = (char *)malloc(reqlen);
1226 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1227 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1228 } else {
1229 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1230 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1231 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1232 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1233 }
1234 }
1235 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001236 else if (!strcmp(args[1], "forwardfor")) {
1237 /* insert x-forwarded-for field, but not for the
1238 * IP address listed as an except.
1239 */
1240 if (*(args[2])) {
1241 if (!strcmp(args[2], "except")) {
1242 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1243 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1244 file, linenum, args[0]);
1245 return -1;
1246 }
1247 /* flush useless bits */
1248 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1249 } else {
1250 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1251 file, linenum, args[0]);
1252 return -1;
1253 }
1254 }
1255 curproxy->options |= PR_O_FWDFOR;
1256 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001257 else {
1258 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1259 return -1;
1260 }
1261 return 0;
1262 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001263 else if (!strcmp(args[0], "default_backend")) {
1264 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1265 return 0;
1266
1267 if (*(args[1]) == 0) {
1268 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1269 return -1;
1270 }
1271 if (curproxy->defbe.name)
1272 free(curproxy->defbe.name);
1273 curproxy->defbe.name = strdup(args[1]);
1274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001275 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001276 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1277 return 0;
1278
Willy Tarreaubaaee002006-06-26 02:48:02 +02001279 /* enable reconnections to dispatch */
1280 curproxy->options |= PR_O_REDISP;
1281 }
1282#ifdef TPROXY
1283 else if (!strcmp(args[0], "transparent")) {
1284 /* enable transparent proxy connections */
1285 curproxy->options |= PR_O_TRANSP;
1286 }
1287#endif
1288 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001289 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1290 return 0;
1291
Willy Tarreaubaaee002006-06-26 02:48:02 +02001292 if (*(args[1]) == 0) {
1293 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1294 return -1;
1295 }
1296 curproxy->maxconn = atol(args[1]);
1297 }
Willy Tarreau86034312006-12-29 00:10:33 +01001298 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001299 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1300 return 0;
1301
Willy Tarreau86034312006-12-29 00:10:33 +01001302 if (*(args[1]) == 0) {
1303 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1304 return -1;
1305 }
1306 curproxy->fullconn = atol(args[1]);
1307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1309 if (*(args[1]) == 0) {
1310 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1311 return -1;
1312 }
1313 curproxy->grace = atol(args[1]);
1314 }
1315 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1316 if (curproxy == &defproxy) {
1317 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1318 return -1;
1319 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001320 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1321 return 0;
1322
Willy Tarreaubaaee002006-06-26 02:48:02 +02001323 if (strchr(args[1], ':') == NULL) {
1324 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1325 return -1;
1326 }
1327 curproxy->dispatch_addr = *str2sa(args[1]);
1328 }
1329 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001330 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1331 return 0;
1332
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001333 memcpy(trash, "error near 'balance'", 19);
1334 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1335 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1336 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001337 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338 }
1339 else if (!strcmp(args[0], "server")) { /* server address */
1340 int cur_arg;
1341 char *rport;
1342 char *raddr;
1343 short realport;
1344 int do_check;
1345
1346 if (curproxy == &defproxy) {
1347 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1348 return -1;
1349 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001350 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1351 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001352
1353 if (!*args[2]) {
1354 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1355 file, linenum, args[0]);
1356 return -1;
1357 }
1358 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1359 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1360 return -1;
1361 }
1362
1363 /* the servers are linked backwards first */
1364 newsrv->next = curproxy->srv;
1365 curproxy->srv = newsrv;
1366 newsrv->proxy = curproxy;
1367
1368 LIST_INIT(&newsrv->pendconns);
1369 do_check = 0;
1370 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001371 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001372 newsrv->id = strdup(args[1]);
1373
1374 /* several ways to check the port component :
1375 * - IP => port=+0, relative
1376 * - IP: => port=+0, relative
1377 * - IP:N => port=N, absolute
1378 * - IP:+N => port=+N, relative
1379 * - IP:-N => port=-N, relative
1380 */
1381 raddr = strdup(args[2]);
1382 rport = strchr(raddr, ':');
1383 if (rport) {
1384 *rport++ = 0;
1385 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001386 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001387 newsrv->state |= SRV_MAPPORTS;
1388 } else {
1389 realport = 0;
1390 newsrv->state |= SRV_MAPPORTS;
1391 }
1392
1393 newsrv->addr = *str2sa(raddr);
1394 newsrv->addr.sin_port = htons(realport);
1395 free(raddr);
1396
1397 newsrv->curfd = -1; /* no health-check in progress */
1398 newsrv->inter = DEF_CHKINTR;
1399 newsrv->rise = DEF_RISETIME;
1400 newsrv->fall = DEF_FALLTIME;
1401 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001402 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001403 newsrv->maxqueue = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001404
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405 cur_arg = 3;
1406 while (*args[cur_arg]) {
1407 if (!strcmp(args[cur_arg], "cookie")) {
1408 newsrv->cookie = strdup(args[cur_arg + 1]);
1409 newsrv->cklen = strlen(args[cur_arg + 1]);
1410 cur_arg += 2;
1411 }
1412 else if (!strcmp(args[cur_arg], "rise")) {
1413 newsrv->rise = atol(args[cur_arg + 1]);
1414 newsrv->health = newsrv->rise;
1415 cur_arg += 2;
1416 }
1417 else if (!strcmp(args[cur_arg], "fall")) {
1418 newsrv->fall = atol(args[cur_arg + 1]);
1419 cur_arg += 2;
1420 }
1421 else if (!strcmp(args[cur_arg], "inter")) {
1422 newsrv->inter = atol(args[cur_arg + 1]);
1423 cur_arg += 2;
1424 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001425 else if (!strcmp(args[cur_arg], "addr")) {
1426 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001427 cur_arg += 2;
1428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429 else if (!strcmp(args[cur_arg], "port")) {
1430 newsrv->check_port = atol(args[cur_arg + 1]);
1431 cur_arg += 2;
1432 }
1433 else if (!strcmp(args[cur_arg], "backup")) {
1434 newsrv->state |= SRV_BACKUP;
1435 cur_arg ++;
1436 }
1437 else if (!strcmp(args[cur_arg], "weight")) {
1438 int w;
1439 w = atol(args[cur_arg + 1]);
1440 if (w < 1 || w > 256) {
1441 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1442 file, linenum, newsrv->id, w);
1443 return -1;
1444 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001445 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001446 cur_arg += 2;
1447 }
1448 else if (!strcmp(args[cur_arg], "minconn")) {
1449 newsrv->minconn = atol(args[cur_arg + 1]);
1450 cur_arg += 2;
1451 }
1452 else if (!strcmp(args[cur_arg], "maxconn")) {
1453 newsrv->maxconn = atol(args[cur_arg + 1]);
1454 cur_arg += 2;
1455 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001456 else if (!strcmp(args[cur_arg], "maxqueue")) {
1457 newsrv->maxqueue = atol(args[cur_arg + 1]);
1458 cur_arg += 2;
1459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001460 else if (!strcmp(args[cur_arg], "check")) {
1461 global.maxsock++;
1462 do_check = 1;
1463 cur_arg += 1;
1464 }
1465 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1466 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001467#ifdef CONFIG_HAP_CTTPROXY
1468 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1469 file, linenum, "source", "usesrc");
1470#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001471 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1472 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001473#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001474 return -1;
1475 }
1476 newsrv->state |= SRV_BIND_SRC;
1477 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1478 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001479 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001480#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001481 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001482 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1483 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001484 return -1;
1485 }
1486 if (!*args[cur_arg + 1]) {
1487 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1488 file, linenum, "usesrc");
1489 return -1;
1490 }
1491 if (!strcmp(args[cur_arg + 1], "client")) {
1492 newsrv->state |= SRV_TPROXY_CLI;
1493 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1494 newsrv->state |= SRV_TPROXY_CIP;
1495 } else {
1496 newsrv->state |= SRV_TPROXY_ADDR;
1497 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1498 }
1499 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1500 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001501#else /* no CTTPROXY support */
1502 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1503 file, linenum, "usesrc");
1504 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001505#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001507 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001508#ifdef CONFIG_HAP_CTTPROXY
1509 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1510 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1511 file, linenum, "usesrc", "source");
1512 return -1;
1513 }
1514#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515 else {
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001516 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001517 file, linenum, newsrv->id);
1518 return -1;
1519 }
1520 }
1521
1522 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001523 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1524 newsrv->check_port = newsrv->check_addr.sin_port;
1525
Willy Tarreaubaaee002006-06-26 02:48:02 +02001526 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1527 newsrv->check_port = realport; /* by default */
1528 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001529 /* not yet valid, because no port was set on
1530 * the server either. We'll check if we have
1531 * a known port on the first listener.
1532 */
1533 struct listener *l;
1534 l = curproxy->listen;
1535 if (l) {
1536 int port;
1537 port = (l->addr.ss_family == AF_INET6)
1538 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1539 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1540 newsrv->check_port = port;
1541 }
1542 }
1543 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001544 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1545 file, linenum, newsrv->id);
1546 return -1;
1547 }
1548 newsrv->state |= SRV_CHECKED;
1549 }
1550
1551 if (newsrv->state & SRV_BACKUP)
1552 curproxy->srv_bck++;
1553 else
1554 curproxy->srv_act++;
1555 }
1556 else if (!strcmp(args[0], "log")) { /* syslog server address */
1557 struct sockaddr_in *sa;
1558 int facility;
1559
1560 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1561 curproxy->logfac1 = global.logfac1;
1562 curproxy->logsrv1 = global.logsrv1;
1563 curproxy->loglev1 = global.loglev1;
1564 curproxy->logfac2 = global.logfac2;
1565 curproxy->logsrv2 = global.logsrv2;
1566 curproxy->loglev2 = global.loglev2;
1567 }
1568 else if (*(args[1]) && *(args[2])) {
1569 int level;
1570
1571 facility = get_log_facility(args[2]);
1572 if (facility < 0) {
1573 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1574 exit(1);
1575 }
1576
1577 level = 7; /* max syslog level = debug */
1578 if (*(args[3])) {
1579 level = get_log_level(args[3]);
1580 if (level < 0) {
1581 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1582 exit(1);
1583 }
1584 }
1585
1586 sa = str2sa(args[1]);
1587 if (!sa->sin_port)
1588 sa->sin_port = htons(SYSLOG_PORT);
1589
1590 if (curproxy->logfac1 == -1) {
1591 curproxy->logsrv1 = *sa;
1592 curproxy->logfac1 = facility;
1593 curproxy->loglev1 = level;
1594 }
1595 else if (curproxy->logfac2 == -1) {
1596 curproxy->logsrv2 = *sa;
1597 curproxy->logfac2 = facility;
1598 curproxy->loglev2 = level;
1599 }
1600 else {
1601 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1602 return -1;
1603 }
1604 }
1605 else {
1606 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1607 file, linenum);
1608 return -1;
1609 }
1610 }
1611 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001612 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1613 return 0;
1614
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001616#ifdef CONFIG_HAP_CTTPROXY
1617 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1618 file, linenum, "source", "usesrc");
1619#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1621 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001622#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 return -1;
1624 }
1625
1626 curproxy->source_addr = *str2sa(args[1]);
1627 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001628 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001629#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001630 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1631 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1632 file, linenum, "usesrc");
1633 return -1;
1634 }
1635 if (!*args[3]) {
1636 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1637 file, linenum, "usesrc");
1638 return -1;
1639 }
1640
1641 if (!strcmp(args[3], "client")) {
1642 curproxy->options |= PR_O_TPXY_CLI;
1643 } else if (!strcmp(args[3], "clientip")) {
1644 curproxy->options |= PR_O_TPXY_CIP;
1645 } else {
1646 curproxy->options |= PR_O_TPXY_ADDR;
1647 curproxy->tproxy_addr = *str2sa(args[3]);
1648 }
1649 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001650#else /* no CTTPROXY support */
1651 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1652 file, linenum, "usesrc");
1653 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001654#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001655 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001657#ifdef CONFIG_HAP_CTTPROXY
1658 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1659 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1660 file, linenum, "usesrc", "source");
1661 return -1;
1662 }
1663#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001664 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1665 regex_t *preg;
1666 if (curproxy == &defproxy) {
1667 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1668 return -1;
1669 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001670 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1671 return 0;
1672
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 if (*(args[1]) == 0 || *(args[2]) == 0) {
1674 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1675 file, linenum, args[0]);
1676 return -1;
1677 }
1678
1679 preg = calloc(1, sizeof(regex_t));
1680 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1681 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1682 return -1;
1683 }
1684
1685 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1686 if (err) {
1687 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1688 file, linenum, *err);
1689 return -1;
1690 }
1691 }
1692 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1693 regex_t *preg;
1694 if (curproxy == &defproxy) {
1695 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1696 return -1;
1697 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001698 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1699 return 0;
1700
Willy Tarreaubaaee002006-06-26 02:48:02 +02001701 if (*(args[1]) == 0) {
1702 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1703 return -1;
1704 }
1705
1706 preg = calloc(1, sizeof(regex_t));
1707 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1708 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1709 return -1;
1710 }
1711
1712 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1713 }
1714 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1715 regex_t *preg;
1716 if (curproxy == &defproxy) {
1717 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1718 return -1;
1719 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001720 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1721 return 0;
1722
Willy Tarreaubaaee002006-06-26 02:48:02 +02001723 if (*(args[1]) == 0) {
1724 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1725 return -1;
1726 }
1727
1728 preg = calloc(1, sizeof(regex_t));
1729 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1730 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1731 return -1;
1732 }
1733
1734 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1735 }
1736 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1737 regex_t *preg;
1738 if (curproxy == &defproxy) {
1739 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1740 return -1;
1741 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001742 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1743 return 0;
1744
Willy Tarreaubaaee002006-06-26 02:48:02 +02001745 if (*(args[1]) == 0) {
1746 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1747 return -1;
1748 }
1749
1750 preg = calloc(1, sizeof(regex_t));
1751 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1752 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1753 return -1;
1754 }
1755
1756 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1757 }
1758 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1759 regex_t *preg;
1760 if (curproxy == &defproxy) {
1761 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1762 return -1;
1763 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001764 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1765 return 0;
1766
Willy Tarreaubaaee002006-06-26 02:48:02 +02001767 if (*(args[1]) == 0) {
1768 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1769 return -1;
1770 }
1771
1772 preg = calloc(1, sizeof(regex_t));
1773 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1774 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1775 return -1;
1776 }
1777
1778 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1779 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001780 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1781 regex_t *preg;
1782 if (curproxy == &defproxy) {
1783 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1784 return -1;
1785 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001786 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1787 return 0;
1788
Willy Tarreaub8750a82006-09-03 09:56:00 +02001789 if (*(args[1]) == 0) {
1790 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1791 return -1;
1792 }
1793
1794 preg = calloc(1, sizeof(regex_t));
1795 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1796 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1797 return -1;
1798 }
1799
1800 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1801 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001802 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1803 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001804 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001805 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1806 return -1;
1807 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001808 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1809 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001810
Willy Tarreau977b8e42006-12-29 14:19:17 +01001811 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001812 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1813 file, linenum, args[0]);
1814 return -1;
1815 }
1816
1817 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001818 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001819 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1820 }
1821
1822 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1823 }
1824 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1825 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001826 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001827 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1828 return -1;
1829 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001830 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1831 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001832
Willy Tarreau977b8e42006-12-29 14:19:17 +01001833 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001834 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1835 file, linenum, args[0]);
1836 return -1;
1837 }
1838
1839 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001840 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001841 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1842 }
1843
1844 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1845 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001846 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1847 regex_t *preg;
1848 if (curproxy == &defproxy) {
1849 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1850 return -1;
1851 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001852 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1853 return 0;
1854
Willy Tarreaubaaee002006-06-26 02:48:02 +02001855 if (*(args[1]) == 0 || *(args[2]) == 0) {
1856 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1857 file, linenum, args[0]);
1858 return -1;
1859 }
1860
1861 preg = calloc(1, sizeof(regex_t));
1862 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1863 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1864 return -1;
1865 }
1866
1867 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1868 if (err) {
1869 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1870 file, linenum, *err);
1871 return -1;
1872 }
1873 }
1874 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1875 regex_t *preg;
1876 if (curproxy == &defproxy) {
1877 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1878 return -1;
1879 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001880 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1881 return 0;
1882
Willy Tarreaubaaee002006-06-26 02:48:02 +02001883 if (*(args[1]) == 0) {
1884 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1885 return -1;
1886 }
1887
1888 preg = calloc(1, sizeof(regex_t));
1889 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1890 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1891 return -1;
1892 }
1893
1894 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1895 }
1896 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1897 regex_t *preg;
1898 if (curproxy == &defproxy) {
1899 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1900 return -1;
1901 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001902 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1903 return 0;
1904
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905 if (*(args[1]) == 0) {
1906 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1907 return -1;
1908 }
1909
1910 preg = calloc(1, sizeof(regex_t));
1911 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1912 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1913 return -1;
1914 }
1915
1916 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1917 }
1918 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1919 regex_t *preg;
1920 if (curproxy == &defproxy) {
1921 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1922 return -1;
1923 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001924 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1925 return 0;
1926
Willy Tarreaubaaee002006-06-26 02:48:02 +02001927 if (*(args[1]) == 0) {
1928 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1929 return -1;
1930 }
1931
1932 preg = calloc(1, sizeof(regex_t));
1933 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1934 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1935 return -1;
1936 }
1937
1938 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1939 }
1940 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1941 regex_t *preg;
1942 if (curproxy == &defproxy) {
1943 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1944 return -1;
1945 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001946 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1947 return 0;
1948
Willy Tarreaubaaee002006-06-26 02:48:02 +02001949 if (*(args[1]) == 0) {
1950 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1951 return -1;
1952 }
1953
1954 preg = calloc(1, sizeof(regex_t));
1955 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1956 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1957 return -1;
1958 }
1959
1960 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1961 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001962 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1963 regex_t *preg;
1964 if (curproxy == &defproxy) {
1965 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1966 return -1;
1967 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001968 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1969 return 0;
1970
Willy Tarreaub8750a82006-09-03 09:56:00 +02001971 if (*(args[1]) == 0) {
1972 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1973 return -1;
1974 }
1975
1976 preg = calloc(1, sizeof(regex_t));
1977 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1978 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1979 return -1;
1980 }
1981
1982 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1983 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001984 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1985 if (curproxy == &defproxy) {
1986 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1987 return -1;
1988 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001989 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1990 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991
1992 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
1993 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1994 return 0;
1995 }
1996
1997 if (*(args[1]) == 0) {
1998 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1999 return -1;
2000 }
2001
2002 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2003 }
2004 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2005 regex_t *preg;
2006
2007 if (*(args[1]) == 0 || *(args[2]) == 0) {
2008 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2009 file, linenum, args[0]);
2010 return -1;
2011 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002012 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2013 return 0;
2014
Willy Tarreaubaaee002006-06-26 02:48:02 +02002015 preg = calloc(1, sizeof(regex_t));
2016 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2017 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2018 return -1;
2019 }
2020
2021 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2022 if (err) {
2023 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2024 file, linenum, *err);
2025 return -1;
2026 }
2027 }
2028 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2029 regex_t *preg;
2030 if (curproxy == &defproxy) {
2031 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2032 return -1;
2033 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002034 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2035 return 0;
2036
Willy Tarreaubaaee002006-06-26 02:48:02 +02002037 if (*(args[1]) == 0) {
2038 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2039 return -1;
2040 }
2041
2042 preg = calloc(1, sizeof(regex_t));
2043 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2044 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2045 return -1;
2046 }
2047
2048 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2049 if (err) {
2050 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2051 file, linenum, *err);
2052 return -1;
2053 }
2054 }
2055 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2056 regex_t *preg;
2057 if (curproxy == &defproxy) {
2058 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2059 return -1;
2060 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002061 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2062 return 0;
2063
Willy Tarreaubaaee002006-06-26 02:48:02 +02002064 if (*(args[1]) == 0) {
2065 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2066 return -1;
2067 }
2068
2069 preg = calloc(1, sizeof(regex_t));
2070 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2071 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2072 return -1;
2073 }
2074
2075 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2076 if (err) {
2077 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2078 file, linenum, *err);
2079 return -1;
2080 }
2081 }
2082 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2083 regex_t *preg;
2084 if (curproxy == &defproxy) {
2085 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2086 return -1;
2087 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002088 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2089 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002090
2091 if (*(args[1]) == 0 || *(args[2]) == 0) {
2092 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2093 file, linenum, args[0]);
2094 return -1;
2095 }
2096
2097 preg = calloc(1, sizeof(regex_t));
2098 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2099 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2100 return -1;
2101 }
2102
2103 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2104 if (err) {
2105 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2106 file, linenum, *err);
2107 return -1;
2108 }
2109 }
2110 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2111 regex_t *preg;
2112 if (curproxy == &defproxy) {
2113 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2114 return -1;
2115 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002116 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2117 return 0;
2118
Willy Tarreaubaaee002006-06-26 02:48:02 +02002119 if (*(args[1]) == 0) {
2120 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2121 return -1;
2122 }
2123
2124 preg = calloc(1, sizeof(regex_t));
2125 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2126 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2127 return -1;
2128 }
2129
2130 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2131 if (err) {
2132 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2133 file, linenum, *err);
2134 return -1;
2135 }
2136 }
2137 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2138 regex_t *preg;
2139 if (curproxy == &defproxy) {
2140 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2141 return -1;
2142 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002143 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2144 return 0;
2145
Willy Tarreaubaaee002006-06-26 02:48:02 +02002146 if (*(args[1]) == 0) {
2147 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2148 return -1;
2149 }
2150
2151 preg = calloc(1, sizeof(regex_t));
2152 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2153 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2154 return -1;
2155 }
2156
2157 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2158 if (err) {
2159 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2160 file, linenum, *err);
2161 return -1;
2162 }
2163 }
2164 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2165 if (curproxy == &defproxy) {
2166 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2167 return -1;
2168 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002169 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2170 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171
2172 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2173 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2174 return 0;
2175 }
2176
2177 if (*(args[1]) == 0) {
2178 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2179 return -1;
2180 }
2181
2182 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2183 }
2184 else if (!strcmp(args[0], "errorloc") ||
2185 !strcmp(args[0], "errorloc302") ||
2186 !strcmp(args[0], "errorloc303")) { /* error location */
2187 int errnum, errlen;
2188 char *err;
2189
Willy Tarreau977b8e42006-12-29 14:19:17 +01002190 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2191 return 0;
2192
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002194 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002195 return -1;
2196 }
2197
2198 errnum = atol(args[1]);
2199 if (!strcmp(args[0], "errorloc303")) {
2200 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2201 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2202 } else {
2203 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2204 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2205 }
2206
Willy Tarreau0f772532006-12-23 20:51:41 +01002207 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2208 if (http_err_codes[rc] == errnum) {
2209 if (curproxy->errmsg[rc].str)
2210 free(curproxy->errmsg[rc].str);
2211 curproxy->errmsg[rc].str = err;
2212 curproxy->errmsg[rc].len = errlen;
2213 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002216
2217 if (rc >= HTTP_ERR_SIZE) {
2218 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2219 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220 free(err);
2221 }
2222 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002223 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2224 int errnum, errlen, fd;
2225 char *err;
2226 struct stat stat;
2227
2228 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2229 return 0;
2230
2231 if (*(args[2]) == 0) {
2232 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2233 return -1;
2234 }
2235
2236 fd = open(args[2], O_RDONLY);
2237 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2238 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2239 file, linenum, args[2], args[1]);
2240 if (fd >= 0)
2241 close(fd);
2242 return -1;
2243 }
2244
2245 if (stat.st_size <= BUFSIZE) {
2246 errlen = stat.st_size;
2247 } else {
2248 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2249 file, linenum, args[2], BUFSIZE);
2250 errlen = BUFSIZE;
2251 }
2252
2253 err = malloc(errlen); /* malloc() must succeed during parsing */
2254 errnum = read(fd, err, errlen);
2255 if (errnum != errlen) {
2256 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2257 file, linenum, args[2], args[1]);
2258 close(fd);
2259 free(err);
2260 return -1;
2261 }
2262 close(fd);
2263
2264 errnum = atol(args[1]);
2265 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2266 if (http_err_codes[rc] == errnum) {
2267 if (curproxy->errmsg[rc].str)
2268 free(curproxy->errmsg[rc].str);
2269 curproxy->errmsg[rc].str = err;
2270 curproxy->errmsg[rc].len = errlen;
2271 break;
2272 }
2273 }
2274
2275 if (rc >= HTTP_ERR_SIZE) {
2276 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2277 file, linenum, errnum);
2278 free(err);
2279 }
2280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002281 else {
2282 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2283 return -1;
2284 }
2285 return 0;
2286}
2287
2288
2289/*
2290 * This function reads and parses the configuration file given in the argument.
2291 * returns 0 if OK, -1 if error.
2292 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002293int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002295 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296 FILE *f;
2297 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002299 int confsect = CFG_NONE;
2300
2301 struct proxy *curproxy = NULL;
2302 struct server *newsrv = NULL;
2303
2304 if ((f=fopen(file,"r")) == NULL)
2305 return -1;
2306
2307 init_default_instance();
2308
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002309 while (fgets(thisline, sizeof(thisline), f) != NULL) {
2310 int arg;
2311 char *end;
2312 char *args[MAX_LINE_ARGS + 1];
2313 char *line = thisline;
2314
Willy Tarreaubaaee002006-06-26 02:48:02 +02002315 linenum++;
2316
2317 end = line + strlen(line);
2318
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002319 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2320 /* Check if we reached the limit and the last char is not \n.
2321 * Watch out for the last line without the terminating '\n'!
2322 */
2323 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2324 file, linenum, sizeof(thisline)-1);
2325 return -1;
2326 }
2327
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002329 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 line++;
2331
2332 arg = 0;
2333 args[arg] = line;
2334
2335 while (*line && arg < MAX_LINE_ARGS) {
2336 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2337 * C equivalent value. Other combinations left unchanged (eg: \1).
2338 */
2339 if (*line == '\\') {
2340 int skip = 0;
2341 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2342 *line = line[1];
2343 skip = 1;
2344 }
2345 else if (line[1] == 'r') {
2346 *line = '\r';
2347 skip = 1;
2348 }
2349 else if (line[1] == 'n') {
2350 *line = '\n';
2351 skip = 1;
2352 }
2353 else if (line[1] == 't') {
2354 *line = '\t';
2355 skip = 1;
2356 }
2357 else if (line[1] == 'x') {
2358 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2359 unsigned char hex1, hex2;
2360 hex1 = toupper(line[2]) - '0';
2361 hex2 = toupper(line[3]) - '0';
2362 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2363 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2364 *line = (hex1<<4) + hex2;
2365 skip = 3;
2366 }
2367 else {
2368 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2369 return -1;
2370 }
2371 }
2372 if (skip) {
2373 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2374 end -= skip;
2375 }
2376 line++;
2377 }
2378 else if (*line == '#' || *line == '\n' || *line == '\r') {
2379 /* end of string, end of loop */
2380 *line = 0;
2381 break;
2382 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002383 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002385 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002386 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387 line++;
2388 args[++arg] = line;
2389 }
2390 else {
2391 line++;
2392 }
2393 }
2394
2395 /* empty line */
2396 if (!**args)
2397 continue;
2398
Willy Tarreau540abe42007-05-02 20:50:16 +02002399 /* zero out remaining args and ensure that at least one entry
2400 * is zeroed out.
2401 */
2402 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 args[arg] = line;
2404 }
2405
Willy Tarreau977b8e42006-12-29 14:19:17 +01002406 if (!strcmp(args[0], "listen") ||
2407 !strcmp(args[0], "frontend") ||
2408 !strcmp(args[0], "backend") ||
2409 !strcmp(args[0], "ruleset") ||
2410 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 confsect = CFG_LISTEN;
2412 else if (!strcmp(args[0], "global")) /* global config */
2413 confsect = CFG_GLOBAL;
2414 /* else it's a section keyword */
2415
2416 switch (confsect) {
2417 case CFG_LISTEN:
2418 if (cfg_parse_listen(file, linenum, args) < 0)
2419 return -1;
2420 break;
2421 case CFG_GLOBAL:
2422 if (cfg_parse_global(file, linenum, args) < 0)
2423 return -1;
2424 break;
2425 default:
2426 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2427 return -1;
2428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 }
2430 fclose(f);
2431
2432 /*
2433 * Now, check for the integrity of all that we have collected.
2434 */
2435
2436 /* will be needed further to delay some tasks */
2437 tv_now(&now);
2438
2439 if ((curproxy = proxy) == NULL) {
2440 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2441 file);
2442 return -1;
2443 }
2444
2445 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002446 struct switching_rule *rule;
2447
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 if (curproxy->state == PR_STSTOPPED) {
2449 curproxy = curproxy->next;
2450 continue;
2451 }
2452
Willy Tarreau977b8e42006-12-29 14:19:17 +01002453 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2454 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 +01002455 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002456 cfgerr++;
2457 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002458 else if (curproxy->cap & PR_CAP_BE &&
2459 ((curproxy->mode != PR_MODE_HEALTH) &&
2460 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
2461 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2462 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 +01002463 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002464 cfgerr++;
2465 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002466
2467 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002469 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002470 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 cfgerr++;
2472 }
2473#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2474 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002475 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002476 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 cfgerr++;
2478 }
2479#endif
2480 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002481 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002482 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483 }
2484 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002485
2486 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002487 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002488 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002489 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002492 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002493 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494 }
2495 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002496 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002497 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002498 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002499 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002500 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002501 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002502 }
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002503 if (curproxy->options & PR_O_BALANCE_L7) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002504 curproxy->options &= ~PR_O_BALANCE;
2505 curproxy->options |= PR_O_BALANCE_RR;
2506
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002507 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002508 file, proxy_type_str(curproxy), curproxy->id);
2509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002510 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002511
2512 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2513 if ((newsrv = curproxy->srv) != NULL) {
2514 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2515 file, proxy_type_str(curproxy), curproxy->id);
2516 }
2517 }
2518
2519 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002520 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2521 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2522 file, curproxy->id);
2523 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002524 }
2525 }
2526
2527 /* if a default backend was specified, let's find it */
2528 if (curproxy->defbe.name) {
2529 struct proxy *target;
2530
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002531 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2532 if (!target) {
2533 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2534 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002535 cfgerr++;
2536 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002537 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2538 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002539 } else {
2540 free(curproxy->defbe.name);
2541 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 }
2543 }
2544
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002545 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002546 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2547 /* map jump target for ACT_SETBE in req_rep chain */
2548 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002549 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002550 struct proxy *target;
2551
Willy Tarreaua496b602006-12-17 23:15:24 +01002552 if (exp->action != ACT_SETBE)
2553 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002554
2555 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2556 if (!target) {
2557 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2558 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002559 cfgerr++;
2560 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002561 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2562 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002563 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002564 } else {
2565 free((void *)exp->replace);
2566 exp->replace = (const char *)target;
2567 }
2568 }
2569 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002570
2571 /* find the target proxy for 'use_backend' rules */
2572 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002573 struct proxy *target;
2574
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002575 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002576
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002577 if (!target) {
2578 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2579 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002580 cfgerr++;
2581 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002582 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2583 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002584 cfgerr++;
2585 } else {
2586 free((void *)rule->be.name);
2587 rule->be.backend = target;
2588 }
2589 }
2590
Willy Tarreau2738a142006-07-08 17:28:09 +02002591 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002592 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2593 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2594 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002595 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002596 " | While not properly invalid, you will certainly encounter various problems\n"
2597 " | with such a configuration. To fix this, please ensure that all following\n"
2598 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002599 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002600 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002601
2602 if (curproxy->options & PR_O_SSL3_CHK) {
2603 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2604 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2605 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2606 }
2607
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002608 /* The small pools required for the capture lists */
2609 if (curproxy->nb_req_cap)
2610 curproxy->req_cap_pool = create_pool("ptrcap",
2611 curproxy->nb_req_cap * sizeof(char *),
2612 MEM_F_SHARED);
2613 if (curproxy->nb_rsp_cap)
2614 curproxy->rsp_cap_pool = create_pool("ptrcap",
2615 curproxy->nb_rsp_cap * sizeof(char *),
2616 MEM_F_SHARED);
2617
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002618 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2619 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2620 MEM_F_SHARED);
2621
Willy Tarreau86034312006-12-29 00:10:33 +01002622 /* for backwards compatibility with "listen" instances, if
2623 * fullconn is not set but maxconn is set, then maxconn
2624 * is used.
2625 */
2626 if (!curproxy->fullconn)
2627 curproxy->fullconn = curproxy->maxconn;
2628
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629 /* first, we will invert the servers list order */
2630 newsrv = NULL;
2631 while (curproxy->srv) {
2632 struct server *next;
2633
2634 next = curproxy->srv->next;
2635 curproxy->srv->next = newsrv;
2636 newsrv = curproxy->srv;
2637 if (!next)
2638 break;
2639 curproxy->srv = next;
2640 }
2641
2642 /* now, newsrv == curproxy->srv */
2643 if (newsrv) {
2644 struct server *srv;
2645 int pgcd;
2646 int act, bck;
2647
2648 /* We will factor the weights to reduce the table,
2649 * using Euclide's largest common divisor algorithm
2650 */
Willy Tarreau417fae02007-03-25 21:16:40 +02002651 pgcd = newsrv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002652 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2653 int t, w;
2654
Willy Tarreau417fae02007-03-25 21:16:40 +02002655 w = srv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002656 while (w) {
2657 t = pgcd % w;
2658 pgcd = w;
2659 w = t;
2660 }
2661 }
2662
2663 act = bck = 0;
2664 for (srv = newsrv; srv; srv = srv->next) {
Willy Tarreau417fae02007-03-25 21:16:40 +02002665 srv->eweight = srv->uweight / pgcd;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666 if (srv->state & SRV_BACKUP)
Willy Tarreau417fae02007-03-25 21:16:40 +02002667 bck += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668 else
Willy Tarreau417fae02007-03-25 21:16:40 +02002669 act += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002670 }
2671
2672 /* this is the largest map we will ever need for this servers list */
2673 if (act < bck)
2674 act = bck;
2675
2676 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2677 /* recounts servers and their weights */
Willy Tarreau5af3a692007-07-24 23:32:33 +02002678 curproxy->map_state = PR_MAP_RECALC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 recount_servers(curproxy);
2680 recalc_server_map(curproxy);
2681 }
2682
2683 if (curproxy->options & PR_O_LOGASAP)
2684 curproxy->to_log &= ~LW_BYTES;
2685
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686 /*
2687 * If this server supports a maxconn parameter, it needs a dedicated
2688 * tasks to fill the emptied slots when a connection leaves.
2689 */
2690 newsrv = curproxy->srv;
2691 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002692 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002693 /* Only 'minconn' was specified, or it was higher than or equal
2694 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2695 * this will avoid further useless expensive computations.
2696 */
2697 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002698 } else if (newsrv->maxconn && !newsrv->minconn) {
2699 /* minconn was not specified, so we set it to maxconn */
2700 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002701 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2702 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002703 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002704 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 }
2706
2707 if (newsrv->maxconn > 0) {
2708 struct task *t;
2709
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002710 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002711 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2712 return -1;
2713 }
2714
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002715 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002716 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002717 t->state = TASK_IDLE;
2718 t->process = process_srv_queue;
2719 t->context = newsrv;
2720 newsrv->queue_mgt = t;
2721
2722 /* never run it unless specifically woken up */
2723 tv_eternity(&t->expire);
2724 task_queue(t);
2725 }
2726 newsrv = newsrv->next;
2727 }
2728
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 curproxy = curproxy->next;
2730 }
2731 if (cfgerr > 0) {
2732 Alert("Errors found in configuration file, aborting.\n");
2733 return -1;
2734 }
2735 else
2736 return 0;
2737}
2738
2739
2740
2741/*
2742 * Local variables:
2743 * c-indent-level: 8
2744 * c-basic-offset: 8
2745 * End:
2746 */