blob: affb9569a829d38bc03d94b830d10aff241ae038 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau0b4ed902007-03-26 00:18:40 +02004 * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
27#include <common/config.h>
28#include <common/memory.h>
29#include <common/standard.h>
30#include <common/time.h>
31#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020032
33#include <types/capture.h>
34#include <types/global.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010035#include <types/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <types/polling.h>
37#include <types/proxy.h>
38#include <types/queue.h>
39
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010045#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020046#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010047#include <proto/protocols.h>
48#include <proto/proto_tcp.h>
49#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010050#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/server.h>
52#include <proto/task.h>
53
54
Willy Tarreauf3c69202006-07-09 16:42:34 +020055/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
56 * ssl-hello-chk option to ensure that the remote server speaks SSL.
57 *
58 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
59 */
60const char sslv3_client_hello_pkt[] = {
61 "\x16" /* ContentType : 0x16 = Hanshake */
62 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
63 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
64 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
65 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
66 "\x03\x00" /* Hello Version : 0x0300 = v3 */
67 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
68 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
69 "\x00" /* Session ID length : empty (no session ID) */
70 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
71 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
72 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
73 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
74 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
75 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
76 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
77 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
78 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
79 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
80 "\x00\x38" "\x00\x39" "\x00\x3A"
81 "\x01" /* Compression Length : 0x01 = 1 byte for types */
82 "\x00" /* Compression Type : 0x00 = NULL compression */
83};
84
Willy Tarreau13943ab2006-12-31 00:24:10 +010085/* some of the most common options which are also the easiest to handle */
86static const struct {
87 const char *name;
88 unsigned int val;
89 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010090 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010091} cfg_opts[] =
92{
93#ifdef TPROXY
94 { "transparent", PR_O_TRANSP, PR_CAP_FE },
95#endif
Willy Tarreau4fee4e92007-01-06 21:09:17 +010096 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
97 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010098 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
Alexandre Cassen87ea5482007-10-11 20:48:58 +020099 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Alexandre Cassen5eb1a902007-11-29 15:43:32 +0100100 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100101 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100102 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100103 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
104 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
105 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
106 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
107 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
108 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
109 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
110 { "forceclose", PR_O_FORCE_CLO | PR_O_HTTP_CLOSE, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100111#ifdef CONFIG_HAP_TCPSPLICE
112 { "tcpsplice", PR_O_TCPSPLICE , PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
113#endif
114
Willy Tarreau13943ab2006-12-31 00:24:10 +0100115 { NULL, 0, 0 }
116};
117
Willy Tarreaubaaee002006-06-26 02:48:02 +0200118
119static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
120int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
121int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
122
123/*
124 * converts <str> to a list of listeners which are dynamically allocated.
125 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
126 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
127 * - <port> is a numerical port from 1 to 65535 ;
128 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
129 * This can be repeated as many times as necessary, separated by a coma.
130 * The <tail> argument is a pointer to a current list which should be appended
131 * to the tail of the new list. The pointer to the new list is returned.
132 */
133static struct listener *str2listener(char *str, struct listener *tail)
134{
135 struct listener *l;
136 char *c, *next, *range, *dupstr;
137 int port, end;
138
139 next = dupstr = strdup(str);
140
141 while (next && *next) {
142 struct sockaddr_storage ss;
143
144 str = next;
145 /* 1) look for the end of the first address */
146 if ((next = strrchr(str, ',')) != NULL) {
147 *next++ = 0;
148 }
149
150 /* 2) look for the addr/port delimiter, it's the last colon. */
151 if ((range = strrchr(str, ':')) == NULL) {
152 Alert("Missing port number: '%s'\n", str);
153 goto fail;
154 }
155
156 *range++ = 0;
157
158 if (strrchr(str, ':') != NULL) {
159 /* IPv6 address contains ':' */
160 memset(&ss, 0, sizeof(ss));
161 ss.ss_family = AF_INET6;
162
163 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
164 Alert("Invalid server address: '%s'\n", str);
165 goto fail;
166 }
167 }
168 else {
169 memset(&ss, 0, sizeof(ss));
170 ss.ss_family = AF_INET;
171
172 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
173 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
174 }
175 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
176 struct hostent *he;
177
178 if ((he = gethostbyname(str)) == NULL) {
179 Alert("Invalid server name: '%s'\n", str);
180 goto fail;
181 }
182 else
183 ((struct sockaddr_in *)&ss)->sin_addr =
184 *(struct in_addr *) *(he->h_addr_list);
185 }
186 }
187
188 /* 3) look for the port-end delimiter */
189 if ((c = strchr(range, '-')) != NULL) {
190 *c++ = 0;
191 end = atol(c);
192 }
193 else {
194 end = atol(range);
195 }
196
197 port = atol(range);
198
199 if (port < 1 || port > 65535) {
200 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
201 goto fail;
202 }
203
204 if (end < 1 || end > 65535) {
205 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
206 goto fail;
207 }
208
209 for (; port <= end; port++) {
210 l = (struct listener *)calloc(1, sizeof(struct listener));
211 l->next = tail;
212 tail = l;
213
214 l->fd = -1;
215 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100216 l->state = LI_INIT;
217
218 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100220 tcpv6_add_listener(l);
221 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100223 tcpv4_add_listener(l);
224 }
225 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 } /* end for(port) */
227 } /* end while(next) */
228 free(dupstr);
229 return tail;
230 fail:
231 free(dupstr);
232 return NULL;
233}
234
Willy Tarreau977b8e42006-12-29 14:19:17 +0100235/*
236 * Sends a warning if proxy <proxy> does not have at least one of the
237 * capabilities in <cap>. An optionnal <hint> may be added at the end
238 * of the warning to help the user. Returns 1 if a warning was emitted
239 * or 0 if the condition is valid.
240 */
241int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
242{
243 char *msg;
244
245 switch (cap) {
246 case PR_CAP_BE: msg = "no backend"; break;
247 case PR_CAP_FE: msg = "no frontend"; break;
248 case PR_CAP_RS: msg = "no ruleset"; break;
249 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
250 default: msg = "not enough"; break;
251 }
252
253 if (!(proxy->cap & cap)) {
254 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100255 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100256 return 1;
257 }
258 return 0;
259}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200260
261/*
262 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
263 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200264int cfg_parse_global(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265{
266
267 if (!strcmp(args[0], "global")) { /* new section */
268 /* no option, nothing special to do */
269 return 0;
270 }
271 else if (!strcmp(args[0], "daemon")) {
272 global.mode |= MODE_DAEMON;
273 }
274 else if (!strcmp(args[0], "debug")) {
275 global.mode |= MODE_DEBUG;
276 }
277 else if (!strcmp(args[0], "noepoll")) {
278 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
279 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200280 else if (!strcmp(args[0], "nosepoll")) {
281 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
282 }
283 else if (!strcmp(args[0], "nokqueue")) {
284 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286 else if (!strcmp(args[0], "nopoll")) {
287 cfg_polling_mechanism &= ~POLL_USE_POLL;
288 }
289 else if (!strcmp(args[0], "quiet")) {
290 global.mode |= MODE_QUIET;
291 }
292 else if (!strcmp(args[0], "stats")) {
Willy Tarreaufbee7132007-10-18 13:53:22 +0200293 memcpy(trash, "error near 'stats'", 19);
294 if (stats_parse_global((const char **)args + 1, trash, sizeof(trash)) < 0) {
295 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
296 return -1;
297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200299 else if (!strcmp(args[0], "tune.maxpollevents")) {
300 if (global.tune.maxpollevents != 0) {
301 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
302 return 0;
303 }
304 if (*(args[1]) == 0) {
305 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
306 return -1;
307 }
308 global.tune.maxpollevents = atol(args[1]);
309 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200310 else if (!strcmp(args[0], "uid")) {
311 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200312 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200313 return 0;
314 }
315 if (*(args[1]) == 0) {
316 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
317 return -1;
318 }
319 global.uid = atol(args[1]);
320 }
321 else if (!strcmp(args[0], "gid")) {
322 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200323 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324 return 0;
325 }
326 if (*(args[1]) == 0) {
327 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
328 return -1;
329 }
330 global.gid = atol(args[1]);
331 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200332 /* user/group name handling */
333 else if (!strcmp(args[0], "user")) {
334 struct passwd *ha_user;
335 if (global.uid != 0) {
336 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
337 return 0;
338 }
339 errno = 0;
340 ha_user = getpwnam(args[1]);
341 if (ha_user != NULL) {
342 global.uid = (int)ha_user->pw_uid;
343 }
344 else {
345 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
346 exit(1);
347 }
348 }
349 else if (!strcmp(args[0], "group")) {
350 struct group *ha_group;
351 if (global.gid != 0) {
352 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
353 return 0;
354 }
355 errno = 0;
356 ha_group = getgrnam(args[1]);
357 if (ha_group != NULL) {
358 global.gid = (int)ha_group->gr_gid;
359 }
360 else {
361 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
362 exit(1);
363 }
364 }
365 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200366 else if (!strcmp(args[0], "nbproc")) {
367 if (global.nbproc != 0) {
368 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
369 return 0;
370 }
371 if (*(args[1]) == 0) {
372 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
373 return -1;
374 }
375 global.nbproc = atol(args[1]);
376 }
377 else if (!strcmp(args[0], "maxconn")) {
378 if (global.maxconn != 0) {
379 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
380 return 0;
381 }
382 if (*(args[1]) == 0) {
383 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
384 return -1;
385 }
386 global.maxconn = atol(args[1]);
387#ifdef SYSTEM_MAXCONN
388 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
389 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);
390 global.maxconn = DEFAULT_MAXCONN;
391 }
392#endif /* SYSTEM_MAXCONN */
393 }
394 else if (!strcmp(args[0], "ulimit-n")) {
395 if (global.rlimit_nofile != 0) {
396 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
397 return 0;
398 }
399 if (*(args[1]) == 0) {
400 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
401 return -1;
402 }
403 global.rlimit_nofile = atol(args[1]);
404 }
405 else if (!strcmp(args[0], "chroot")) {
406 if (global.chroot != NULL) {
407 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
408 return 0;
409 }
410 if (*(args[1]) == 0) {
411 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
412 return -1;
413 }
414 global.chroot = strdup(args[1]);
415 }
416 else if (!strcmp(args[0], "pidfile")) {
417 if (global.pidfile != NULL) {
418 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
419 return 0;
420 }
421 if (*(args[1]) == 0) {
422 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
423 return -1;
424 }
425 global.pidfile = strdup(args[1]);
426 }
427 else if (!strcmp(args[0], "log")) { /* syslog server address */
428 struct sockaddr_in *sa;
429 int facility, level;
430
431 if (*(args[1]) == 0 || *(args[2]) == 0) {
432 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
433 return -1;
434 }
435
436 facility = get_log_facility(args[2]);
437 if (facility < 0) {
438 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
439 exit(1);
440 }
441
442 level = 7; /* max syslog level = debug */
443 if (*(args[3])) {
444 level = get_log_level(args[3]);
445 if (level < 0) {
446 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
447 exit(1);
448 }
449 }
450
451 sa = str2sa(args[1]);
452 if (!sa->sin_port)
453 sa->sin_port = htons(SYSLOG_PORT);
454
455 if (global.logfac1 == -1) {
456 global.logsrv1 = *sa;
457 global.logfac1 = facility;
458 global.loglev1 = level;
459 }
460 else if (global.logfac2 == -1) {
461 global.logsrv2 = *sa;
462 global.logfac2 = facility;
463 global.loglev2 = level;
464 }
465 else {
466 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
467 return -1;
468 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200469 }
470 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
471 if (global.spread_checks != 0) {
472 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
473 return 0;
474 }
475 if (*(args[1]) == 0) {
476 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
477 return -1;
478 }
479 global.spread_checks = atol(args[1]);
480 if (global.spread_checks < 0 || global.spread_checks > 50) {
481 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
482 return -1;
483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200484 }
485 else {
486 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
487 return -1;
488 }
489 return 0;
490}
491
492
493static void init_default_instance()
494{
495 memset(&defproxy, 0, sizeof(defproxy));
496 defproxy.mode = PR_MODE_TCP;
497 defproxy.state = PR_STNEW;
498 defproxy.maxconn = cfg_maxpconn;
499 defproxy.conn_retries = CONN_RETRIES;
500 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaufdd0f552007-09-17 11:12:40 +0200501 tv_eternity(&defproxy.clitimeout);
502 tv_eternity(&defproxy.contimeout);
503 tv_eternity(&defproxy.srvtimeout);
504 tv_eternity(&defproxy.appsession_timeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200505}
506
507/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100508 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
509 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200510 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200511int cfg_parse_listen(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200512{
513 static struct proxy *curproxy = NULL;
514 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200515 const char *err;
Willy Tarreauee991362007-05-14 14:37:50 +0200516 int rc, val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200517
Willy Tarreau977b8e42006-12-29 14:19:17 +0100518 if (!strcmp(args[0], "listen"))
519 rc = PR_CAP_LISTEN;
520 else if (!strcmp(args[0], "frontend"))
521 rc = PR_CAP_FE | PR_CAP_RS;
522 else if (!strcmp(args[0], "backend"))
523 rc = PR_CAP_BE | PR_CAP_RS;
524 else if (!strcmp(args[0], "ruleset"))
525 rc = PR_CAP_RS;
526 else
527 rc = PR_CAP_NONE;
528
529 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530 if (!*args[1]) {
531 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
532 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
533 file, linenum, args[0]);
534 return -1;
535 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200536
537 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
538 /*
539 * If there are two proxies with the same name only following
540 * combinations are allowed:
541 *
542 * listen backend frontend ruleset
543 * listen - - - -
544 * backend - - OK -
545 * frontend - OK - -
546 * ruleset - - - -
547 */
548
549 if (!strcmp(curproxy->id, args[1]) &&
550 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
551 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100552 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
553 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200554 }
555 }
556
Willy Tarreaubaaee002006-06-26 02:48:02 +0200557 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
558 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
559 return -1;
560 }
561
562 curproxy->next = proxy;
563 proxy = curproxy;
564 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200565 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200566 LIST_INIT(&curproxy->block_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200567 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200568
Willy Tarreauee991362007-05-14 14:37:50 +0200569 /* Timeouts are defined as -1, so we cannot use the zeroed area
570 * as a default value.
571 */
572 tv_eternity(&curproxy->clitimeout);
573 tv_eternity(&curproxy->srvtimeout);
574 tv_eternity(&curproxy->contimeout);
575 tv_eternity(&curproxy->appsession_timeout);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200576
577 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200578 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100579 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580
581 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100582 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200583 curproxy->listen = str2listener(args[2], curproxy->listen);
584 if (!curproxy->listen)
585 return -1;
586 global.maxsock++;
587 }
588
589 /* set default values */
590 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200591 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100592 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200593 curproxy->except_net = defproxy.except_net;
594 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595
Willy Tarreau977b8e42006-12-29 14:19:17 +0100596 if (curproxy->cap & PR_CAP_FE) {
597 curproxy->maxconn = defproxy.maxconn;
598
599 /* initialize error relocations */
600 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
601 if (defproxy.errmsg[rc].str)
602 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
603 }
604
605 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607
Willy Tarreau977b8e42006-12-29 14:19:17 +0100608 if (curproxy->cap & PR_CAP_BE) {
609 curproxy->fullconn = defproxy.fullconn;
610 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611
Willy Tarreau977b8e42006-12-29 14:19:17 +0100612 if (defproxy.check_req)
613 curproxy->check_req = strdup(defproxy.check_req);
614 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615
Willy Tarreau977b8e42006-12-29 14:19:17 +0100616 if (defproxy.cookie_name)
617 curproxy->cookie_name = strdup(defproxy.cookie_name);
618 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100619
620 if (defproxy.url_param_name)
621 curproxy->url_param_name = strdup(defproxy.url_param_name);
622 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100623 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200624
Willy Tarreau977b8e42006-12-29 14:19:17 +0100625 if (curproxy->cap & PR_CAP_RS) {
626 if (defproxy.capture_name)
627 curproxy->capture_name = strdup(defproxy.capture_name);
628 curproxy->capture_namelen = defproxy.capture_namelen;
629 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100630 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631
Willy Tarreau977b8e42006-12-29 14:19:17 +0100632 if (curproxy->cap & PR_CAP_FE) {
633 curproxy->clitimeout = defproxy.clitimeout;
634 curproxy->uri_auth = defproxy.uri_auth;
635 curproxy->mon_net = defproxy.mon_net;
636 curproxy->mon_mask = defproxy.mon_mask;
637 if (defproxy.monitor_uri)
638 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
639 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100640 if (defproxy.defbe.name)
641 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100642 }
643
644 if (curproxy->cap & PR_CAP_BE) {
645 curproxy->contimeout = defproxy.contimeout;
646 curproxy->srvtimeout = defproxy.srvtimeout;
647 curproxy->source_addr = defproxy.source_addr;
648 }
649
Willy Tarreaubaaee002006-06-26 02:48:02 +0200650 curproxy->mode = defproxy.mode;
651 curproxy->logfac1 = defproxy.logfac1;
652 curproxy->logsrv1 = defproxy.logsrv1;
653 curproxy->loglev1 = defproxy.loglev1;
654 curproxy->logfac2 = defproxy.logfac2;
655 curproxy->logsrv2 = defproxy.logsrv2;
656 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100658 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
659 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200660
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 return 0;
662 }
663 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
664 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100665 /* FIXME-20070101: we should do this too at the end of the
666 * config parsing to free all default values.
667 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668 if (defproxy.check_req) free(defproxy.check_req);
669 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100670 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200672 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100673 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100674
675 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
676 if (defproxy.errmsg[rc].len)
677 free(defproxy.errmsg[rc].str);
678 }
679
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 /* we cannot free uri_auth because it might already be used */
681 init_default_instance();
682 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100683 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200684 return 0;
685 }
686 else if (curproxy == NULL) {
687 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
688 return -1;
689 }
690
Willy Tarreau977b8e42006-12-29 14:19:17 +0100691
692 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 if (!strcmp(args[0], "bind")) { /* new listen addresses */
694 if (curproxy == &defproxy) {
695 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
696 return -1;
697 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100698 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
699 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700
701 if (strchr(args[1], ':') == NULL) {
702 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
703 file, linenum, args[0]);
704 return -1;
705 }
706 curproxy->listen = str2listener(args[1], curproxy->listen);
707 if (!curproxy->listen)
708 return -1;
709 global.maxsock++;
710 return 0;
711 }
712 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
713 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
714 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
715 file, linenum, args[0]);
716 return -1;
717 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100718 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
719 return 0;
720
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 /* flush useless bits */
722 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
723 return 0;
724 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200725 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100726 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
727 return 0;
728
Willy Tarreau1c47f852006-07-09 08:22:27 +0200729 if (!*args[1]) {
730 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
731 file, linenum, args[0]);
732 return -1;
733 }
734
735 if (curproxy->monitor_uri != NULL)
736 free(curproxy->monitor_uri);
737
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100738 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200739 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100740 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200741 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
742
743 return 0;
744 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200745 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
746 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
747 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
748 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
749 else {
750 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
751 return -1;
752 }
753 }
754 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
755 curproxy->state = PR_STSTOPPED;
756 }
757 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
758 curproxy->state = PR_STNEW;
759 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200760 else if (!strcmp(args[0], "acl")) { /* add an ACL */
761 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
762 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
763 file, linenum, args[1]);
764 return -1;
765 }
766 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200767 else if (!strcmp(args[0], "cookie")) { /* cookie name */
768 int cur_arg;
769 // if (curproxy == &defproxy) {
770 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
771 // return -1;
772 // }
773
Willy Tarreau977b8e42006-12-29 14:19:17 +0100774 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
775 return 0;
776
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 if (curproxy->cookie_name != NULL) {
778 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
779 // file, linenum);
780 // return 0;
781 free(curproxy->cookie_name);
782 }
783
784 if (*(args[1]) == 0) {
785 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
786 file, linenum, args[0]);
787 return -1;
788 }
789 curproxy->cookie_name = strdup(args[1]);
790 curproxy->cookie_len = strlen(curproxy->cookie_name);
791
792 cur_arg = 2;
793 while (*(args[cur_arg])) {
794 if (!strcmp(args[cur_arg], "rewrite")) {
795 curproxy->options |= PR_O_COOK_RW;
796 }
797 else if (!strcmp(args[cur_arg], "indirect")) {
798 curproxy->options |= PR_O_COOK_IND;
799 }
800 else if (!strcmp(args[cur_arg], "insert")) {
801 curproxy->options |= PR_O_COOK_INS;
802 }
803 else if (!strcmp(args[cur_arg], "nocache")) {
804 curproxy->options |= PR_O_COOK_NOC;
805 }
806 else if (!strcmp(args[cur_arg], "postonly")) {
807 curproxy->options |= PR_O_COOK_POST;
808 }
809 else if (!strcmp(args[cur_arg], "prefix")) {
810 curproxy->options |= PR_O_COOK_PFX;
811 }
812 else {
813 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
814 file, linenum, args[0]);
815 return -1;
816 }
817 cur_arg++;
818 }
819 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
820 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
821 file, linenum);
822 return -1;
823 }
824
825 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
826 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
827 file, linenum);
828 return -1;
829 }
830 }/* end else if (!strcmp(args[0], "cookie")) */
831 else if (!strcmp(args[0], "appsession")) { /* cookie name */
832 // if (curproxy == &defproxy) {
833 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
834 // return -1;
835 // }
836
Willy Tarreau977b8e42006-12-29 14:19:17 +0100837 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
838 return 0;
839
Willy Tarreaubaaee002006-06-26 02:48:02 +0200840 if (curproxy->appsession_name != NULL) {
841 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
842 // file, linenum);
843 // return 0;
844 free(curproxy->appsession_name);
845 }
846
847 if (*(args[5]) == 0) {
848 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
849 file, linenum, args[0]);
850 return -1;
851 }
852 have_appsession = 1;
853 curproxy->appsession_name = strdup(args[1]);
854 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
855 curproxy->appsession_len = atoi(args[3]);
Willy Tarreauee991362007-05-14 14:37:50 +0200856 val = atoi(args[5]);
857 if (val > 0)
858 __tv_from_ms(&curproxy->appsession_timeout, val);
859 else
860 tv_eternity(&curproxy->appsession_timeout);
861
Willy Tarreau51041c72007-09-09 21:56:53 +0200862 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
863 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200864 return -1;
865 }
866 } /* Url App Session */
867 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100868 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
869 return 0;
870
Willy Tarreaubaaee002006-06-26 02:48:02 +0200871 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
872 // if (curproxy == &defproxy) {
873 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
874 // return -1;
875 // }
876
877 if (curproxy->capture_name != NULL) {
878 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
879 // file, linenum, args[0]);
880 // return 0;
881 free(curproxy->capture_name);
882 }
883
884 if (*(args[4]) == 0) {
885 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
886 file, linenum, args[0]);
887 return -1;
888 }
889 curproxy->capture_name = strdup(args[2]);
890 curproxy->capture_namelen = strlen(curproxy->capture_name);
891 curproxy->capture_len = atol(args[4]);
892 if (curproxy->capture_len >= CAPTURE_LEN) {
893 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
894 file, linenum, CAPTURE_LEN - 1);
895 curproxy->capture_len = CAPTURE_LEN - 1;
896 }
897 curproxy->to_log |= LW_COOKIE;
898 }
899 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
900 struct cap_hdr *hdr;
901
902 if (curproxy == &defproxy) {
903 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
904 return -1;
905 }
906
907 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
908 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
909 file, linenum, args[0], args[1]);
910 return -1;
911 }
912
913 hdr = calloc(sizeof(struct cap_hdr), 1);
914 hdr->next = curproxy->req_cap;
915 hdr->name = strdup(args[3]);
916 hdr->namelen = strlen(args[3]);
917 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200918 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 hdr->index = curproxy->nb_req_cap++;
920 curproxy->req_cap = hdr;
921 curproxy->to_log |= LW_REQHDR;
922 }
923 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
924 struct cap_hdr *hdr;
925
926 if (curproxy == &defproxy) {
927 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
928 return -1;
929 }
930
931 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
932 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
933 file, linenum, args[0], args[1]);
934 return -1;
935 }
936 hdr = calloc(sizeof(struct cap_hdr), 1);
937 hdr->next = curproxy->rsp_cap;
938 hdr->name = strdup(args[3]);
939 hdr->namelen = strlen(args[3]);
940 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200941 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 hdr->index = curproxy->nb_rsp_cap++;
943 curproxy->rsp_cap = hdr;
944 curproxy->to_log |= LW_RSPHDR;
945 }
946 else {
947 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
948 file, linenum, args[0]);
949 return -1;
950 }
951 }
952 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200953 if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
955 return 0;
956 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100957 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
958 return 0;
959
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960 if (*(args[1]) == 0) {
961 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
962 file, linenum, args[0]);
963 return -1;
964 }
Willy Tarreauee991362007-05-14 14:37:50 +0200965 val = atoi(args[1]);
966 if (val > 0)
967 __tv_from_ms(&curproxy->contimeout, val);
968 else
969 tv_eternity(&curproxy->contimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 }
971 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200972 if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
974 file, linenum, args[0]);
975 return 0;
976 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100977 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
978 return 0;
979
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 if (*(args[1]) == 0) {
981 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
982 file, linenum, args[0]);
983 return -1;
984 }
Willy Tarreauee991362007-05-14 14:37:50 +0200985 val = atoi(args[1]);
986 if (val > 0)
987 __tv_from_ms(&curproxy->clitimeout, val);
988 else
989 tv_eternity(&curproxy->clitimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200990 }
991 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200992 if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
994 return 0;
995 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100996 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
997 return 0;
998
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 if (*(args[1]) == 0) {
1000 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
1001 file, linenum, args[0]);
1002 return -1;
1003 }
Willy Tarreauee991362007-05-14 14:37:50 +02001004 val = atoi(args[1]);
1005 if (val > 0)
1006 __tv_from_ms(&curproxy->srvtimeout, val);
1007 else
1008 tv_eternity(&curproxy->srvtimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001009 }
1010 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001011 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1012 return 0;
1013
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 if (*(args[1]) == 0) {
1015 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1016 file, linenum, args[0]);
1017 return -1;
1018 }
1019 curproxy->conn_retries = atol(args[1]);
1020 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001021 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1022 int pol = ACL_COND_NONE;
1023 struct acl_cond *cond;
1024
1025 if (!strcmp(args[1], "if"))
1026 pol = ACL_COND_IF;
1027 else if (!strcmp(args[1], "unless"))
1028 pol = ACL_COND_UNLESS;
1029
1030 if (pol == ACL_COND_NONE) {
1031 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1032 file, linenum, args[0]);
1033 return -1;
1034 }
1035
1036 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1037 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1038 file, linenum);
1039 return -1;
1040 }
1041 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1042 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001043 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1044 int pol = ACL_COND_NONE;
1045 struct acl_cond *cond;
1046 struct switching_rule *rule;
1047
1048 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1049 return 0;
1050
1051 if (*(args[1]) == 0) {
1052 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1053 return -1;
1054 }
1055
1056 if (!strcmp(args[2], "if"))
1057 pol = ACL_COND_IF;
1058 else if (!strcmp(args[2], "unless"))
1059 pol = ACL_COND_UNLESS;
1060
1061 if (pol == ACL_COND_NONE) {
1062 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1063 file, linenum, args[0]);
1064 return -1;
1065 }
1066
1067 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1068 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1069 file, linenum);
1070 return -1;
1071 }
1072
1073 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1074 rule->cond = cond;
1075 rule->be.name = strdup(args[1]);
1076 LIST_INIT(&rule->list);
1077 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1078 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001080 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1081 return 0;
1082
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1084 curproxy->uri_auth = NULL; /* we must detach from the default config */
1085
1086 if (*(args[1]) == 0) {
1087 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1088 return -1;
1089 } else if (!strcmp(args[1], "uri")) {
1090 if (*(args[2]) == 0) {
1091 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1092 return -1;
1093 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1094 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1095 return -1;
1096 }
1097 } else if (!strcmp(args[1], "realm")) {
1098 if (*(args[2]) == 0) {
1099 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1100 return -1;
1101 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1102 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1103 return -1;
1104 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001105 } else if (!strcmp(args[1], "refresh")) {
1106 int interval = atoi(args[2]);
1107
1108 if (interval < 0) {
1109 Alert("parsing [%s:%d] : 'refresh' needs a positive interval in seconds.\n", file, linenum);
1110 return -1;
1111 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1112 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1113 return -1;
1114 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001115 } else if (!strcmp(args[1], "auth")) {
1116 if (*(args[2]) == 0) {
1117 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1118 return -1;
1119 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1120 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1121 return -1;
1122 }
1123 } else if (!strcmp(args[1], "scope")) {
1124 if (*(args[2]) == 0) {
1125 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1126 return -1;
1127 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1128 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1129 return -1;
1130 }
1131 } else if (!strcmp(args[1], "enable")) {
1132 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1133 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1134 return -1;
1135 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001136 } else if (!strcmp(args[1], "hide-version")) {
1137 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1138 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1139 return -1;
1140 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001142 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 file, linenum, args[0]);
1144 return -1;
1145 }
1146 }
1147 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001148 int optnum;
1149
Willy Tarreaubaaee002006-06-26 02:48:02 +02001150 if (*(args[1]) == 0) {
1151 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
1152 return -1;
1153 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001154
1155 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1156 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1157 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1158 return 0;
1159 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001160 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001161 return 0;
1162 }
1163 }
1164
1165 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001166 /* generate a complete HTTP log */
1167 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1168 else if (!strcmp(args[1], "tcplog"))
1169 /* generate a detailed TCP log */
1170 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001171 else if (!strcmp(args[1], "tcpka")) {
1172 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001173 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1174 return 0;
1175
1176 if (curproxy->cap & PR_CAP_FE)
1177 curproxy->options |= PR_O_TCP_CLI_KA;
1178 if (curproxy->cap & PR_CAP_BE)
1179 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001180 }
1181 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001182 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1183 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001184 /* use HTTP request to check servers' health */
1185 if (curproxy->check_req != NULL) {
1186 free(curproxy->check_req);
1187 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001188 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001189 curproxy->options &= ~PR_O_SMTP_CHK;
1190 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191 if (!*args[2]) { /* no argument */
1192 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1193 curproxy->check_len = strlen(DEF_CHECK_REQ);
1194 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001195 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001196 curproxy->check_req = (char *)malloc(reqlen);
1197 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1198 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1199 } else { /* more arguments : METHOD URI [HTTP_VER] */
1200 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1201 if (*args[4])
1202 reqlen += strlen(args[4]);
1203 else
1204 reqlen += strlen("HTTP/1.0");
1205
1206 curproxy->check_req = (char *)malloc(reqlen);
1207 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1208 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1209 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001210 }
1211 else if (!strcmp(args[1], "ssl-hello-chk")) {
1212 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001213 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1214 return 0;
1215
Willy Tarreauf3c69202006-07-09 16:42:34 +02001216 if (curproxy->check_req != NULL) {
1217 free(curproxy->check_req);
1218 }
1219 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001220 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001221 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001222 }
Willy Tarreau23677902007-05-08 23:50:35 +02001223 else if (!strcmp(args[1], "smtpchk")) {
1224 /* use SMTP request to check servers' health */
1225 if (curproxy->check_req != NULL) {
1226 free(curproxy->check_req);
1227 }
1228 curproxy->options &= ~PR_O_HTTP_CHK;
1229 curproxy->options &= ~PR_O_SSL3_CHK;
1230 curproxy->options |= PR_O_SMTP_CHK;
1231
1232 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1233 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1234 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1235 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1236 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1237 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1238 curproxy->check_req = (char *)malloc(reqlen);
1239 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1240 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1241 } else {
1242 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1243 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1244 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1245 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1246 }
1247 }
1248 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001249 else if (!strcmp(args[1], "forwardfor")) {
1250 /* insert x-forwarded-for field, but not for the
1251 * IP address listed as an except.
1252 */
1253 if (*(args[2])) {
1254 if (!strcmp(args[2], "except")) {
1255 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1256 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1257 file, linenum, args[0]);
1258 return -1;
1259 }
1260 /* flush useless bits */
1261 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1262 } else {
1263 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1264 file, linenum, args[0]);
1265 return -1;
1266 }
1267 }
1268 curproxy->options |= PR_O_FWDFOR;
1269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001270 else {
1271 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1272 return -1;
1273 }
1274 return 0;
1275 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001276 else if (!strcmp(args[0], "default_backend")) {
1277 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1278 return 0;
1279
1280 if (*(args[1]) == 0) {
1281 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1282 return -1;
1283 }
1284 if (curproxy->defbe.name)
1285 free(curproxy->defbe.name);
1286 curproxy->defbe.name = strdup(args[1]);
1287 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001288 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001289 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1290 return 0;
1291
Willy Tarreaubaaee002006-06-26 02:48:02 +02001292 /* enable reconnections to dispatch */
1293 curproxy->options |= PR_O_REDISP;
1294 }
1295#ifdef TPROXY
1296 else if (!strcmp(args[0], "transparent")) {
1297 /* enable transparent proxy connections */
1298 curproxy->options |= PR_O_TRANSP;
1299 }
1300#endif
1301 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001302 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1303 return 0;
1304
Willy Tarreaubaaee002006-06-26 02:48:02 +02001305 if (*(args[1]) == 0) {
1306 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1307 return -1;
1308 }
1309 curproxy->maxconn = atol(args[1]);
1310 }
Willy Tarreau86034312006-12-29 00:10:33 +01001311 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001312 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1313 return 0;
1314
Willy Tarreau86034312006-12-29 00:10:33 +01001315 if (*(args[1]) == 0) {
1316 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1317 return -1;
1318 }
1319 curproxy->fullconn = atol(args[1]);
1320 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001321 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1322 if (*(args[1]) == 0) {
1323 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1324 return -1;
1325 }
1326 curproxy->grace = atol(args[1]);
1327 }
1328 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1329 if (curproxy == &defproxy) {
1330 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1331 return -1;
1332 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001333 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1334 return 0;
1335
Willy Tarreaubaaee002006-06-26 02:48:02 +02001336 if (strchr(args[1], ':') == NULL) {
1337 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1338 return -1;
1339 }
1340 curproxy->dispatch_addr = *str2sa(args[1]);
1341 }
1342 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001343 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1344 return 0;
1345
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001346 memcpy(trash, "error near 'balance'", 19);
1347 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1348 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1349 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001350 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001351 }
1352 else if (!strcmp(args[0], "server")) { /* server address */
1353 int cur_arg;
1354 char *rport;
1355 char *raddr;
1356 short realport;
1357 int do_check;
1358
1359 if (curproxy == &defproxy) {
1360 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1361 return -1;
1362 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001363 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1364 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365
1366 if (!*args[2]) {
1367 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1368 file, linenum, args[0]);
1369 return -1;
1370 }
1371 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1372 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1373 return -1;
1374 }
1375
1376 /* the servers are linked backwards first */
1377 newsrv->next = curproxy->srv;
1378 curproxy->srv = newsrv;
1379 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001380 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001381
1382 LIST_INIT(&newsrv->pendconns);
1383 do_check = 0;
1384 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001385 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001386 newsrv->id = strdup(args[1]);
1387
1388 /* several ways to check the port component :
1389 * - IP => port=+0, relative
1390 * - IP: => port=+0, relative
1391 * - IP:N => port=N, absolute
1392 * - IP:+N => port=+N, relative
1393 * - IP:-N => port=-N, relative
1394 */
1395 raddr = strdup(args[2]);
1396 rport = strchr(raddr, ':');
1397 if (rport) {
1398 *rport++ = 0;
1399 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001400 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 newsrv->state |= SRV_MAPPORTS;
1402 } else {
1403 realport = 0;
1404 newsrv->state |= SRV_MAPPORTS;
1405 }
1406
1407 newsrv->addr = *str2sa(raddr);
1408 newsrv->addr.sin_port = htons(realport);
1409 free(raddr);
1410
1411 newsrv->curfd = -1; /* no health-check in progress */
1412 newsrv->inter = DEF_CHKINTR;
1413 newsrv->rise = DEF_RISETIME;
1414 newsrv->fall = DEF_FALLTIME;
1415 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001416 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001417 newsrv->maxqueue = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001418
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419 cur_arg = 3;
1420 while (*args[cur_arg]) {
1421 if (!strcmp(args[cur_arg], "cookie")) {
1422 newsrv->cookie = strdup(args[cur_arg + 1]);
1423 newsrv->cklen = strlen(args[cur_arg + 1]);
1424 cur_arg += 2;
1425 }
1426 else if (!strcmp(args[cur_arg], "rise")) {
1427 newsrv->rise = atol(args[cur_arg + 1]);
1428 newsrv->health = newsrv->rise;
1429 cur_arg += 2;
1430 }
1431 else if (!strcmp(args[cur_arg], "fall")) {
1432 newsrv->fall = atol(args[cur_arg + 1]);
1433 cur_arg += 2;
1434 }
1435 else if (!strcmp(args[cur_arg], "inter")) {
1436 newsrv->inter = atol(args[cur_arg + 1]);
1437 cur_arg += 2;
1438 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001439 else if (!strcmp(args[cur_arg], "addr")) {
1440 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001441 cur_arg += 2;
1442 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001443 else if (!strcmp(args[cur_arg], "port")) {
1444 newsrv->check_port = atol(args[cur_arg + 1]);
1445 cur_arg += 2;
1446 }
1447 else if (!strcmp(args[cur_arg], "backup")) {
1448 newsrv->state |= SRV_BACKUP;
1449 cur_arg ++;
1450 }
1451 else if (!strcmp(args[cur_arg], "weight")) {
1452 int w;
1453 w = atol(args[cur_arg + 1]);
1454 if (w < 1 || w > 256) {
1455 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1456 file, linenum, newsrv->id, w);
1457 return -1;
1458 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001459 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001460 cur_arg += 2;
1461 }
1462 else if (!strcmp(args[cur_arg], "minconn")) {
1463 newsrv->minconn = atol(args[cur_arg + 1]);
1464 cur_arg += 2;
1465 }
1466 else if (!strcmp(args[cur_arg], "maxconn")) {
1467 newsrv->maxconn = atol(args[cur_arg + 1]);
1468 cur_arg += 2;
1469 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001470 else if (!strcmp(args[cur_arg], "maxqueue")) {
1471 newsrv->maxqueue = atol(args[cur_arg + 1]);
1472 cur_arg += 2;
1473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001474 else if (!strcmp(args[cur_arg], "check")) {
1475 global.maxsock++;
1476 do_check = 1;
1477 cur_arg += 1;
1478 }
1479 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1480 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001481#ifdef CONFIG_HAP_CTTPROXY
1482 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1483 file, linenum, "source", "usesrc");
1484#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1486 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001487#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001488 return -1;
1489 }
1490 newsrv->state |= SRV_BIND_SRC;
1491 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1492 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001493 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001494#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001495 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001496 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1497 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001498 return -1;
1499 }
1500 if (!*args[cur_arg + 1]) {
1501 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1502 file, linenum, "usesrc");
1503 return -1;
1504 }
1505 if (!strcmp(args[cur_arg + 1], "client")) {
1506 newsrv->state |= SRV_TPROXY_CLI;
1507 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1508 newsrv->state |= SRV_TPROXY_CIP;
1509 } else {
1510 newsrv->state |= SRV_TPROXY_ADDR;
1511 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1512 }
1513 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1514 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001515#else /* no CTTPROXY support */
1516 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1517 file, linenum, "usesrc");
1518 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001519#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001521 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001522#ifdef CONFIG_HAP_CTTPROXY
1523 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1524 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1525 file, linenum, "usesrc", "source");
1526 return -1;
1527 }
1528#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529 else {
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001530 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 +02001531 file, linenum, newsrv->id);
1532 return -1;
1533 }
1534 }
1535
1536 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001537 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1538 newsrv->check_port = newsrv->check_addr.sin_port;
1539
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1541 newsrv->check_port = realport; /* by default */
1542 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001543 /* not yet valid, because no port was set on
1544 * the server either. We'll check if we have
1545 * a known port on the first listener.
1546 */
1547 struct listener *l;
1548 l = curproxy->listen;
1549 if (l) {
1550 int port;
1551 port = (l->addr.ss_family == AF_INET6)
1552 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1553 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1554 newsrv->check_port = port;
1555 }
1556 }
1557 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1559 file, linenum, newsrv->id);
1560 return -1;
1561 }
1562 newsrv->state |= SRV_CHECKED;
1563 }
1564
1565 if (newsrv->state & SRV_BACKUP)
1566 curproxy->srv_bck++;
1567 else
1568 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001569
1570 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 }
1572 else if (!strcmp(args[0], "log")) { /* syslog server address */
1573 struct sockaddr_in *sa;
1574 int facility;
1575
1576 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1577 curproxy->logfac1 = global.logfac1;
1578 curproxy->logsrv1 = global.logsrv1;
1579 curproxy->loglev1 = global.loglev1;
1580 curproxy->logfac2 = global.logfac2;
1581 curproxy->logsrv2 = global.logsrv2;
1582 curproxy->loglev2 = global.loglev2;
1583 }
1584 else if (*(args[1]) && *(args[2])) {
1585 int level;
1586
1587 facility = get_log_facility(args[2]);
1588 if (facility < 0) {
1589 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1590 exit(1);
1591 }
1592
1593 level = 7; /* max syslog level = debug */
1594 if (*(args[3])) {
1595 level = get_log_level(args[3]);
1596 if (level < 0) {
1597 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1598 exit(1);
1599 }
1600 }
1601
1602 sa = str2sa(args[1]);
1603 if (!sa->sin_port)
1604 sa->sin_port = htons(SYSLOG_PORT);
1605
1606 if (curproxy->logfac1 == -1) {
1607 curproxy->logsrv1 = *sa;
1608 curproxy->logfac1 = facility;
1609 curproxy->loglev1 = level;
1610 }
1611 else if (curproxy->logfac2 == -1) {
1612 curproxy->logsrv2 = *sa;
1613 curproxy->logfac2 = facility;
1614 curproxy->loglev2 = level;
1615 }
1616 else {
1617 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1618 return -1;
1619 }
1620 }
1621 else {
1622 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1623 file, linenum);
1624 return -1;
1625 }
1626 }
1627 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001628 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1629 return 0;
1630
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001632#ifdef CONFIG_HAP_CTTPROXY
1633 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1634 file, linenum, "source", "usesrc");
1635#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1637 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001638#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 return -1;
1640 }
1641
1642 curproxy->source_addr = *str2sa(args[1]);
1643 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001644 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001645#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001646 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1647 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1648 file, linenum, "usesrc");
1649 return -1;
1650 }
1651 if (!*args[3]) {
1652 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1653 file, linenum, "usesrc");
1654 return -1;
1655 }
1656
1657 if (!strcmp(args[3], "client")) {
1658 curproxy->options |= PR_O_TPXY_CLI;
1659 } else if (!strcmp(args[3], "clientip")) {
1660 curproxy->options |= PR_O_TPXY_CIP;
1661 } else {
1662 curproxy->options |= PR_O_TPXY_ADDR;
1663 curproxy->tproxy_addr = *str2sa(args[3]);
1664 }
1665 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001666#else /* no CTTPROXY support */
1667 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1668 file, linenum, "usesrc");
1669 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001670#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001671 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001672 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001673#ifdef CONFIG_HAP_CTTPROXY
1674 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1675 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1676 file, linenum, "usesrc", "source");
1677 return -1;
1678 }
1679#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001680 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1681 regex_t *preg;
1682 if (curproxy == &defproxy) {
1683 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1684 return -1;
1685 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001686 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1687 return 0;
1688
Willy Tarreaubaaee002006-06-26 02:48:02 +02001689 if (*(args[1]) == 0 || *(args[2]) == 0) {
1690 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1691 file, linenum, args[0]);
1692 return -1;
1693 }
1694
1695 preg = calloc(1, sizeof(regex_t));
1696 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1697 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1698 return -1;
1699 }
1700
1701 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1702 if (err) {
1703 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1704 file, linenum, *err);
1705 return -1;
1706 }
1707 }
1708 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1709 regex_t *preg;
1710 if (curproxy == &defproxy) {
1711 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1712 return -1;
1713 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001714 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1715 return 0;
1716
Willy Tarreaubaaee002006-06-26 02:48:02 +02001717 if (*(args[1]) == 0) {
1718 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1719 return -1;
1720 }
1721
1722 preg = calloc(1, sizeof(regex_t));
1723 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1724 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1725 return -1;
1726 }
1727
1728 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1729 }
1730 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1731 regex_t *preg;
1732 if (curproxy == &defproxy) {
1733 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1734 return -1;
1735 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001736 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1737 return 0;
1738
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739 if (*(args[1]) == 0) {
1740 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1741 return -1;
1742 }
1743
1744 preg = calloc(1, sizeof(regex_t));
1745 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1746 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1747 return -1;
1748 }
1749
1750 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1751 }
1752 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1753 regex_t *preg;
1754 if (curproxy == &defproxy) {
1755 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1756 return -1;
1757 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001758 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1759 return 0;
1760
Willy Tarreaubaaee002006-06-26 02:48:02 +02001761 if (*(args[1]) == 0) {
1762 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1763 return -1;
1764 }
1765
1766 preg = calloc(1, sizeof(regex_t));
1767 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1768 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1769 return -1;
1770 }
1771
1772 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1773 }
1774 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1775 regex_t *preg;
1776 if (curproxy == &defproxy) {
1777 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1778 return -1;
1779 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001780 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1781 return 0;
1782
Willy Tarreaubaaee002006-06-26 02:48:02 +02001783 if (*(args[1]) == 0) {
1784 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1785 return -1;
1786 }
1787
1788 preg = calloc(1, sizeof(regex_t));
1789 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1790 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1791 return -1;
1792 }
1793
1794 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1795 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001796 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1797 regex_t *preg;
1798 if (curproxy == &defproxy) {
1799 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1800 return -1;
1801 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001802 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1803 return 0;
1804
Willy Tarreaub8750a82006-09-03 09:56:00 +02001805 if (*(args[1]) == 0) {
1806 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1807 return -1;
1808 }
1809
1810 preg = calloc(1, sizeof(regex_t));
1811 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1812 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1813 return -1;
1814 }
1815
1816 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1817 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001818 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1819 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001820 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001821 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1822 return -1;
1823 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001824 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1825 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001826
Willy Tarreau977b8e42006-12-29 14:19:17 +01001827 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001828 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1829 file, linenum, args[0]);
1830 return -1;
1831 }
1832
1833 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001834 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001835 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1836 }
1837
1838 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1839 }
1840 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1841 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001842 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001843 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1844 return -1;
1845 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001846 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1847 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001848
Willy Tarreau977b8e42006-12-29 14:19:17 +01001849 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001850 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1851 file, linenum, args[0]);
1852 return -1;
1853 }
1854
1855 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001856 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001857 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1858 }
1859
1860 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001862 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1863 regex_t *preg;
1864 if (curproxy == &defproxy) {
1865 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1866 return -1;
1867 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001868 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1869 return 0;
1870
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 if (*(args[1]) == 0 || *(args[2]) == 0) {
1872 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1873 file, linenum, args[0]);
1874 return -1;
1875 }
1876
1877 preg = calloc(1, sizeof(regex_t));
1878 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1879 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1880 return -1;
1881 }
1882
1883 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1884 if (err) {
1885 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1886 file, linenum, *err);
1887 return -1;
1888 }
1889 }
1890 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1891 regex_t *preg;
1892 if (curproxy == &defproxy) {
1893 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1894 return -1;
1895 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001896 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1897 return 0;
1898
Willy Tarreaubaaee002006-06-26 02:48:02 +02001899 if (*(args[1]) == 0) {
1900 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1901 return -1;
1902 }
1903
1904 preg = calloc(1, sizeof(regex_t));
1905 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1906 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1907 return -1;
1908 }
1909
1910 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1911 }
1912 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1913 regex_t *preg;
1914 if (curproxy == &defproxy) {
1915 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1916 return -1;
1917 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001918 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1919 return 0;
1920
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 if (*(args[1]) == 0) {
1922 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1923 return -1;
1924 }
1925
1926 preg = calloc(1, sizeof(regex_t));
1927 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1928 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1929 return -1;
1930 }
1931
1932 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1933 }
1934 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1935 regex_t *preg;
1936 if (curproxy == &defproxy) {
1937 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1938 return -1;
1939 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001940 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1941 return 0;
1942
Willy Tarreaubaaee002006-06-26 02:48:02 +02001943 if (*(args[1]) == 0) {
1944 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1945 return -1;
1946 }
1947
1948 preg = calloc(1, sizeof(regex_t));
1949 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1950 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1951 return -1;
1952 }
1953
1954 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1955 }
1956 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1957 regex_t *preg;
1958 if (curproxy == &defproxy) {
1959 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1960 return -1;
1961 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001962 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1963 return 0;
1964
Willy Tarreaubaaee002006-06-26 02:48:02 +02001965 if (*(args[1]) == 0) {
1966 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1967 return -1;
1968 }
1969
1970 preg = calloc(1, sizeof(regex_t));
1971 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1972 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1973 return -1;
1974 }
1975
1976 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1977 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001978 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1979 regex_t *preg;
1980 if (curproxy == &defproxy) {
1981 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1982 return -1;
1983 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001984 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1985 return 0;
1986
Willy Tarreaub8750a82006-09-03 09:56:00 +02001987 if (*(args[1]) == 0) {
1988 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1989 return -1;
1990 }
1991
1992 preg = calloc(1, sizeof(regex_t));
1993 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1994 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1995 return -1;
1996 }
1997
1998 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1999 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002000 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2001 if (curproxy == &defproxy) {
2002 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2003 return -1;
2004 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002005 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2006 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002007
2008 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2009 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2010 return 0;
2011 }
2012
2013 if (*(args[1]) == 0) {
2014 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2015 return -1;
2016 }
2017
2018 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2019 }
2020 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2021 regex_t *preg;
2022
2023 if (*(args[1]) == 0 || *(args[2]) == 0) {
2024 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2025 file, linenum, args[0]);
2026 return -1;
2027 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002028 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2029 return 0;
2030
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 preg = calloc(1, sizeof(regex_t));
2032 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2033 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2034 return -1;
2035 }
2036
2037 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2038 if (err) {
2039 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2040 file, linenum, *err);
2041 return -1;
2042 }
2043 }
2044 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2045 regex_t *preg;
2046 if (curproxy == &defproxy) {
2047 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2048 return -1;
2049 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002050 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2051 return 0;
2052
Willy Tarreaubaaee002006-06-26 02:48:02 +02002053 if (*(args[1]) == 0) {
2054 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2055 return -1;
2056 }
2057
2058 preg = calloc(1, sizeof(regex_t));
2059 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2060 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2061 return -1;
2062 }
2063
2064 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2065 if (err) {
2066 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2067 file, linenum, *err);
2068 return -1;
2069 }
2070 }
2071 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2072 regex_t *preg;
2073 if (curproxy == &defproxy) {
2074 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2075 return -1;
2076 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002077 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2078 return 0;
2079
Willy Tarreaubaaee002006-06-26 02:48:02 +02002080 if (*(args[1]) == 0) {
2081 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2082 return -1;
2083 }
2084
2085 preg = calloc(1, sizeof(regex_t));
2086 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2087 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2088 return -1;
2089 }
2090
2091 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2092 if (err) {
2093 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2094 file, linenum, *err);
2095 return -1;
2096 }
2097 }
2098 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2099 regex_t *preg;
2100 if (curproxy == &defproxy) {
2101 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2102 return -1;
2103 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002104 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2105 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106
2107 if (*(args[1]) == 0 || *(args[2]) == 0) {
2108 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2109 file, linenum, args[0]);
2110 return -1;
2111 }
2112
2113 preg = calloc(1, sizeof(regex_t));
2114 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2115 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2116 return -1;
2117 }
2118
2119 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2120 if (err) {
2121 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2122 file, linenum, *err);
2123 return -1;
2124 }
2125 }
2126 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2127 regex_t *preg;
2128 if (curproxy == &defproxy) {
2129 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2130 return -1;
2131 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002132 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2133 return 0;
2134
Willy Tarreaubaaee002006-06-26 02:48:02 +02002135 if (*(args[1]) == 0) {
2136 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2137 return -1;
2138 }
2139
2140 preg = calloc(1, sizeof(regex_t));
2141 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2142 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2143 return -1;
2144 }
2145
2146 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2147 if (err) {
2148 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2149 file, linenum, *err);
2150 return -1;
2151 }
2152 }
2153 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2154 regex_t *preg;
2155 if (curproxy == &defproxy) {
2156 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2157 return -1;
2158 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002159 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2160 return 0;
2161
Willy Tarreaubaaee002006-06-26 02:48:02 +02002162 if (*(args[1]) == 0) {
2163 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2164 return -1;
2165 }
2166
2167 preg = calloc(1, sizeof(regex_t));
2168 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2169 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2170 return -1;
2171 }
2172
2173 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2174 if (err) {
2175 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2176 file, linenum, *err);
2177 return -1;
2178 }
2179 }
2180 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2181 if (curproxy == &defproxy) {
2182 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2183 return -1;
2184 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002185 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2186 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187
2188 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2189 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2190 return 0;
2191 }
2192
2193 if (*(args[1]) == 0) {
2194 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2195 return -1;
2196 }
2197
2198 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2199 }
2200 else if (!strcmp(args[0], "errorloc") ||
2201 !strcmp(args[0], "errorloc302") ||
2202 !strcmp(args[0], "errorloc303")) { /* error location */
2203 int errnum, errlen;
2204 char *err;
2205
Willy Tarreau977b8e42006-12-29 14:19:17 +01002206 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2207 return 0;
2208
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002210 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002211 return -1;
2212 }
2213
2214 errnum = atol(args[1]);
2215 if (!strcmp(args[0], "errorloc303")) {
2216 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2217 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2218 } else {
2219 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2220 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2221 }
2222
Willy Tarreau0f772532006-12-23 20:51:41 +01002223 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2224 if (http_err_codes[rc] == errnum) {
2225 if (curproxy->errmsg[rc].str)
2226 free(curproxy->errmsg[rc].str);
2227 curproxy->errmsg[rc].str = err;
2228 curproxy->errmsg[rc].len = errlen;
2229 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002232
2233 if (rc >= HTTP_ERR_SIZE) {
2234 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2235 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 free(err);
2237 }
2238 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002239 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2240 int errnum, errlen, fd;
2241 char *err;
2242 struct stat stat;
2243
2244 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2245 return 0;
2246
2247 if (*(args[2]) == 0) {
2248 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2249 return -1;
2250 }
2251
2252 fd = open(args[2], O_RDONLY);
2253 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2254 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2255 file, linenum, args[2], args[1]);
2256 if (fd >= 0)
2257 close(fd);
2258 return -1;
2259 }
2260
2261 if (stat.st_size <= BUFSIZE) {
2262 errlen = stat.st_size;
2263 } else {
2264 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2265 file, linenum, args[2], BUFSIZE);
2266 errlen = BUFSIZE;
2267 }
2268
2269 err = malloc(errlen); /* malloc() must succeed during parsing */
2270 errnum = read(fd, err, errlen);
2271 if (errnum != errlen) {
2272 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2273 file, linenum, args[2], args[1]);
2274 close(fd);
2275 free(err);
2276 return -1;
2277 }
2278 close(fd);
2279
2280 errnum = atol(args[1]);
2281 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2282 if (http_err_codes[rc] == errnum) {
2283 if (curproxy->errmsg[rc].str)
2284 free(curproxy->errmsg[rc].str);
2285 curproxy->errmsg[rc].str = err;
2286 curproxy->errmsg[rc].len = errlen;
2287 break;
2288 }
2289 }
2290
2291 if (rc >= HTTP_ERR_SIZE) {
2292 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2293 file, linenum, errnum);
2294 free(err);
2295 }
2296 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297 else {
2298 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2299 return -1;
2300 }
2301 return 0;
2302}
2303
2304
2305/*
2306 * This function reads and parses the configuration file given in the argument.
2307 * returns 0 if OK, -1 if error.
2308 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002309int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002310{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002311 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 FILE *f;
2313 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002314 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002315 int confsect = CFG_NONE;
2316
2317 struct proxy *curproxy = NULL;
2318 struct server *newsrv = NULL;
2319
2320 if ((f=fopen(file,"r")) == NULL)
2321 return -1;
2322
2323 init_default_instance();
2324
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002325 while (fgets(thisline, sizeof(thisline), f) != NULL) {
2326 int arg;
2327 char *end;
2328 char *args[MAX_LINE_ARGS + 1];
2329 char *line = thisline;
2330
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 linenum++;
2332
2333 end = line + strlen(line);
2334
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002335 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2336 /* Check if we reached the limit and the last char is not \n.
2337 * Watch out for the last line without the terminating '\n'!
2338 */
2339 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2340 file, linenum, sizeof(thisline)-1);
2341 return -1;
2342 }
2343
Willy Tarreaubaaee002006-06-26 02:48:02 +02002344 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002345 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 line++;
2347
2348 arg = 0;
2349 args[arg] = line;
2350
2351 while (*line && arg < MAX_LINE_ARGS) {
2352 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2353 * C equivalent value. Other combinations left unchanged (eg: \1).
2354 */
2355 if (*line == '\\') {
2356 int skip = 0;
2357 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2358 *line = line[1];
2359 skip = 1;
2360 }
2361 else if (line[1] == 'r') {
2362 *line = '\r';
2363 skip = 1;
2364 }
2365 else if (line[1] == 'n') {
2366 *line = '\n';
2367 skip = 1;
2368 }
2369 else if (line[1] == 't') {
2370 *line = '\t';
2371 skip = 1;
2372 }
2373 else if (line[1] == 'x') {
2374 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2375 unsigned char hex1, hex2;
2376 hex1 = toupper(line[2]) - '0';
2377 hex2 = toupper(line[3]) - '0';
2378 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2379 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2380 *line = (hex1<<4) + hex2;
2381 skip = 3;
2382 }
2383 else {
2384 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2385 return -1;
2386 }
2387 }
2388 if (skip) {
2389 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2390 end -= skip;
2391 }
2392 line++;
2393 }
2394 else if (*line == '#' || *line == '\n' || *line == '\r') {
2395 /* end of string, end of loop */
2396 *line = 0;
2397 break;
2398 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002399 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002401 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002402 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 line++;
2404 args[++arg] = line;
2405 }
2406 else {
2407 line++;
2408 }
2409 }
2410
2411 /* empty line */
2412 if (!**args)
2413 continue;
2414
Willy Tarreau540abe42007-05-02 20:50:16 +02002415 /* zero out remaining args and ensure that at least one entry
2416 * is zeroed out.
2417 */
2418 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 args[arg] = line;
2420 }
2421
Willy Tarreau977b8e42006-12-29 14:19:17 +01002422 if (!strcmp(args[0], "listen") ||
2423 !strcmp(args[0], "frontend") ||
2424 !strcmp(args[0], "backend") ||
2425 !strcmp(args[0], "ruleset") ||
2426 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 confsect = CFG_LISTEN;
2428 else if (!strcmp(args[0], "global")) /* global config */
2429 confsect = CFG_GLOBAL;
2430 /* else it's a section keyword */
2431
2432 switch (confsect) {
2433 case CFG_LISTEN:
2434 if (cfg_parse_listen(file, linenum, args) < 0)
2435 return -1;
2436 break;
2437 case CFG_GLOBAL:
2438 if (cfg_parse_global(file, linenum, args) < 0)
2439 return -1;
2440 break;
2441 default:
2442 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2443 return -1;
2444 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445 }
2446 fclose(f);
2447
2448 /*
2449 * Now, check for the integrity of all that we have collected.
2450 */
2451
2452 /* will be needed further to delay some tasks */
2453 tv_now(&now);
2454
2455 if ((curproxy = proxy) == NULL) {
2456 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2457 file);
2458 return -1;
2459 }
2460
2461 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002462 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002463 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002464
Willy Tarreaubaaee002006-06-26 02:48:02 +02002465 if (curproxy->state == PR_STSTOPPED) {
2466 curproxy = curproxy->next;
2467 continue;
2468 }
2469
Willy Tarreau977b8e42006-12-29 14:19:17 +01002470 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2471 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 +01002472 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 cfgerr++;
2474 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002475 else if (curproxy->cap & PR_CAP_BE &&
2476 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002477 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002478 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002479 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2480 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 +01002481 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002482 cfgerr++;
2483 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002484
Willy Tarreau31682232007-11-29 15:38:04 +01002485 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002486 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002487 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002488 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 cfgerr++;
2490 }
2491#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2492 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002493 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002494 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 cfgerr++;
2496 }
2497#endif
2498 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002499 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002500 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 }
2502 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002503
2504 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002505 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002506 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002507 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002509 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002510 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002511 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 }
2513 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002514 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002515 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002517 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002518 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002519 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002520 }
Willy Tarreau31682232007-11-29 15:38:04 +01002521 if (curproxy->lbprm.algo & BE_LB_ALGO_L7) {
2522 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2523 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002524
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002525 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002526 file, proxy_type_str(curproxy), curproxy->id);
2527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002528 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002529
2530 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2531 if ((newsrv = curproxy->srv) != NULL) {
2532 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2533 file, proxy_type_str(curproxy), curproxy->id);
2534 }
2535 }
2536
2537 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002538 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2539 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2540 file, curproxy->id);
2541 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002542 }
2543 }
2544
2545 /* if a default backend was specified, let's find it */
2546 if (curproxy->defbe.name) {
2547 struct proxy *target;
2548
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002549 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2550 if (!target) {
2551 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2552 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002553 cfgerr++;
2554 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002555 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2556 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002557 } else {
2558 free(curproxy->defbe.name);
2559 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 }
2561 }
2562
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002563 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002564 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2565 /* map jump target for ACT_SETBE in req_rep chain */
2566 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002567 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002568 struct proxy *target;
2569
Willy Tarreaua496b602006-12-17 23:15:24 +01002570 if (exp->action != ACT_SETBE)
2571 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002572
2573 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2574 if (!target) {
2575 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2576 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002577 cfgerr++;
2578 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002579 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2580 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002581 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002582 } else {
2583 free((void *)exp->replace);
2584 exp->replace = (const char *)target;
2585 }
2586 }
2587 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002588
2589 /* find the target proxy for 'use_backend' rules */
2590 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002591 struct proxy *target;
2592
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002593 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002594
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002595 if (!target) {
2596 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2597 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002598 cfgerr++;
2599 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002600 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2601 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002602 cfgerr++;
2603 } else {
2604 free((void *)rule->be.name);
2605 rule->be.backend = target;
2606 }
2607 }
2608
Willy Tarreau2738a142006-07-08 17:28:09 +02002609 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002610 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2611 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2612 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002613 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002614 " | While not properly invalid, you will certainly encounter various problems\n"
2615 " | with such a configuration. To fix this, please ensure that all following\n"
2616 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002617 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002618 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002619
2620 if (curproxy->options & PR_O_SSL3_CHK) {
2621 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2622 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2623 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2624 }
2625
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002626 /* The small pools required for the capture lists */
2627 if (curproxy->nb_req_cap)
2628 curproxy->req_cap_pool = create_pool("ptrcap",
2629 curproxy->nb_req_cap * sizeof(char *),
2630 MEM_F_SHARED);
2631 if (curproxy->nb_rsp_cap)
2632 curproxy->rsp_cap_pool = create_pool("ptrcap",
2633 curproxy->nb_rsp_cap * sizeof(char *),
2634 MEM_F_SHARED);
2635
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002636 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2637 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2638 MEM_F_SHARED);
2639
Willy Tarreau86034312006-12-29 00:10:33 +01002640 /* for backwards compatibility with "listen" instances, if
2641 * fullconn is not set but maxconn is set, then maxconn
2642 * is used.
2643 */
2644 if (!curproxy->fullconn)
2645 curproxy->fullconn = curproxy->maxconn;
2646
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 /* first, we will invert the servers list order */
2648 newsrv = NULL;
2649 while (curproxy->srv) {
2650 struct server *next;
2651
2652 next = curproxy->srv->next;
2653 curproxy->srv->next = newsrv;
2654 newsrv = curproxy->srv;
2655 if (!next)
2656 break;
2657 curproxy->srv = next;
2658 }
2659
Willy Tarreau20697042007-11-15 23:26:18 +01002660 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01002661 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002662
Willy Tarreaub625a082007-11-26 01:15:43 +01002663 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01002664 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01002665 fwrr_init_server_groups(curproxy);
2666 else
2667 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668
2669 if (curproxy->options & PR_O_LOGASAP)
2670 curproxy->to_log &= ~LW_BYTES;
2671
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 /*
2673 * If this server supports a maxconn parameter, it needs a dedicated
2674 * tasks to fill the emptied slots when a connection leaves.
2675 */
2676 newsrv = curproxy->srv;
2677 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002678 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 /* Only 'minconn' was specified, or it was higher than or equal
2680 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2681 * this will avoid further useless expensive computations.
2682 */
2683 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002684 } else if (newsrv->maxconn && !newsrv->minconn) {
2685 /* minconn was not specified, so we set it to maxconn */
2686 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002687 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2688 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002689 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002690 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 }
2692
2693 if (newsrv->maxconn > 0) {
2694 struct task *t;
2695
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002696 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002697 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2698 return -1;
2699 }
2700
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002701 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002702 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002703 t->state = TASK_IDLE;
2704 t->process = process_srv_queue;
2705 t->context = newsrv;
2706 newsrv->queue_mgt = t;
2707
2708 /* never run it unless specifically woken up */
2709 tv_eternity(&t->expire);
2710 task_queue(t);
2711 }
2712 newsrv = newsrv->next;
2713 }
2714
Willy Tarreaue6b98942007-10-29 01:09:36 +01002715 /* adjust this proxy's listeners */
2716 listener = curproxy->listen;
2717 while (listener) {
2718 if (curproxy->options & PR_O_TCP_NOLING)
2719 listener->options |= LI_O_NOLINGER;
2720 listener->maxconn = curproxy->maxconn;
2721 listener->timeout = &curproxy->clitimeout;
2722 listener->accept = event_accept;
2723 listener->private = curproxy;
2724
2725 listener = listener->next;
2726 }
2727
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728 curproxy = curproxy->next;
2729 }
2730 if (cfgerr > 0) {
2731 Alert("Errors found in configuration file, aborting.\n");
2732 return -1;
2733 }
2734 else
2735 return 0;
2736}
2737
2738
2739
2740/*
2741 * Local variables:
2742 * c-indent-level: 8
2743 * c-basic-offset: 8
2744 * End:
2745 */