blob: 869567ffad74252ad6a865fa1668992af7ea9520 [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 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001295 else if (!strcmp(args[0], "http-check")) {
1296 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1297 return 0;
1298
1299 if (strcmp(args[1], "disable-on-404") == 0) {
1300 /* enable a graceful server shutdown on an HTTP 404 response */
1301 curproxy->options |= PR_O_DISABLE404;
1302 }
1303 else {
1304 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1305 return -1;
1306 }
1307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308#ifdef TPROXY
1309 else if (!strcmp(args[0], "transparent")) {
1310 /* enable transparent proxy connections */
1311 curproxy->options |= PR_O_TRANSP;
1312 }
1313#endif
1314 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001315 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1316 return 0;
1317
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318 if (*(args[1]) == 0) {
1319 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1320 return -1;
1321 }
1322 curproxy->maxconn = atol(args[1]);
1323 }
Willy Tarreau86034312006-12-29 00:10:33 +01001324 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001325 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1326 return 0;
1327
Willy Tarreau86034312006-12-29 00:10:33 +01001328 if (*(args[1]) == 0) {
1329 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1330 return -1;
1331 }
1332 curproxy->fullconn = atol(args[1]);
1333 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001334 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1335 if (*(args[1]) == 0) {
1336 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1337 return -1;
1338 }
1339 curproxy->grace = atol(args[1]);
1340 }
1341 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1342 if (curproxy == &defproxy) {
1343 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1344 return -1;
1345 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001346 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1347 return 0;
1348
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 if (strchr(args[1], ':') == NULL) {
1350 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1351 return -1;
1352 }
1353 curproxy->dispatch_addr = *str2sa(args[1]);
1354 }
1355 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001356 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1357 return 0;
1358
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001359 memcpy(trash, "error near 'balance'", 19);
1360 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1361 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1362 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001363 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001364 }
1365 else if (!strcmp(args[0], "server")) { /* server address */
1366 int cur_arg;
1367 char *rport;
1368 char *raddr;
1369 short realport;
1370 int do_check;
1371
1372 if (curproxy == &defproxy) {
1373 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1374 return -1;
1375 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001376 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1377 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378
1379 if (!*args[2]) {
1380 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1381 file, linenum, args[0]);
1382 return -1;
1383 }
1384 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1385 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1386 return -1;
1387 }
1388
1389 /* the servers are linked backwards first */
1390 newsrv->next = curproxy->srv;
1391 curproxy->srv = newsrv;
1392 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001393 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394
1395 LIST_INIT(&newsrv->pendconns);
1396 do_check = 0;
1397 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001398 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 newsrv->id = strdup(args[1]);
1400
1401 /* several ways to check the port component :
1402 * - IP => port=+0, relative
1403 * - IP: => port=+0, relative
1404 * - IP:N => port=N, absolute
1405 * - IP:+N => port=+N, relative
1406 * - IP:-N => port=-N, relative
1407 */
1408 raddr = strdup(args[2]);
1409 rport = strchr(raddr, ':');
1410 if (rport) {
1411 *rport++ = 0;
1412 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001413 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 newsrv->state |= SRV_MAPPORTS;
1415 } else {
1416 realport = 0;
1417 newsrv->state |= SRV_MAPPORTS;
1418 }
1419
1420 newsrv->addr = *str2sa(raddr);
1421 newsrv->addr.sin_port = htons(realport);
1422 free(raddr);
1423
1424 newsrv->curfd = -1; /* no health-check in progress */
1425 newsrv->inter = DEF_CHKINTR;
1426 newsrv->rise = DEF_RISETIME;
1427 newsrv->fall = DEF_FALLTIME;
1428 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001429 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001430 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001431 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001432
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 cur_arg = 3;
1434 while (*args[cur_arg]) {
1435 if (!strcmp(args[cur_arg], "cookie")) {
1436 newsrv->cookie = strdup(args[cur_arg + 1]);
1437 newsrv->cklen = strlen(args[cur_arg + 1]);
1438 cur_arg += 2;
1439 }
1440 else if (!strcmp(args[cur_arg], "rise")) {
1441 newsrv->rise = atol(args[cur_arg + 1]);
1442 newsrv->health = newsrv->rise;
1443 cur_arg += 2;
1444 }
1445 else if (!strcmp(args[cur_arg], "fall")) {
1446 newsrv->fall = atol(args[cur_arg + 1]);
1447 cur_arg += 2;
1448 }
1449 else if (!strcmp(args[cur_arg], "inter")) {
1450 newsrv->inter = atol(args[cur_arg + 1]);
1451 cur_arg += 2;
1452 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001453 else if (!strcmp(args[cur_arg], "addr")) {
1454 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001455 cur_arg += 2;
1456 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 else if (!strcmp(args[cur_arg], "port")) {
1458 newsrv->check_port = atol(args[cur_arg + 1]);
1459 cur_arg += 2;
1460 }
1461 else if (!strcmp(args[cur_arg], "backup")) {
1462 newsrv->state |= SRV_BACKUP;
1463 cur_arg ++;
1464 }
1465 else if (!strcmp(args[cur_arg], "weight")) {
1466 int w;
1467 w = atol(args[cur_arg + 1]);
1468 if (w < 1 || w > 256) {
1469 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1470 file, linenum, newsrv->id, w);
1471 return -1;
1472 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001473 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001474 cur_arg += 2;
1475 }
1476 else if (!strcmp(args[cur_arg], "minconn")) {
1477 newsrv->minconn = atol(args[cur_arg + 1]);
1478 cur_arg += 2;
1479 }
1480 else if (!strcmp(args[cur_arg], "maxconn")) {
1481 newsrv->maxconn = atol(args[cur_arg + 1]);
1482 cur_arg += 2;
1483 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001484 else if (!strcmp(args[cur_arg], "maxqueue")) {
1485 newsrv->maxqueue = atol(args[cur_arg + 1]);
1486 cur_arg += 2;
1487 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001488 else if (!strcmp(args[cur_arg], "slowstart")) {
1489 /* slowstart is stored in seconds */
1490 newsrv->slowstart = (atol(args[cur_arg + 1]) + 999) / 1000;
1491 cur_arg += 2;
1492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493 else if (!strcmp(args[cur_arg], "check")) {
1494 global.maxsock++;
1495 do_check = 1;
1496 cur_arg += 1;
1497 }
1498 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1499 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001500#ifdef CONFIG_HAP_CTTPROXY
1501 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1502 file, linenum, "source", "usesrc");
1503#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001504 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1505 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001506#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001507 return -1;
1508 }
1509 newsrv->state |= SRV_BIND_SRC;
1510 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1511 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001512 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001513#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001514 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001515 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1516 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001517 return -1;
1518 }
1519 if (!*args[cur_arg + 1]) {
1520 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1521 file, linenum, "usesrc");
1522 return -1;
1523 }
1524 if (!strcmp(args[cur_arg + 1], "client")) {
1525 newsrv->state |= SRV_TPROXY_CLI;
1526 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1527 newsrv->state |= SRV_TPROXY_CIP;
1528 } else {
1529 newsrv->state |= SRV_TPROXY_ADDR;
1530 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1531 }
1532 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1533 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001534#else /* no CTTPROXY support */
1535 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1536 file, linenum, "usesrc");
1537 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001538#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001539 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001541#ifdef CONFIG_HAP_CTTPROXY
1542 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1543 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1544 file, linenum, "usesrc", "source");
1545 return -1;
1546 }
1547#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001548 else {
Willy Tarreau9909fc12007-11-30 17:42:05 +01001549 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001550 file, linenum, newsrv->id);
1551 return -1;
1552 }
1553 }
1554
1555 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001556 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1557 newsrv->check_port = newsrv->check_addr.sin_port;
1558
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1560 newsrv->check_port = realport; /* by default */
1561 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001562 /* not yet valid, because no port was set on
1563 * the server either. We'll check if we have
1564 * a known port on the first listener.
1565 */
1566 struct listener *l;
1567 l = curproxy->listen;
1568 if (l) {
1569 int port;
1570 port = (l->addr.ss_family == AF_INET6)
1571 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1572 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1573 newsrv->check_port = port;
1574 }
1575 }
1576 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1578 file, linenum, newsrv->id);
1579 return -1;
1580 }
1581 newsrv->state |= SRV_CHECKED;
1582 }
1583
1584 if (newsrv->state & SRV_BACKUP)
1585 curproxy->srv_bck++;
1586 else
1587 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001588
1589 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590 }
1591 else if (!strcmp(args[0], "log")) { /* syslog server address */
1592 struct sockaddr_in *sa;
1593 int facility;
1594
1595 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1596 curproxy->logfac1 = global.logfac1;
1597 curproxy->logsrv1 = global.logsrv1;
1598 curproxy->loglev1 = global.loglev1;
1599 curproxy->logfac2 = global.logfac2;
1600 curproxy->logsrv2 = global.logsrv2;
1601 curproxy->loglev2 = global.loglev2;
1602 }
1603 else if (*(args[1]) && *(args[2])) {
1604 int level;
1605
1606 facility = get_log_facility(args[2]);
1607 if (facility < 0) {
1608 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1609 exit(1);
1610 }
1611
1612 level = 7; /* max syslog level = debug */
1613 if (*(args[3])) {
1614 level = get_log_level(args[3]);
1615 if (level < 0) {
1616 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1617 exit(1);
1618 }
1619 }
1620
1621 sa = str2sa(args[1]);
1622 if (!sa->sin_port)
1623 sa->sin_port = htons(SYSLOG_PORT);
1624
1625 if (curproxy->logfac1 == -1) {
1626 curproxy->logsrv1 = *sa;
1627 curproxy->logfac1 = facility;
1628 curproxy->loglev1 = level;
1629 }
1630 else if (curproxy->logfac2 == -1) {
1631 curproxy->logsrv2 = *sa;
1632 curproxy->logfac2 = facility;
1633 curproxy->loglev2 = level;
1634 }
1635 else {
1636 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1637 return -1;
1638 }
1639 }
1640 else {
1641 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1642 file, linenum);
1643 return -1;
1644 }
1645 }
1646 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001647 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1648 return 0;
1649
Willy Tarreaubaaee002006-06-26 02:48:02 +02001650 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001651#ifdef CONFIG_HAP_CTTPROXY
1652 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1653 file, linenum, "source", "usesrc");
1654#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1656 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001657#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 return -1;
1659 }
1660
1661 curproxy->source_addr = *str2sa(args[1]);
1662 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001663 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001664#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001665 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1666 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1667 file, linenum, "usesrc");
1668 return -1;
1669 }
1670 if (!*args[3]) {
1671 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1672 file, linenum, "usesrc");
1673 return -1;
1674 }
1675
1676 if (!strcmp(args[3], "client")) {
1677 curproxy->options |= PR_O_TPXY_CLI;
1678 } else if (!strcmp(args[3], "clientip")) {
1679 curproxy->options |= PR_O_TPXY_CIP;
1680 } else {
1681 curproxy->options |= PR_O_TPXY_ADDR;
1682 curproxy->tproxy_addr = *str2sa(args[3]);
1683 }
1684 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001685#else /* no CTTPROXY support */
1686 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1687 file, linenum, "usesrc");
1688 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001689#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001691 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001692#ifdef CONFIG_HAP_CTTPROXY
1693 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1694 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1695 file, linenum, "usesrc", "source");
1696 return -1;
1697 }
1698#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1700 regex_t *preg;
1701 if (curproxy == &defproxy) {
1702 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1703 return -1;
1704 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001705 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1706 return 0;
1707
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 if (*(args[1]) == 0 || *(args[2]) == 0) {
1709 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1710 file, linenum, args[0]);
1711 return -1;
1712 }
1713
1714 preg = calloc(1, sizeof(regex_t));
1715 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1716 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1717 return -1;
1718 }
1719
1720 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1721 if (err) {
1722 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1723 file, linenum, *err);
1724 return -1;
1725 }
1726 }
1727 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1728 regex_t *preg;
1729 if (curproxy == &defproxy) {
1730 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1731 return -1;
1732 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001733 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1734 return 0;
1735
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 if (*(args[1]) == 0) {
1737 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1738 return -1;
1739 }
1740
1741 preg = calloc(1, sizeof(regex_t));
1742 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1743 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1744 return -1;
1745 }
1746
1747 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1748 }
1749 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1750 regex_t *preg;
1751 if (curproxy == &defproxy) {
1752 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1753 return -1;
1754 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001755 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1756 return 0;
1757
Willy Tarreaubaaee002006-06-26 02:48:02 +02001758 if (*(args[1]) == 0) {
1759 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1760 return -1;
1761 }
1762
1763 preg = calloc(1, sizeof(regex_t));
1764 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1765 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1766 return -1;
1767 }
1768
1769 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1770 }
1771 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1772 regex_t *preg;
1773 if (curproxy == &defproxy) {
1774 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1775 return -1;
1776 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001777 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1778 return 0;
1779
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 if (*(args[1]) == 0) {
1781 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1782 return -1;
1783 }
1784
1785 preg = calloc(1, sizeof(regex_t));
1786 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1787 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1788 return -1;
1789 }
1790
1791 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1792 }
1793 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1794 regex_t *preg;
1795 if (curproxy == &defproxy) {
1796 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1797 return -1;
1798 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001799 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1800 return 0;
1801
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802 if (*(args[1]) == 0) {
1803 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1804 return -1;
1805 }
1806
1807 preg = calloc(1, sizeof(regex_t));
1808 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1809 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1810 return -1;
1811 }
1812
1813 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1814 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001815 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1816 regex_t *preg;
1817 if (curproxy == &defproxy) {
1818 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1819 return -1;
1820 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001821 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1822 return 0;
1823
Willy Tarreaub8750a82006-09-03 09:56:00 +02001824 if (*(args[1]) == 0) {
1825 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1826 return -1;
1827 }
1828
1829 preg = calloc(1, sizeof(regex_t));
1830 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1831 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1832 return -1;
1833 }
1834
1835 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1836 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001837 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1838 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001839 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001840 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1841 return -1;
1842 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001843 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1844 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001845
Willy Tarreau977b8e42006-12-29 14:19:17 +01001846 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001847 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1848 file, linenum, args[0]);
1849 return -1;
1850 }
1851
1852 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001853 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001854 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1855 }
1856
1857 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1858 }
1859 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1860 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001861 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001862 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1863 return -1;
1864 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001865 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1866 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001867
Willy Tarreau977b8e42006-12-29 14:19:17 +01001868 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001869 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1870 file, linenum, args[0]);
1871 return -1;
1872 }
1873
1874 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001875 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001876 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1877 }
1878
1879 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1880 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001881 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1882 regex_t *preg;
1883 if (curproxy == &defproxy) {
1884 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1885 return -1;
1886 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001887 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1888 return 0;
1889
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890 if (*(args[1]) == 0 || *(args[2]) == 0) {
1891 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1892 file, linenum, args[0]);
1893 return -1;
1894 }
1895
1896 preg = calloc(1, sizeof(regex_t));
1897 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1898 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1899 return -1;
1900 }
1901
1902 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1903 if (err) {
1904 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1905 file, linenum, *err);
1906 return -1;
1907 }
1908 }
1909 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1910 regex_t *preg;
1911 if (curproxy == &defproxy) {
1912 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1913 return -1;
1914 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001915 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1916 return 0;
1917
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 if (*(args[1]) == 0) {
1919 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1920 return -1;
1921 }
1922
1923 preg = calloc(1, sizeof(regex_t));
1924 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1925 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1926 return -1;
1927 }
1928
1929 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1930 }
1931 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1932 regex_t *preg;
1933 if (curproxy == &defproxy) {
1934 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1935 return -1;
1936 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001937 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1938 return 0;
1939
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 if (*(args[1]) == 0) {
1941 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1942 return -1;
1943 }
1944
1945 preg = calloc(1, sizeof(regex_t));
1946 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1947 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1948 return -1;
1949 }
1950
1951 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1952 }
1953 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1954 regex_t *preg;
1955 if (curproxy == &defproxy) {
1956 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1957 return -1;
1958 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001959 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1960 return 0;
1961
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962 if (*(args[1]) == 0) {
1963 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1964 return -1;
1965 }
1966
1967 preg = calloc(1, sizeof(regex_t));
1968 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1969 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1970 return -1;
1971 }
1972
1973 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1974 }
1975 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1976 regex_t *preg;
1977 if (curproxy == &defproxy) {
1978 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1979 return -1;
1980 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001981 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1982 return 0;
1983
Willy Tarreaubaaee002006-06-26 02:48:02 +02001984 if (*(args[1]) == 0) {
1985 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1986 return -1;
1987 }
1988
1989 preg = calloc(1, sizeof(regex_t));
1990 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1991 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1992 return -1;
1993 }
1994
1995 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1996 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001997 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1998 regex_t *preg;
1999 if (curproxy == &defproxy) {
2000 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2001 return -1;
2002 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002003 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2004 return 0;
2005
Willy Tarreaub8750a82006-09-03 09:56:00 +02002006 if (*(args[1]) == 0) {
2007 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2008 return -1;
2009 }
2010
2011 preg = calloc(1, sizeof(regex_t));
2012 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2013 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2014 return -1;
2015 }
2016
2017 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2018 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002019 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2020 if (curproxy == &defproxy) {
2021 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2022 return -1;
2023 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002024 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2025 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002026
2027 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2028 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2029 return 0;
2030 }
2031
2032 if (*(args[1]) == 0) {
2033 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2034 return -1;
2035 }
2036
2037 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2038 }
2039 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2040 regex_t *preg;
2041
2042 if (*(args[1]) == 0 || *(args[2]) == 0) {
2043 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2044 file, linenum, args[0]);
2045 return -1;
2046 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002047 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2048 return 0;
2049
Willy Tarreaubaaee002006-06-26 02:48:02 +02002050 preg = calloc(1, sizeof(regex_t));
2051 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2052 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2053 return -1;
2054 }
2055
2056 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2057 if (err) {
2058 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2059 file, linenum, *err);
2060 return -1;
2061 }
2062 }
2063 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2064 regex_t *preg;
2065 if (curproxy == &defproxy) {
2066 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2067 return -1;
2068 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002069 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2070 return 0;
2071
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072 if (*(args[1]) == 0) {
2073 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2074 return -1;
2075 }
2076
2077 preg = calloc(1, sizeof(regex_t));
2078 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2079 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2080 return -1;
2081 }
2082
2083 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2084 if (err) {
2085 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2086 file, linenum, *err);
2087 return -1;
2088 }
2089 }
2090 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2091 regex_t *preg;
2092 if (curproxy == &defproxy) {
2093 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2094 return -1;
2095 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002096 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2097 return 0;
2098
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 if (*(args[1]) == 0) {
2100 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2101 return -1;
2102 }
2103
2104 preg = calloc(1, sizeof(regex_t));
2105 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2106 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2107 return -1;
2108 }
2109
2110 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2111 if (err) {
2112 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2113 file, linenum, *err);
2114 return -1;
2115 }
2116 }
2117 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2118 regex_t *preg;
2119 if (curproxy == &defproxy) {
2120 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2121 return -1;
2122 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002123 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2124 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125
2126 if (*(args[1]) == 0 || *(args[2]) == 0) {
2127 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2128 file, linenum, args[0]);
2129 return -1;
2130 }
2131
2132 preg = calloc(1, sizeof(regex_t));
2133 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2134 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2135 return -1;
2136 }
2137
2138 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2139 if (err) {
2140 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2141 file, linenum, *err);
2142 return -1;
2143 }
2144 }
2145 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2146 regex_t *preg;
2147 if (curproxy == &defproxy) {
2148 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2149 return -1;
2150 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002151 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2152 return 0;
2153
Willy Tarreaubaaee002006-06-26 02:48:02 +02002154 if (*(args[1]) == 0) {
2155 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2156 return -1;
2157 }
2158
2159 preg = calloc(1, sizeof(regex_t));
2160 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2161 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2162 return -1;
2163 }
2164
2165 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2166 if (err) {
2167 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2168 file, linenum, *err);
2169 return -1;
2170 }
2171 }
2172 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2173 regex_t *preg;
2174 if (curproxy == &defproxy) {
2175 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2176 return -1;
2177 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002178 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2179 return 0;
2180
Willy Tarreaubaaee002006-06-26 02:48:02 +02002181 if (*(args[1]) == 0) {
2182 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2183 return -1;
2184 }
2185
2186 preg = calloc(1, sizeof(regex_t));
2187 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2188 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2189 return -1;
2190 }
2191
2192 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2193 if (err) {
2194 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2195 file, linenum, *err);
2196 return -1;
2197 }
2198 }
2199 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2200 if (curproxy == &defproxy) {
2201 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2202 return -1;
2203 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002204 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2205 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002206
2207 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2208 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2209 return 0;
2210 }
2211
2212 if (*(args[1]) == 0) {
2213 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2214 return -1;
2215 }
2216
2217 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2218 }
2219 else if (!strcmp(args[0], "errorloc") ||
2220 !strcmp(args[0], "errorloc302") ||
2221 !strcmp(args[0], "errorloc303")) { /* error location */
2222 int errnum, errlen;
2223 char *err;
2224
Willy Tarreau977b8e42006-12-29 14:19:17 +01002225 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2226 return 0;
2227
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002229 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230 return -1;
2231 }
2232
2233 errnum = atol(args[1]);
2234 if (!strcmp(args[0], "errorloc303")) {
2235 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2236 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2237 } else {
2238 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2239 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2240 }
2241
Willy Tarreau0f772532006-12-23 20:51:41 +01002242 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2243 if (http_err_codes[rc] == errnum) {
2244 if (curproxy->errmsg[rc].str)
2245 free(curproxy->errmsg[rc].str);
2246 curproxy->errmsg[rc].str = err;
2247 curproxy->errmsg[rc].len = errlen;
2248 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002250 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002251
2252 if (rc >= HTTP_ERR_SIZE) {
2253 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2254 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 free(err);
2256 }
2257 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002258 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2259 int errnum, errlen, fd;
2260 char *err;
2261 struct stat stat;
2262
2263 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2264 return 0;
2265
2266 if (*(args[2]) == 0) {
2267 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2268 return -1;
2269 }
2270
2271 fd = open(args[2], O_RDONLY);
2272 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2273 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2274 file, linenum, args[2], args[1]);
2275 if (fd >= 0)
2276 close(fd);
2277 return -1;
2278 }
2279
2280 if (stat.st_size <= BUFSIZE) {
2281 errlen = stat.st_size;
2282 } else {
2283 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2284 file, linenum, args[2], BUFSIZE);
2285 errlen = BUFSIZE;
2286 }
2287
2288 err = malloc(errlen); /* malloc() must succeed during parsing */
2289 errnum = read(fd, err, errlen);
2290 if (errnum != errlen) {
2291 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2292 file, linenum, args[2], args[1]);
2293 close(fd);
2294 free(err);
2295 return -1;
2296 }
2297 close(fd);
2298
2299 errnum = atol(args[1]);
2300 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2301 if (http_err_codes[rc] == errnum) {
2302 if (curproxy->errmsg[rc].str)
2303 free(curproxy->errmsg[rc].str);
2304 curproxy->errmsg[rc].str = err;
2305 curproxy->errmsg[rc].len = errlen;
2306 break;
2307 }
2308 }
2309
2310 if (rc >= HTTP_ERR_SIZE) {
2311 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2312 file, linenum, errnum);
2313 free(err);
2314 }
2315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002316 else {
2317 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2318 return -1;
2319 }
2320 return 0;
2321}
2322
2323
2324/*
2325 * This function reads and parses the configuration file given in the argument.
2326 * returns 0 if OK, -1 if error.
2327 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002328int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002329{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002330 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 FILE *f;
2332 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 int confsect = CFG_NONE;
2335
2336 struct proxy *curproxy = NULL;
2337 struct server *newsrv = NULL;
2338
2339 if ((f=fopen(file,"r")) == NULL)
2340 return -1;
2341
2342 init_default_instance();
2343
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002344 while (fgets(thisline, sizeof(thisline), f) != NULL) {
2345 int arg;
2346 char *end;
2347 char *args[MAX_LINE_ARGS + 1];
2348 char *line = thisline;
2349
Willy Tarreaubaaee002006-06-26 02:48:02 +02002350 linenum++;
2351
2352 end = line + strlen(line);
2353
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002354 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2355 /* Check if we reached the limit and the last char is not \n.
2356 * Watch out for the last line without the terminating '\n'!
2357 */
2358 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2359 file, linenum, sizeof(thisline)-1);
2360 return -1;
2361 }
2362
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002364 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002365 line++;
2366
2367 arg = 0;
2368 args[arg] = line;
2369
2370 while (*line && arg < MAX_LINE_ARGS) {
2371 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2372 * C equivalent value. Other combinations left unchanged (eg: \1).
2373 */
2374 if (*line == '\\') {
2375 int skip = 0;
2376 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2377 *line = line[1];
2378 skip = 1;
2379 }
2380 else if (line[1] == 'r') {
2381 *line = '\r';
2382 skip = 1;
2383 }
2384 else if (line[1] == 'n') {
2385 *line = '\n';
2386 skip = 1;
2387 }
2388 else if (line[1] == 't') {
2389 *line = '\t';
2390 skip = 1;
2391 }
2392 else if (line[1] == 'x') {
2393 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2394 unsigned char hex1, hex2;
2395 hex1 = toupper(line[2]) - '0';
2396 hex2 = toupper(line[3]) - '0';
2397 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2398 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2399 *line = (hex1<<4) + hex2;
2400 skip = 3;
2401 }
2402 else {
2403 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2404 return -1;
2405 }
2406 }
2407 if (skip) {
2408 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2409 end -= skip;
2410 }
2411 line++;
2412 }
2413 else if (*line == '#' || *line == '\n' || *line == '\r') {
2414 /* end of string, end of loop */
2415 *line = 0;
2416 break;
2417 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002418 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002420 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002421 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 line++;
2423 args[++arg] = line;
2424 }
2425 else {
2426 line++;
2427 }
2428 }
2429
2430 /* empty line */
2431 if (!**args)
2432 continue;
2433
Willy Tarreau540abe42007-05-02 20:50:16 +02002434 /* zero out remaining args and ensure that at least one entry
2435 * is zeroed out.
2436 */
2437 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 args[arg] = line;
2439 }
2440
Willy Tarreau977b8e42006-12-29 14:19:17 +01002441 if (!strcmp(args[0], "listen") ||
2442 !strcmp(args[0], "frontend") ||
2443 !strcmp(args[0], "backend") ||
2444 !strcmp(args[0], "ruleset") ||
2445 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446 confsect = CFG_LISTEN;
2447 else if (!strcmp(args[0], "global")) /* global config */
2448 confsect = CFG_GLOBAL;
2449 /* else it's a section keyword */
2450
2451 switch (confsect) {
2452 case CFG_LISTEN:
2453 if (cfg_parse_listen(file, linenum, args) < 0)
2454 return -1;
2455 break;
2456 case CFG_GLOBAL:
2457 if (cfg_parse_global(file, linenum, args) < 0)
2458 return -1;
2459 break;
2460 default:
2461 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2462 return -1;
2463 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002464 }
2465 fclose(f);
2466
2467 /*
2468 * Now, check for the integrity of all that we have collected.
2469 */
2470
2471 /* will be needed further to delay some tasks */
2472 tv_now(&now);
2473
2474 if ((curproxy = proxy) == NULL) {
2475 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2476 file);
2477 return -1;
2478 }
2479
2480 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002481 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002482 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002483
Willy Tarreaubaaee002006-06-26 02:48:02 +02002484 if (curproxy->state == PR_STSTOPPED) {
2485 curproxy = curproxy->next;
2486 continue;
2487 }
2488
Willy Tarreau977b8e42006-12-29 14:19:17 +01002489 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2490 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 +01002491 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002492 cfgerr++;
2493 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002494 else if (curproxy->cap & PR_CAP_BE &&
2495 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002496 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002497 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002498 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2499 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 +01002500 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 cfgerr++;
2502 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002503
Willy Tarreau31682232007-11-29 15:38:04 +01002504 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002505 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002506 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002507 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002508 cfgerr++;
2509 }
2510#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2511 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002512 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002513 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 cfgerr++;
2515 }
2516#endif
2517 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002518 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002519 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002520 }
2521 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002522
2523 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002525 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002526 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002528 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002529 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002530 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 }
2532 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002533 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002534 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002536 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002537 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002538 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002539 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002540 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002541 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2542 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002543
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002544 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002545 file, proxy_type_str(curproxy), curproxy->id);
2546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002548
2549 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2550 if ((newsrv = curproxy->srv) != NULL) {
2551 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2552 file, proxy_type_str(curproxy), curproxy->id);
2553 }
2554 }
2555
2556 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2558 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2559 file, curproxy->id);
2560 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002561 }
2562 }
2563
Willy Tarreau82936582007-11-30 15:20:09 +01002564 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2565 curproxy->options &= ~PR_O_DISABLE404;
2566 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2567 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2568 }
2569
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002570 /* if a default backend was specified, let's find it */
2571 if (curproxy->defbe.name) {
2572 struct proxy *target;
2573
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002574 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2575 if (!target) {
2576 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2577 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002578 cfgerr++;
2579 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002580 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2581 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002582 } else {
2583 free(curproxy->defbe.name);
2584 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 }
2586 }
2587
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002588 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002589 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2590 /* map jump target for ACT_SETBE in req_rep chain */
2591 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002592 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002593 struct proxy *target;
2594
Willy Tarreaua496b602006-12-17 23:15:24 +01002595 if (exp->action != ACT_SETBE)
2596 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002597
2598 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2599 if (!target) {
2600 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2601 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002602 cfgerr++;
2603 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002604 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2605 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002606 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002607 } else {
2608 free((void *)exp->replace);
2609 exp->replace = (const char *)target;
2610 }
2611 }
2612 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002613
2614 /* find the target proxy for 'use_backend' rules */
2615 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002616 struct proxy *target;
2617
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002618 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002619
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002620 if (!target) {
2621 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2622 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002623 cfgerr++;
2624 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002625 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2626 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002627 cfgerr++;
2628 } else {
2629 free((void *)rule->be.name);
2630 rule->be.backend = target;
2631 }
2632 }
2633
Willy Tarreau2738a142006-07-08 17:28:09 +02002634 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002635 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2636 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2637 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002638 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002639 " | While not properly invalid, you will certainly encounter various problems\n"
2640 " | with such a configuration. To fix this, please ensure that all following\n"
2641 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002642 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002643 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002644
2645 if (curproxy->options & PR_O_SSL3_CHK) {
2646 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2647 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2648 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2649 }
2650
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002651 /* The small pools required for the capture lists */
2652 if (curproxy->nb_req_cap)
2653 curproxy->req_cap_pool = create_pool("ptrcap",
2654 curproxy->nb_req_cap * sizeof(char *),
2655 MEM_F_SHARED);
2656 if (curproxy->nb_rsp_cap)
2657 curproxy->rsp_cap_pool = create_pool("ptrcap",
2658 curproxy->nb_rsp_cap * sizeof(char *),
2659 MEM_F_SHARED);
2660
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002661 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2662 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2663 MEM_F_SHARED);
2664
Willy Tarreau86034312006-12-29 00:10:33 +01002665 /* for backwards compatibility with "listen" instances, if
2666 * fullconn is not set but maxconn is set, then maxconn
2667 * is used.
2668 */
2669 if (!curproxy->fullconn)
2670 curproxy->fullconn = curproxy->maxconn;
2671
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 /* first, we will invert the servers list order */
2673 newsrv = NULL;
2674 while (curproxy->srv) {
2675 struct server *next;
2676
2677 next = curproxy->srv->next;
2678 curproxy->srv->next = newsrv;
2679 newsrv = curproxy->srv;
2680 if (!next)
2681 break;
2682 curproxy->srv = next;
2683 }
2684
Willy Tarreau20697042007-11-15 23:26:18 +01002685 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01002686 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687
Willy Tarreaub625a082007-11-26 01:15:43 +01002688 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01002689 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01002690 fwrr_init_server_groups(curproxy);
2691 else
2692 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002693
2694 if (curproxy->options & PR_O_LOGASAP)
2695 curproxy->to_log &= ~LW_BYTES;
2696
Willy Tarreaubaaee002006-06-26 02:48:02 +02002697 /*
2698 * If this server supports a maxconn parameter, it needs a dedicated
2699 * tasks to fill the emptied slots when a connection leaves.
2700 */
2701 newsrv = curproxy->srv;
2702 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002703 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002704 /* Only 'minconn' was specified, or it was higher than or equal
2705 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2706 * this will avoid further useless expensive computations.
2707 */
2708 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002709 } else if (newsrv->maxconn && !newsrv->minconn) {
2710 /* minconn was not specified, so we set it to maxconn */
2711 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002712 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2713 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002714 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002715 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716 }
2717
2718 if (newsrv->maxconn > 0) {
2719 struct task *t;
2720
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002721 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002722 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2723 return -1;
2724 }
2725
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002726 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002727 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728 t->state = TASK_IDLE;
2729 t->process = process_srv_queue;
2730 t->context = newsrv;
2731 newsrv->queue_mgt = t;
2732
2733 /* never run it unless specifically woken up */
2734 tv_eternity(&t->expire);
2735 task_queue(t);
2736 }
2737 newsrv = newsrv->next;
2738 }
2739
Willy Tarreaue6b98942007-10-29 01:09:36 +01002740 /* adjust this proxy's listeners */
2741 listener = curproxy->listen;
2742 while (listener) {
2743 if (curproxy->options & PR_O_TCP_NOLING)
2744 listener->options |= LI_O_NOLINGER;
2745 listener->maxconn = curproxy->maxconn;
2746 listener->timeout = &curproxy->clitimeout;
2747 listener->accept = event_accept;
2748 listener->private = curproxy;
2749
2750 listener = listener->next;
2751 }
2752
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 curproxy = curproxy->next;
2754 }
2755 if (cfgerr > 0) {
2756 Alert("Errors found in configuration file, aborting.\n");
2757 return -1;
2758 }
2759 else
2760 return 0;
2761}
2762
2763
2764
2765/*
2766 * Local variables:
2767 * c-indent-level: 8
2768 * c-basic-offset: 8
2769 * End:
2770 */