blob: 05864d82e962b9bdf2d0d1472566d2a17b67b5c8 [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 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100100 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100101 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100102 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
103 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
104 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
105 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
106 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
107 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
108 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
109 { "forceclose", PR_O_FORCE_CLO | PR_O_HTTP_CLOSE, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100110#ifdef CONFIG_HAP_TCPSPLICE
111 { "tcpsplice", PR_O_TCPSPLICE , PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
112#endif
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114 { NULL, 0, 0 }
115};
116
Willy Tarreaubaaee002006-06-26 02:48:02 +0200117
118static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
119int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
120int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
121
122/*
123 * converts <str> to a list of listeners which are dynamically allocated.
124 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
125 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
126 * - <port> is a numerical port from 1 to 65535 ;
127 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
128 * This can be repeated as many times as necessary, separated by a coma.
129 * The <tail> argument is a pointer to a current list which should be appended
130 * to the tail of the new list. The pointer to the new list is returned.
131 */
132static struct listener *str2listener(char *str, struct listener *tail)
133{
134 struct listener *l;
135 char *c, *next, *range, *dupstr;
136 int port, end;
137
138 next = dupstr = strdup(str);
139
140 while (next && *next) {
141 struct sockaddr_storage ss;
142
143 str = next;
144 /* 1) look for the end of the first address */
145 if ((next = strrchr(str, ',')) != NULL) {
146 *next++ = 0;
147 }
148
149 /* 2) look for the addr/port delimiter, it's the last colon. */
150 if ((range = strrchr(str, ':')) == NULL) {
151 Alert("Missing port number: '%s'\n", str);
152 goto fail;
153 }
154
155 *range++ = 0;
156
157 if (strrchr(str, ':') != NULL) {
158 /* IPv6 address contains ':' */
159 memset(&ss, 0, sizeof(ss));
160 ss.ss_family = AF_INET6;
161
162 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
163 Alert("Invalid server address: '%s'\n", str);
164 goto fail;
165 }
166 }
167 else {
168 memset(&ss, 0, sizeof(ss));
169 ss.ss_family = AF_INET;
170
171 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
172 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
173 }
174 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
175 struct hostent *he;
176
177 if ((he = gethostbyname(str)) == NULL) {
178 Alert("Invalid server name: '%s'\n", str);
179 goto fail;
180 }
181 else
182 ((struct sockaddr_in *)&ss)->sin_addr =
183 *(struct in_addr *) *(he->h_addr_list);
184 }
185 }
186
187 /* 3) look for the port-end delimiter */
188 if ((c = strchr(range, '-')) != NULL) {
189 *c++ = 0;
190 end = atol(c);
191 }
192 else {
193 end = atol(range);
194 }
195
196 port = atol(range);
197
198 if (port < 1 || port > 65535) {
199 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
200 goto fail;
201 }
202
203 if (end < 1 || end > 65535) {
204 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
205 goto fail;
206 }
207
208 for (; port <= end; port++) {
209 l = (struct listener *)calloc(1, sizeof(struct listener));
210 l->next = tail;
211 tail = l;
212
213 l->fd = -1;
214 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100215 l->state = LI_INIT;
216
217 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200218 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100219 tcpv6_add_listener(l);
220 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100222 tcpv4_add_listener(l);
223 }
224 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 } /* end for(port) */
226 } /* end while(next) */
227 free(dupstr);
228 return tail;
229 fail:
230 free(dupstr);
231 return NULL;
232}
233
Willy Tarreau977b8e42006-12-29 14:19:17 +0100234/*
235 * Sends a warning if proxy <proxy> does not have at least one of the
236 * capabilities in <cap>. An optionnal <hint> may be added at the end
237 * of the warning to help the user. Returns 1 if a warning was emitted
238 * or 0 if the condition is valid.
239 */
240int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
241{
242 char *msg;
243
244 switch (cap) {
245 case PR_CAP_BE: msg = "no backend"; break;
246 case PR_CAP_FE: msg = "no frontend"; break;
247 case PR_CAP_RS: msg = "no ruleset"; break;
248 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
249 default: msg = "not enough"; break;
250 }
251
252 if (!(proxy->cap & cap)) {
253 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100254 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100255 return 1;
256 }
257 return 0;
258}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200259
260/*
261 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
262 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200263int cfg_parse_global(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264{
265
266 if (!strcmp(args[0], "global")) { /* new section */
267 /* no option, nothing special to do */
268 return 0;
269 }
270 else if (!strcmp(args[0], "daemon")) {
271 global.mode |= MODE_DAEMON;
272 }
273 else if (!strcmp(args[0], "debug")) {
274 global.mode |= MODE_DEBUG;
275 }
276 else if (!strcmp(args[0], "noepoll")) {
277 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
278 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200279 else if (!strcmp(args[0], "nosepoll")) {
280 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
281 }
282 else if (!strcmp(args[0], "nokqueue")) {
283 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285 else if (!strcmp(args[0], "nopoll")) {
286 cfg_polling_mechanism &= ~POLL_USE_POLL;
287 }
288 else if (!strcmp(args[0], "quiet")) {
289 global.mode |= MODE_QUIET;
290 }
291 else if (!strcmp(args[0], "stats")) {
Willy Tarreaufbee7132007-10-18 13:53:22 +0200292 memcpy(trash, "error near 'stats'", 19);
293 if (stats_parse_global((const char **)args + 1, trash, sizeof(trash)) < 0) {
294 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
295 return -1;
296 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200298 else if (!strcmp(args[0], "tune.maxpollevents")) {
299 if (global.tune.maxpollevents != 0) {
300 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
301 return 0;
302 }
303 if (*(args[1]) == 0) {
304 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
305 return -1;
306 }
307 global.tune.maxpollevents = atol(args[1]);
308 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200309 else if (!strcmp(args[0], "uid")) {
310 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200311 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200312 return 0;
313 }
314 if (*(args[1]) == 0) {
315 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
316 return -1;
317 }
318 global.uid = atol(args[1]);
319 }
320 else if (!strcmp(args[0], "gid")) {
321 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200322 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323 return 0;
324 }
325 if (*(args[1]) == 0) {
326 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
327 return -1;
328 }
329 global.gid = atol(args[1]);
330 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200331 /* user/group name handling */
332 else if (!strcmp(args[0], "user")) {
333 struct passwd *ha_user;
334 if (global.uid != 0) {
335 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
336 return 0;
337 }
338 errno = 0;
339 ha_user = getpwnam(args[1]);
340 if (ha_user != NULL) {
341 global.uid = (int)ha_user->pw_uid;
342 }
343 else {
344 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
345 exit(1);
346 }
347 }
348 else if (!strcmp(args[0], "group")) {
349 struct group *ha_group;
350 if (global.gid != 0) {
351 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
352 return 0;
353 }
354 errno = 0;
355 ha_group = getgrnam(args[1]);
356 if (ha_group != NULL) {
357 global.gid = (int)ha_group->gr_gid;
358 }
359 else {
360 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
361 exit(1);
362 }
363 }
364 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200365 else if (!strcmp(args[0], "nbproc")) {
366 if (global.nbproc != 0) {
367 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
368 return 0;
369 }
370 if (*(args[1]) == 0) {
371 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
372 return -1;
373 }
374 global.nbproc = atol(args[1]);
375 }
376 else if (!strcmp(args[0], "maxconn")) {
377 if (global.maxconn != 0) {
378 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
379 return 0;
380 }
381 if (*(args[1]) == 0) {
382 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
383 return -1;
384 }
385 global.maxconn = atol(args[1]);
386#ifdef SYSTEM_MAXCONN
387 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
388 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);
389 global.maxconn = DEFAULT_MAXCONN;
390 }
391#endif /* SYSTEM_MAXCONN */
392 }
393 else if (!strcmp(args[0], "ulimit-n")) {
394 if (global.rlimit_nofile != 0) {
395 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
396 return 0;
397 }
398 if (*(args[1]) == 0) {
399 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
400 return -1;
401 }
402 global.rlimit_nofile = atol(args[1]);
403 }
404 else if (!strcmp(args[0], "chroot")) {
405 if (global.chroot != NULL) {
406 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
407 return 0;
408 }
409 if (*(args[1]) == 0) {
410 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
411 return -1;
412 }
413 global.chroot = strdup(args[1]);
414 }
415 else if (!strcmp(args[0], "pidfile")) {
416 if (global.pidfile != NULL) {
417 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
418 return 0;
419 }
420 if (*(args[1]) == 0) {
421 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
422 return -1;
423 }
424 global.pidfile = strdup(args[1]);
425 }
426 else if (!strcmp(args[0], "log")) { /* syslog server address */
427 struct sockaddr_in *sa;
428 int facility, level;
429
430 if (*(args[1]) == 0 || *(args[2]) == 0) {
431 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
432 return -1;
433 }
434
435 facility = get_log_facility(args[2]);
436 if (facility < 0) {
437 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
438 exit(1);
439 }
440
441 level = 7; /* max syslog level = debug */
442 if (*(args[3])) {
443 level = get_log_level(args[3]);
444 if (level < 0) {
445 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
446 exit(1);
447 }
448 }
449
450 sa = str2sa(args[1]);
451 if (!sa->sin_port)
452 sa->sin_port = htons(SYSLOG_PORT);
453
454 if (global.logfac1 == -1) {
455 global.logsrv1 = *sa;
456 global.logfac1 = facility;
457 global.loglev1 = level;
458 }
459 else if (global.logfac2 == -1) {
460 global.logsrv2 = *sa;
461 global.logfac2 = facility;
462 global.loglev2 = level;
463 }
464 else {
465 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
466 return -1;
467 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200468 }
469 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
470 if (global.spread_checks != 0) {
471 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
472 return 0;
473 }
474 if (*(args[1]) == 0) {
475 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
476 return -1;
477 }
478 global.spread_checks = atol(args[1]);
479 if (global.spread_checks < 0 || global.spread_checks > 50) {
480 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
481 return -1;
482 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483 }
484 else {
485 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
486 return -1;
487 }
488 return 0;
489}
490
491
492static void init_default_instance()
493{
494 memset(&defproxy, 0, sizeof(defproxy));
495 defproxy.mode = PR_MODE_TCP;
496 defproxy.state = PR_STNEW;
497 defproxy.maxconn = cfg_maxpconn;
498 defproxy.conn_retries = CONN_RETRIES;
499 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaufdd0f552007-09-17 11:12:40 +0200500 tv_eternity(&defproxy.clitimeout);
501 tv_eternity(&defproxy.contimeout);
502 tv_eternity(&defproxy.srvtimeout);
503 tv_eternity(&defproxy.appsession_timeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200504}
505
506/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100507 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
508 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200510int cfg_parse_listen(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200511{
512 static struct proxy *curproxy = NULL;
513 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200514 const char *err;
Willy Tarreauee991362007-05-14 14:37:50 +0200515 int rc, val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200516
Willy Tarreau977b8e42006-12-29 14:19:17 +0100517 if (!strcmp(args[0], "listen"))
518 rc = PR_CAP_LISTEN;
519 else if (!strcmp(args[0], "frontend"))
520 rc = PR_CAP_FE | PR_CAP_RS;
521 else if (!strcmp(args[0], "backend"))
522 rc = PR_CAP_BE | PR_CAP_RS;
523 else if (!strcmp(args[0], "ruleset"))
524 rc = PR_CAP_RS;
525 else
526 rc = PR_CAP_NONE;
527
528 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200529 if (!*args[1]) {
530 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
531 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
532 file, linenum, args[0]);
533 return -1;
534 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200535
536 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
537 /*
538 * If there are two proxies with the same name only following
539 * combinations are allowed:
540 *
541 * listen backend frontend ruleset
542 * listen - - - -
543 * backend - - OK -
544 * frontend - OK - -
545 * ruleset - - - -
546 */
547
548 if (!strcmp(curproxy->id, args[1]) &&
549 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
550 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100551 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
552 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200553 }
554 }
555
Willy Tarreaubaaee002006-06-26 02:48:02 +0200556 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
557 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
558 return -1;
559 }
560
561 curproxy->next = proxy;
562 proxy = curproxy;
563 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200564 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200565 LIST_INIT(&curproxy->block_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200566 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567
Willy Tarreauee991362007-05-14 14:37:50 +0200568 /* Timeouts are defined as -1, so we cannot use the zeroed area
569 * as a default value.
570 */
571 tv_eternity(&curproxy->clitimeout);
572 tv_eternity(&curproxy->srvtimeout);
573 tv_eternity(&curproxy->contimeout);
574 tv_eternity(&curproxy->appsession_timeout);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200575
576 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100578 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579
580 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100581 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582 curproxy->listen = str2listener(args[2], curproxy->listen);
583 if (!curproxy->listen)
584 return -1;
585 global.maxsock++;
586 }
587
588 /* set default values */
589 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 curproxy->options = defproxy.options;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200591 curproxy->except_net = defproxy.except_net;
592 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200593
Willy Tarreau977b8e42006-12-29 14:19:17 +0100594 if (curproxy->cap & PR_CAP_FE) {
595 curproxy->maxconn = defproxy.maxconn;
596
597 /* initialize error relocations */
598 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
599 if (defproxy.errmsg[rc].str)
600 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
601 }
602
603 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
604 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200605
Willy Tarreau977b8e42006-12-29 14:19:17 +0100606 if (curproxy->cap & PR_CAP_BE) {
607 curproxy->fullconn = defproxy.fullconn;
608 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200609
Willy Tarreau977b8e42006-12-29 14:19:17 +0100610 if (defproxy.check_req)
611 curproxy->check_req = strdup(defproxy.check_req);
612 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613
Willy Tarreau977b8e42006-12-29 14:19:17 +0100614 if (defproxy.cookie_name)
615 curproxy->cookie_name = strdup(defproxy.cookie_name);
616 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100617
618 if (defproxy.url_param_name)
619 curproxy->url_param_name = strdup(defproxy.url_param_name);
620 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100621 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622
Willy Tarreau977b8e42006-12-29 14:19:17 +0100623 if (curproxy->cap & PR_CAP_RS) {
624 if (defproxy.capture_name)
625 curproxy->capture_name = strdup(defproxy.capture_name);
626 curproxy->capture_namelen = defproxy.capture_namelen;
627 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629
Willy Tarreau977b8e42006-12-29 14:19:17 +0100630 if (curproxy->cap & PR_CAP_FE) {
631 curproxy->clitimeout = defproxy.clitimeout;
632 curproxy->uri_auth = defproxy.uri_auth;
633 curproxy->mon_net = defproxy.mon_net;
634 curproxy->mon_mask = defproxy.mon_mask;
635 if (defproxy.monitor_uri)
636 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
637 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100638 if (defproxy.defbe.name)
639 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100640 }
641
642 if (curproxy->cap & PR_CAP_BE) {
643 curproxy->contimeout = defproxy.contimeout;
644 curproxy->srvtimeout = defproxy.srvtimeout;
645 curproxy->source_addr = defproxy.source_addr;
646 }
647
Willy Tarreaubaaee002006-06-26 02:48:02 +0200648 curproxy->mode = defproxy.mode;
649 curproxy->logfac1 = defproxy.logfac1;
650 curproxy->logsrv1 = defproxy.logsrv1;
651 curproxy->loglev1 = defproxy.loglev1;
652 curproxy->logfac2 = defproxy.logfac2;
653 curproxy->logsrv2 = defproxy.logsrv2;
654 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200655 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100656 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
657 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200658
Willy Tarreaubaaee002006-06-26 02:48:02 +0200659 return 0;
660 }
661 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
662 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100663 /* FIXME-20070101: we should do this too at the end of the
664 * config parsing to free all default values.
665 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 if (defproxy.check_req) free(defproxy.check_req);
667 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100668 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200670 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100671 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100672
673 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
674 if (defproxy.errmsg[rc].len)
675 free(defproxy.errmsg[rc].str);
676 }
677
Willy Tarreaubaaee002006-06-26 02:48:02 +0200678 /* we cannot free uri_auth because it might already be used */
679 init_default_instance();
680 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100681 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 return 0;
683 }
684 else if (curproxy == NULL) {
685 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
686 return -1;
687 }
688
Willy Tarreau977b8e42006-12-29 14:19:17 +0100689
690 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200691 if (!strcmp(args[0], "bind")) { /* new listen addresses */
692 if (curproxy == &defproxy) {
693 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
694 return -1;
695 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100696 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
697 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698
699 if (strchr(args[1], ':') == NULL) {
700 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
701 file, linenum, args[0]);
702 return -1;
703 }
704 curproxy->listen = str2listener(args[1], curproxy->listen);
705 if (!curproxy->listen)
706 return -1;
707 global.maxsock++;
708 return 0;
709 }
710 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
711 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
712 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
713 file, linenum, args[0]);
714 return -1;
715 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100716 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
717 return 0;
718
Willy Tarreaubaaee002006-06-26 02:48:02 +0200719 /* flush useless bits */
720 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
721 return 0;
722 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200723 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100724 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
725 return 0;
726
Willy Tarreau1c47f852006-07-09 08:22:27 +0200727 if (!*args[1]) {
728 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
729 file, linenum, args[0]);
730 return -1;
731 }
732
733 if (curproxy->monitor_uri != NULL)
734 free(curproxy->monitor_uri);
735
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100736 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200737 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100738 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200739 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
740
741 return 0;
742 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200743 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
744 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
745 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
746 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
747 else {
748 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
749 return -1;
750 }
751 }
752 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
753 curproxy->state = PR_STSTOPPED;
754 }
755 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
756 curproxy->state = PR_STNEW;
757 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200758 else if (!strcmp(args[0], "acl")) { /* add an ACL */
759 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
760 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
761 file, linenum, args[1]);
762 return -1;
763 }
764 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200765 else if (!strcmp(args[0], "cookie")) { /* cookie name */
766 int cur_arg;
767 // if (curproxy == &defproxy) {
768 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
769 // return -1;
770 // }
771
Willy Tarreau977b8e42006-12-29 14:19:17 +0100772 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
773 return 0;
774
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 if (curproxy->cookie_name != NULL) {
776 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
777 // file, linenum);
778 // return 0;
779 free(curproxy->cookie_name);
780 }
781
782 if (*(args[1]) == 0) {
783 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
784 file, linenum, args[0]);
785 return -1;
786 }
787 curproxy->cookie_name = strdup(args[1]);
788 curproxy->cookie_len = strlen(curproxy->cookie_name);
789
790 cur_arg = 2;
791 while (*(args[cur_arg])) {
792 if (!strcmp(args[cur_arg], "rewrite")) {
793 curproxy->options |= PR_O_COOK_RW;
794 }
795 else if (!strcmp(args[cur_arg], "indirect")) {
796 curproxy->options |= PR_O_COOK_IND;
797 }
798 else if (!strcmp(args[cur_arg], "insert")) {
799 curproxy->options |= PR_O_COOK_INS;
800 }
801 else if (!strcmp(args[cur_arg], "nocache")) {
802 curproxy->options |= PR_O_COOK_NOC;
803 }
804 else if (!strcmp(args[cur_arg], "postonly")) {
805 curproxy->options |= PR_O_COOK_POST;
806 }
807 else if (!strcmp(args[cur_arg], "prefix")) {
808 curproxy->options |= PR_O_COOK_PFX;
809 }
810 else {
811 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
812 file, linenum, args[0]);
813 return -1;
814 }
815 cur_arg++;
816 }
817 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
818 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
819 file, linenum);
820 return -1;
821 }
822
823 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
824 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
825 file, linenum);
826 return -1;
827 }
828 }/* end else if (!strcmp(args[0], "cookie")) */
829 else if (!strcmp(args[0], "appsession")) { /* cookie name */
830 // if (curproxy == &defproxy) {
831 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
832 // return -1;
833 // }
834
Willy Tarreau977b8e42006-12-29 14:19:17 +0100835 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
836 return 0;
837
Willy Tarreaubaaee002006-06-26 02:48:02 +0200838 if (curproxy->appsession_name != NULL) {
839 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
840 // file, linenum);
841 // return 0;
842 free(curproxy->appsession_name);
843 }
844
845 if (*(args[5]) == 0) {
846 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
847 file, linenum, args[0]);
848 return -1;
849 }
850 have_appsession = 1;
851 curproxy->appsession_name = strdup(args[1]);
852 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
853 curproxy->appsession_len = atoi(args[3]);
Willy Tarreauee991362007-05-14 14:37:50 +0200854 val = atoi(args[5]);
855 if (val > 0)
856 __tv_from_ms(&curproxy->appsession_timeout, val);
857 else
858 tv_eternity(&curproxy->appsession_timeout);
859
Willy Tarreau51041c72007-09-09 21:56:53 +0200860 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
861 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200862 return -1;
863 }
864 } /* Url App Session */
865 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100866 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
867 return 0;
868
Willy Tarreaubaaee002006-06-26 02:48:02 +0200869 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
870 // if (curproxy == &defproxy) {
871 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
872 // return -1;
873 // }
874
875 if (curproxy->capture_name != NULL) {
876 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
877 // file, linenum, args[0]);
878 // return 0;
879 free(curproxy->capture_name);
880 }
881
882 if (*(args[4]) == 0) {
883 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
884 file, linenum, args[0]);
885 return -1;
886 }
887 curproxy->capture_name = strdup(args[2]);
888 curproxy->capture_namelen = strlen(curproxy->capture_name);
889 curproxy->capture_len = atol(args[4]);
890 if (curproxy->capture_len >= CAPTURE_LEN) {
891 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
892 file, linenum, CAPTURE_LEN - 1);
893 curproxy->capture_len = CAPTURE_LEN - 1;
894 }
895 curproxy->to_log |= LW_COOKIE;
896 }
897 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
898 struct cap_hdr *hdr;
899
900 if (curproxy == &defproxy) {
901 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
902 return -1;
903 }
904
905 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
906 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
907 file, linenum, args[0], args[1]);
908 return -1;
909 }
910
911 hdr = calloc(sizeof(struct cap_hdr), 1);
912 hdr->next = curproxy->req_cap;
913 hdr->name = strdup(args[3]);
914 hdr->namelen = strlen(args[3]);
915 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200916 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 hdr->index = curproxy->nb_req_cap++;
918 curproxy->req_cap = hdr;
919 curproxy->to_log |= LW_REQHDR;
920 }
921 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
922 struct cap_hdr *hdr;
923
924 if (curproxy == &defproxy) {
925 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
926 return -1;
927 }
928
929 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
930 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
931 file, linenum, args[0], args[1]);
932 return -1;
933 }
934 hdr = calloc(sizeof(struct cap_hdr), 1);
935 hdr->next = curproxy->rsp_cap;
936 hdr->name = strdup(args[3]);
937 hdr->namelen = strlen(args[3]);
938 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200939 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940 hdr->index = curproxy->nb_rsp_cap++;
941 curproxy->rsp_cap = hdr;
942 curproxy->to_log |= LW_RSPHDR;
943 }
944 else {
945 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
946 file, linenum, args[0]);
947 return -1;
948 }
949 }
950 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200951 if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
953 return 0;
954 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100955 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
956 return 0;
957
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958 if (*(args[1]) == 0) {
959 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
960 file, linenum, args[0]);
961 return -1;
962 }
Willy Tarreauee991362007-05-14 14:37:50 +0200963 val = atoi(args[1]);
964 if (val > 0)
965 __tv_from_ms(&curproxy->contimeout, val);
966 else
967 tv_eternity(&curproxy->contimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
969 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200970 if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200971 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
972 file, linenum, args[0]);
973 return 0;
974 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100975 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
976 return 0;
977
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978 if (*(args[1]) == 0) {
979 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
980 file, linenum, args[0]);
981 return -1;
982 }
Willy Tarreauee991362007-05-14 14:37:50 +0200983 val = atoi(args[1]);
984 if (val > 0)
985 __tv_from_ms(&curproxy->clitimeout, val);
986 else
987 tv_eternity(&curproxy->clitimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988 }
989 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200990 if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200991 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
992 return 0;
993 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100994 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
995 return 0;
996
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 if (*(args[1]) == 0) {
998 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
999 file, linenum, args[0]);
1000 return -1;
1001 }
Willy Tarreauee991362007-05-14 14:37:50 +02001002 val = atoi(args[1]);
1003 if (val > 0)
1004 __tv_from_ms(&curproxy->srvtimeout, val);
1005 else
1006 tv_eternity(&curproxy->srvtimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001007 }
1008 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001009 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1010 return 0;
1011
Willy Tarreaubaaee002006-06-26 02:48:02 +02001012 if (*(args[1]) == 0) {
1013 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1014 file, linenum, args[0]);
1015 return -1;
1016 }
1017 curproxy->conn_retries = atol(args[1]);
1018 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001019 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1020 int pol = ACL_COND_NONE;
1021 struct acl_cond *cond;
1022
1023 if (!strcmp(args[1], "if"))
1024 pol = ACL_COND_IF;
1025 else if (!strcmp(args[1], "unless"))
1026 pol = ACL_COND_UNLESS;
1027
1028 if (pol == ACL_COND_NONE) {
1029 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1030 file, linenum, args[0]);
1031 return -1;
1032 }
1033
1034 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1035 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1036 file, linenum);
1037 return -1;
1038 }
1039 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1040 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001041 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1042 int pol = ACL_COND_NONE;
1043 struct acl_cond *cond;
1044 struct switching_rule *rule;
1045
1046 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1047 return 0;
1048
1049 if (*(args[1]) == 0) {
1050 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1051 return -1;
1052 }
1053
1054 if (!strcmp(args[2], "if"))
1055 pol = ACL_COND_IF;
1056 else if (!strcmp(args[2], "unless"))
1057 pol = ACL_COND_UNLESS;
1058
1059 if (pol == ACL_COND_NONE) {
1060 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1061 file, linenum, args[0]);
1062 return -1;
1063 }
1064
1065 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1066 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1067 file, linenum);
1068 return -1;
1069 }
1070
1071 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1072 rule->cond = cond;
1073 rule->be.name = strdup(args[1]);
1074 LIST_INIT(&rule->list);
1075 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1076 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001077 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001078 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1079 return 0;
1080
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1082 curproxy->uri_auth = NULL; /* we must detach from the default config */
1083
1084 if (*(args[1]) == 0) {
1085 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1086 return -1;
1087 } else if (!strcmp(args[1], "uri")) {
1088 if (*(args[2]) == 0) {
1089 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1090 return -1;
1091 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1092 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1093 return -1;
1094 }
1095 } else if (!strcmp(args[1], "realm")) {
1096 if (*(args[2]) == 0) {
1097 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1098 return -1;
1099 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1100 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1101 return -1;
1102 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001103 } else if (!strcmp(args[1], "refresh")) {
1104 int interval = atoi(args[2]);
1105
1106 if (interval < 0) {
1107 Alert("parsing [%s:%d] : 'refresh' needs a positive interval in seconds.\n", file, linenum);
1108 return -1;
1109 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1110 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1111 return -1;
1112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001113 } else if (!strcmp(args[1], "auth")) {
1114 if (*(args[2]) == 0) {
1115 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1116 return -1;
1117 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1118 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1119 return -1;
1120 }
1121 } else if (!strcmp(args[1], "scope")) {
1122 if (*(args[2]) == 0) {
1123 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1124 return -1;
1125 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1126 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1127 return -1;
1128 }
1129 } else if (!strcmp(args[1], "enable")) {
1130 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1131 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1132 return -1;
1133 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001134 } else if (!strcmp(args[1], "hide-version")) {
1135 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1136 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1137 return -1;
1138 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001139 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001140 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 file, linenum, args[0]);
1142 return -1;
1143 }
1144 }
1145 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001146 int optnum;
1147
Willy Tarreaubaaee002006-06-26 02:48:02 +02001148 if (*(args[1]) == 0) {
1149 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
1150 return -1;
1151 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001152
1153 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1154 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1155 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1156 return 0;
1157 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001158 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001159 return 0;
1160 }
1161 }
1162
1163 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001164 /* generate a complete HTTP log */
1165 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1166 else if (!strcmp(args[1], "tcplog"))
1167 /* generate a detailed TCP log */
1168 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169 else if (!strcmp(args[1], "tcpka")) {
1170 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001171 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1172 return 0;
1173
1174 if (curproxy->cap & PR_CAP_FE)
1175 curproxy->options |= PR_O_TCP_CLI_KA;
1176 if (curproxy->cap & PR_CAP_BE)
1177 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178 }
1179 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001180 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1181 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182 /* use HTTP request to check servers' health */
1183 if (curproxy->check_req != NULL) {
1184 free(curproxy->check_req);
1185 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001186 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001187 curproxy->options &= ~PR_O_SMTP_CHK;
1188 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001189 if (!*args[2]) { /* no argument */
1190 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1191 curproxy->check_len = strlen(DEF_CHECK_REQ);
1192 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001193 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001194 curproxy->check_req = (char *)malloc(reqlen);
1195 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1196 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1197 } else { /* more arguments : METHOD URI [HTTP_VER] */
1198 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1199 if (*args[4])
1200 reqlen += strlen(args[4]);
1201 else
1202 reqlen += strlen("HTTP/1.0");
1203
1204 curproxy->check_req = (char *)malloc(reqlen);
1205 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1206 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1207 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001208 }
1209 else if (!strcmp(args[1], "ssl-hello-chk")) {
1210 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001211 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1212 return 0;
1213
Willy Tarreauf3c69202006-07-09 16:42:34 +02001214 if (curproxy->check_req != NULL) {
1215 free(curproxy->check_req);
1216 }
1217 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001218 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001219 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001220 }
Willy Tarreau23677902007-05-08 23:50:35 +02001221 else if (!strcmp(args[1], "smtpchk")) {
1222 /* use SMTP request to check servers' health */
1223 if (curproxy->check_req != NULL) {
1224 free(curproxy->check_req);
1225 }
1226 curproxy->options &= ~PR_O_HTTP_CHK;
1227 curproxy->options &= ~PR_O_SSL3_CHK;
1228 curproxy->options |= PR_O_SMTP_CHK;
1229
1230 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1231 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1232 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1233 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1234 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1235 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1236 curproxy->check_req = (char *)malloc(reqlen);
1237 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1238 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1239 } else {
1240 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1241 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1242 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1243 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1244 }
1245 }
1246 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001247 else if (!strcmp(args[1], "forwardfor")) {
1248 /* insert x-forwarded-for field, but not for the
1249 * IP address listed as an except.
1250 */
1251 if (*(args[2])) {
1252 if (!strcmp(args[2], "except")) {
1253 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1254 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1255 file, linenum, args[0]);
1256 return -1;
1257 }
1258 /* flush useless bits */
1259 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1260 } else {
1261 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1262 file, linenum, args[0]);
1263 return -1;
1264 }
1265 }
1266 curproxy->options |= PR_O_FWDFOR;
1267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001268 else {
1269 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1270 return -1;
1271 }
1272 return 0;
1273 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001274 else if (!strcmp(args[0], "default_backend")) {
1275 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1276 return 0;
1277
1278 if (*(args[1]) == 0) {
1279 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1280 return -1;
1281 }
1282 if (curproxy->defbe.name)
1283 free(curproxy->defbe.name);
1284 curproxy->defbe.name = strdup(args[1]);
1285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001286 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001287 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1288 return 0;
1289
Willy Tarreaubaaee002006-06-26 02:48:02 +02001290 /* enable reconnections to dispatch */
1291 curproxy->options |= PR_O_REDISP;
1292 }
1293#ifdef TPROXY
1294 else if (!strcmp(args[0], "transparent")) {
1295 /* enable transparent proxy connections */
1296 curproxy->options |= PR_O_TRANSP;
1297 }
1298#endif
1299 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001300 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1301 return 0;
1302
Willy Tarreaubaaee002006-06-26 02:48:02 +02001303 if (*(args[1]) == 0) {
1304 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1305 return -1;
1306 }
1307 curproxy->maxconn = atol(args[1]);
1308 }
Willy Tarreau86034312006-12-29 00:10:33 +01001309 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001310 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1311 return 0;
1312
Willy Tarreau86034312006-12-29 00:10:33 +01001313 if (*(args[1]) == 0) {
1314 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1315 return -1;
1316 }
1317 curproxy->fullconn = atol(args[1]);
1318 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001319 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1320 if (*(args[1]) == 0) {
1321 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1322 return -1;
1323 }
1324 curproxy->grace = atol(args[1]);
1325 }
1326 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1327 if (curproxy == &defproxy) {
1328 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1329 return -1;
1330 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001331 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1332 return 0;
1333
Willy Tarreaubaaee002006-06-26 02:48:02 +02001334 if (strchr(args[1], ':') == NULL) {
1335 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1336 return -1;
1337 }
1338 curproxy->dispatch_addr = *str2sa(args[1]);
1339 }
1340 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001341 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1342 return 0;
1343
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001344 memcpy(trash, "error near 'balance'", 19);
1345 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1346 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1347 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001348 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 }
1350 else if (!strcmp(args[0], "server")) { /* server address */
1351 int cur_arg;
1352 char *rport;
1353 char *raddr;
1354 short realport;
1355 int do_check;
1356
1357 if (curproxy == &defproxy) {
1358 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1359 return -1;
1360 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001361 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1362 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363
1364 if (!*args[2]) {
1365 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1366 file, linenum, args[0]);
1367 return -1;
1368 }
1369 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1370 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1371 return -1;
1372 }
1373
1374 /* the servers are linked backwards first */
1375 newsrv->next = curproxy->srv;
1376 curproxy->srv = newsrv;
1377 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001378 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001379
1380 LIST_INIT(&newsrv->pendconns);
1381 do_check = 0;
1382 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001383 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 newsrv->id = strdup(args[1]);
1385
1386 /* several ways to check the port component :
1387 * - IP => port=+0, relative
1388 * - IP: => port=+0, relative
1389 * - IP:N => port=N, absolute
1390 * - IP:+N => port=+N, relative
1391 * - IP:-N => port=-N, relative
1392 */
1393 raddr = strdup(args[2]);
1394 rport = strchr(raddr, ':');
1395 if (rport) {
1396 *rport++ = 0;
1397 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001398 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 newsrv->state |= SRV_MAPPORTS;
1400 } else {
1401 realport = 0;
1402 newsrv->state |= SRV_MAPPORTS;
1403 }
1404
1405 newsrv->addr = *str2sa(raddr);
1406 newsrv->addr.sin_port = htons(realport);
1407 free(raddr);
1408
1409 newsrv->curfd = -1; /* no health-check in progress */
1410 newsrv->inter = DEF_CHKINTR;
1411 newsrv->rise = DEF_RISETIME;
1412 newsrv->fall = DEF_FALLTIME;
1413 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001414 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001415 newsrv->maxqueue = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001416
Willy Tarreaubaaee002006-06-26 02:48:02 +02001417 cur_arg = 3;
1418 while (*args[cur_arg]) {
1419 if (!strcmp(args[cur_arg], "cookie")) {
1420 newsrv->cookie = strdup(args[cur_arg + 1]);
1421 newsrv->cklen = strlen(args[cur_arg + 1]);
1422 cur_arg += 2;
1423 }
1424 else if (!strcmp(args[cur_arg], "rise")) {
1425 newsrv->rise = atol(args[cur_arg + 1]);
1426 newsrv->health = newsrv->rise;
1427 cur_arg += 2;
1428 }
1429 else if (!strcmp(args[cur_arg], "fall")) {
1430 newsrv->fall = atol(args[cur_arg + 1]);
1431 cur_arg += 2;
1432 }
1433 else if (!strcmp(args[cur_arg], "inter")) {
1434 newsrv->inter = atol(args[cur_arg + 1]);
1435 cur_arg += 2;
1436 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001437 else if (!strcmp(args[cur_arg], "addr")) {
1438 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001439 cur_arg += 2;
1440 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001441 else if (!strcmp(args[cur_arg], "port")) {
1442 newsrv->check_port = atol(args[cur_arg + 1]);
1443 cur_arg += 2;
1444 }
1445 else if (!strcmp(args[cur_arg], "backup")) {
1446 newsrv->state |= SRV_BACKUP;
1447 cur_arg ++;
1448 }
1449 else if (!strcmp(args[cur_arg], "weight")) {
1450 int w;
1451 w = atol(args[cur_arg + 1]);
1452 if (w < 1 || w > 256) {
1453 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1454 file, linenum, newsrv->id, w);
1455 return -1;
1456 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001457 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001458 cur_arg += 2;
1459 }
1460 else if (!strcmp(args[cur_arg], "minconn")) {
1461 newsrv->minconn = atol(args[cur_arg + 1]);
1462 cur_arg += 2;
1463 }
1464 else if (!strcmp(args[cur_arg], "maxconn")) {
1465 newsrv->maxconn = atol(args[cur_arg + 1]);
1466 cur_arg += 2;
1467 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001468 else if (!strcmp(args[cur_arg], "maxqueue")) {
1469 newsrv->maxqueue = atol(args[cur_arg + 1]);
1470 cur_arg += 2;
1471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472 else if (!strcmp(args[cur_arg], "check")) {
1473 global.maxsock++;
1474 do_check = 1;
1475 cur_arg += 1;
1476 }
1477 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1478 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001479#ifdef CONFIG_HAP_CTTPROXY
1480 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1481 file, linenum, "source", "usesrc");
1482#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001483 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1484 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001485#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001486 return -1;
1487 }
1488 newsrv->state |= SRV_BIND_SRC;
1489 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1490 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001491 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001492#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001493 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001494 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1495 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001496 return -1;
1497 }
1498 if (!*args[cur_arg + 1]) {
1499 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1500 file, linenum, "usesrc");
1501 return -1;
1502 }
1503 if (!strcmp(args[cur_arg + 1], "client")) {
1504 newsrv->state |= SRV_TPROXY_CLI;
1505 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1506 newsrv->state |= SRV_TPROXY_CIP;
1507 } else {
1508 newsrv->state |= SRV_TPROXY_ADDR;
1509 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1510 }
1511 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1512 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001513#else /* no CTTPROXY support */
1514 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1515 file, linenum, "usesrc");
1516 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001517#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001518 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001519 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001520#ifdef CONFIG_HAP_CTTPROXY
1521 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1522 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1523 file, linenum, "usesrc", "source");
1524 return -1;
1525 }
1526#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527 else {
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001528 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529 file, linenum, newsrv->id);
1530 return -1;
1531 }
1532 }
1533
1534 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001535 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1536 newsrv->check_port = newsrv->check_addr.sin_port;
1537
Willy Tarreaubaaee002006-06-26 02:48:02 +02001538 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1539 newsrv->check_port = realport; /* by default */
1540 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001541 /* not yet valid, because no port was set on
1542 * the server either. We'll check if we have
1543 * a known port on the first listener.
1544 */
1545 struct listener *l;
1546 l = curproxy->listen;
1547 if (l) {
1548 int port;
1549 port = (l->addr.ss_family == AF_INET6)
1550 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1551 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1552 newsrv->check_port = port;
1553 }
1554 }
1555 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001556 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1557 file, linenum, newsrv->id);
1558 return -1;
1559 }
1560 newsrv->state |= SRV_CHECKED;
1561 }
1562
1563 if (newsrv->state & SRV_BACKUP)
1564 curproxy->srv_bck++;
1565 else
1566 curproxy->srv_act++;
1567 }
1568 else if (!strcmp(args[0], "log")) { /* syslog server address */
1569 struct sockaddr_in *sa;
1570 int facility;
1571
1572 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1573 curproxy->logfac1 = global.logfac1;
1574 curproxy->logsrv1 = global.logsrv1;
1575 curproxy->loglev1 = global.loglev1;
1576 curproxy->logfac2 = global.logfac2;
1577 curproxy->logsrv2 = global.logsrv2;
1578 curproxy->loglev2 = global.loglev2;
1579 }
1580 else if (*(args[1]) && *(args[2])) {
1581 int level;
1582
1583 facility = get_log_facility(args[2]);
1584 if (facility < 0) {
1585 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1586 exit(1);
1587 }
1588
1589 level = 7; /* max syslog level = debug */
1590 if (*(args[3])) {
1591 level = get_log_level(args[3]);
1592 if (level < 0) {
1593 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1594 exit(1);
1595 }
1596 }
1597
1598 sa = str2sa(args[1]);
1599 if (!sa->sin_port)
1600 sa->sin_port = htons(SYSLOG_PORT);
1601
1602 if (curproxy->logfac1 == -1) {
1603 curproxy->logsrv1 = *sa;
1604 curproxy->logfac1 = facility;
1605 curproxy->loglev1 = level;
1606 }
1607 else if (curproxy->logfac2 == -1) {
1608 curproxy->logsrv2 = *sa;
1609 curproxy->logfac2 = facility;
1610 curproxy->loglev2 = level;
1611 }
1612 else {
1613 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1614 return -1;
1615 }
1616 }
1617 else {
1618 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1619 file, linenum);
1620 return -1;
1621 }
1622 }
1623 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001624 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1625 return 0;
1626
Willy Tarreaubaaee002006-06-26 02:48:02 +02001627 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001628#ifdef CONFIG_HAP_CTTPROXY
1629 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1630 file, linenum, "source", "usesrc");
1631#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001632 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1633 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001634#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635 return -1;
1636 }
1637
1638 curproxy->source_addr = *str2sa(args[1]);
1639 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001640 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001641#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001642 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1643 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1644 file, linenum, "usesrc");
1645 return -1;
1646 }
1647 if (!*args[3]) {
1648 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1649 file, linenum, "usesrc");
1650 return -1;
1651 }
1652
1653 if (!strcmp(args[3], "client")) {
1654 curproxy->options |= PR_O_TPXY_CLI;
1655 } else if (!strcmp(args[3], "clientip")) {
1656 curproxy->options |= PR_O_TPXY_CIP;
1657 } else {
1658 curproxy->options |= PR_O_TPXY_ADDR;
1659 curproxy->tproxy_addr = *str2sa(args[3]);
1660 }
1661 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001662#else /* no CTTPROXY support */
1663 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1664 file, linenum, "usesrc");
1665 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001666#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001668 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001669#ifdef CONFIG_HAP_CTTPROXY
1670 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1671 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1672 file, linenum, "usesrc", "source");
1673 return -1;
1674 }
1675#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1677 regex_t *preg;
1678 if (curproxy == &defproxy) {
1679 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1680 return -1;
1681 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001682 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1683 return 0;
1684
Willy Tarreaubaaee002006-06-26 02:48:02 +02001685 if (*(args[1]) == 0 || *(args[2]) == 0) {
1686 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1687 file, linenum, args[0]);
1688 return -1;
1689 }
1690
1691 preg = calloc(1, sizeof(regex_t));
1692 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1693 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1694 return -1;
1695 }
1696
1697 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1698 if (err) {
1699 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1700 file, linenum, *err);
1701 return -1;
1702 }
1703 }
1704 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1705 regex_t *preg;
1706 if (curproxy == &defproxy) {
1707 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1708 return -1;
1709 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001710 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1711 return 0;
1712
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 if (*(args[1]) == 0) {
1714 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1715 return -1;
1716 }
1717
1718 preg = calloc(1, sizeof(regex_t));
1719 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1720 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1721 return -1;
1722 }
1723
1724 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1725 }
1726 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1727 regex_t *preg;
1728 if (curproxy == &defproxy) {
1729 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1730 return -1;
1731 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001732 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1733 return 0;
1734
Willy Tarreaubaaee002006-06-26 02:48:02 +02001735 if (*(args[1]) == 0) {
1736 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1737 return -1;
1738 }
1739
1740 preg = calloc(1, sizeof(regex_t));
1741 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1742 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1743 return -1;
1744 }
1745
1746 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1747 }
1748 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1749 regex_t *preg;
1750 if (curproxy == &defproxy) {
1751 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1752 return -1;
1753 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001754 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1755 return 0;
1756
Willy Tarreaubaaee002006-06-26 02:48:02 +02001757 if (*(args[1]) == 0) {
1758 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1759 return -1;
1760 }
1761
1762 preg = calloc(1, sizeof(regex_t));
1763 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1764 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1765 return -1;
1766 }
1767
1768 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1769 }
1770 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1771 regex_t *preg;
1772 if (curproxy == &defproxy) {
1773 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1774 return -1;
1775 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001776 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1777 return 0;
1778
Willy Tarreaubaaee002006-06-26 02:48:02 +02001779 if (*(args[1]) == 0) {
1780 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1781 return -1;
1782 }
1783
1784 preg = calloc(1, sizeof(regex_t));
1785 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1786 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1787 return -1;
1788 }
1789
1790 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1791 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001792 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1793 regex_t *preg;
1794 if (curproxy == &defproxy) {
1795 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1796 return -1;
1797 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001798 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1799 return 0;
1800
Willy Tarreaub8750a82006-09-03 09:56:00 +02001801 if (*(args[1]) == 0) {
1802 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1803 return -1;
1804 }
1805
1806 preg = calloc(1, sizeof(regex_t));
1807 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1808 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1809 return -1;
1810 }
1811
1812 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1813 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001814 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1815 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001816 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001817 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1818 return -1;
1819 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001820 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1821 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001822
Willy Tarreau977b8e42006-12-29 14:19:17 +01001823 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001824 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1825 file, linenum, args[0]);
1826 return -1;
1827 }
1828
1829 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001830 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001831 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1832 }
1833
1834 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1835 }
1836 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1837 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001838 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001839 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1840 return -1;
1841 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001842 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1843 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001844
Willy Tarreau977b8e42006-12-29 14:19:17 +01001845 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001846 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1847 file, linenum, args[0]);
1848 return -1;
1849 }
1850
1851 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001852 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001853 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1854 }
1855
1856 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1857 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001858 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1859 regex_t *preg;
1860 if (curproxy == &defproxy) {
1861 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1862 return -1;
1863 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001864 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1865 return 0;
1866
Willy Tarreaubaaee002006-06-26 02:48:02 +02001867 if (*(args[1]) == 0 || *(args[2]) == 0) {
1868 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1869 file, linenum, args[0]);
1870 return -1;
1871 }
1872
1873 preg = calloc(1, sizeof(regex_t));
1874 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1875 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1876 return -1;
1877 }
1878
1879 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1880 if (err) {
1881 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1882 file, linenum, *err);
1883 return -1;
1884 }
1885 }
1886 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1887 regex_t *preg;
1888 if (curproxy == &defproxy) {
1889 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1890 return -1;
1891 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001892 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1893 return 0;
1894
Willy Tarreaubaaee002006-06-26 02:48:02 +02001895 if (*(args[1]) == 0) {
1896 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1897 return -1;
1898 }
1899
1900 preg = calloc(1, sizeof(regex_t));
1901 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1902 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1903 return -1;
1904 }
1905
1906 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1907 }
1908 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1909 regex_t *preg;
1910 if (curproxy == &defproxy) {
1911 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1912 return -1;
1913 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001914 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1915 return 0;
1916
Willy Tarreaubaaee002006-06-26 02:48:02 +02001917 if (*(args[1]) == 0) {
1918 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1919 return -1;
1920 }
1921
1922 preg = calloc(1, sizeof(regex_t));
1923 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1924 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1925 return -1;
1926 }
1927
1928 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1929 }
1930 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1931 regex_t *preg;
1932 if (curproxy == &defproxy) {
1933 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1934 return -1;
1935 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001936 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1937 return 0;
1938
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939 if (*(args[1]) == 0) {
1940 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1941 return -1;
1942 }
1943
1944 preg = calloc(1, sizeof(regex_t));
1945 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1946 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1947 return -1;
1948 }
1949
1950 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1951 }
1952 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1953 regex_t *preg;
1954 if (curproxy == &defproxy) {
1955 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1956 return -1;
1957 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001958 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1959 return 0;
1960
Willy Tarreaubaaee002006-06-26 02:48:02 +02001961 if (*(args[1]) == 0) {
1962 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1963 return -1;
1964 }
1965
1966 preg = calloc(1, sizeof(regex_t));
1967 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1968 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1969 return -1;
1970 }
1971
1972 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1973 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001974 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1975 regex_t *preg;
1976 if (curproxy == &defproxy) {
1977 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1978 return -1;
1979 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001980 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1981 return 0;
1982
Willy Tarreaub8750a82006-09-03 09:56:00 +02001983 if (*(args[1]) == 0) {
1984 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1985 return -1;
1986 }
1987
1988 preg = calloc(1, sizeof(regex_t));
1989 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1990 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1991 return -1;
1992 }
1993
1994 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1995 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001996 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1997 if (curproxy == &defproxy) {
1998 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1999 return -1;
2000 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002001 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2002 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002003
2004 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2005 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2006 return 0;
2007 }
2008
2009 if (*(args[1]) == 0) {
2010 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2011 return -1;
2012 }
2013
2014 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2015 }
2016 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2017 regex_t *preg;
2018
2019 if (*(args[1]) == 0 || *(args[2]) == 0) {
2020 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2021 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;
2026
Willy Tarreaubaaee002006-06-26 02:48:02 +02002027 preg = calloc(1, sizeof(regex_t));
2028 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2029 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2030 return -1;
2031 }
2032
2033 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2034 if (err) {
2035 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2036 file, linenum, *err);
2037 return -1;
2038 }
2039 }
2040 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2041 regex_t *preg;
2042 if (curproxy == &defproxy) {
2043 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2044 return -1;
2045 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002046 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2047 return 0;
2048
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049 if (*(args[1]) == 0) {
2050 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2051 return -1;
2052 }
2053
2054 preg = calloc(1, sizeof(regex_t));
2055 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2056 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2057 return -1;
2058 }
2059
2060 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2061 if (err) {
2062 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2063 file, linenum, *err);
2064 return -1;
2065 }
2066 }
2067 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2068 regex_t *preg;
2069 if (curproxy == &defproxy) {
2070 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2071 return -1;
2072 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002073 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2074 return 0;
2075
Willy Tarreaubaaee002006-06-26 02:48:02 +02002076 if (*(args[1]) == 0) {
2077 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2078 return -1;
2079 }
2080
2081 preg = calloc(1, sizeof(regex_t));
2082 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2083 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2084 return -1;
2085 }
2086
2087 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2088 if (err) {
2089 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2090 file, linenum, *err);
2091 return -1;
2092 }
2093 }
2094 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2095 regex_t *preg;
2096 if (curproxy == &defproxy) {
2097 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2098 return -1;
2099 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002100 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2101 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002102
2103 if (*(args[1]) == 0 || *(args[2]) == 0) {
2104 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2105 file, linenum, args[0]);
2106 return -1;
2107 }
2108
2109 preg = calloc(1, sizeof(regex_t));
2110 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2111 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2112 return -1;
2113 }
2114
2115 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2116 if (err) {
2117 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2118 file, linenum, *err);
2119 return -1;
2120 }
2121 }
2122 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2123 regex_t *preg;
2124 if (curproxy == &defproxy) {
2125 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2126 return -1;
2127 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002128 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2129 return 0;
2130
Willy Tarreaubaaee002006-06-26 02:48:02 +02002131 if (*(args[1]) == 0) {
2132 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2133 return -1;
2134 }
2135
2136 preg = calloc(1, sizeof(regex_t));
2137 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2138 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2139 return -1;
2140 }
2141
2142 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2143 if (err) {
2144 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2145 file, linenum, *err);
2146 return -1;
2147 }
2148 }
2149 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2150 regex_t *preg;
2151 if (curproxy == &defproxy) {
2152 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2153 return -1;
2154 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002155 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2156 return 0;
2157
Willy Tarreaubaaee002006-06-26 02:48:02 +02002158 if (*(args[1]) == 0) {
2159 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2160 return -1;
2161 }
2162
2163 preg = calloc(1, sizeof(regex_t));
2164 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2165 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2166 return -1;
2167 }
2168
2169 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2170 if (err) {
2171 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2172 file, linenum, *err);
2173 return -1;
2174 }
2175 }
2176 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2177 if (curproxy == &defproxy) {
2178 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2179 return -1;
2180 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002181 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2182 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002183
2184 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2185 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2186 return 0;
2187 }
2188
2189 if (*(args[1]) == 0) {
2190 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2191 return -1;
2192 }
2193
2194 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2195 }
2196 else if (!strcmp(args[0], "errorloc") ||
2197 !strcmp(args[0], "errorloc302") ||
2198 !strcmp(args[0], "errorloc303")) { /* error location */
2199 int errnum, errlen;
2200 char *err;
2201
Willy Tarreau977b8e42006-12-29 14:19:17 +01002202 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2203 return 0;
2204
Willy Tarreaubaaee002006-06-26 02:48:02 +02002205 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002206 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002207 return -1;
2208 }
2209
2210 errnum = atol(args[1]);
2211 if (!strcmp(args[0], "errorloc303")) {
2212 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2213 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2214 } else {
2215 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2216 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2217 }
2218
Willy Tarreau0f772532006-12-23 20:51:41 +01002219 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2220 if (http_err_codes[rc] == errnum) {
2221 if (curproxy->errmsg[rc].str)
2222 free(curproxy->errmsg[rc].str);
2223 curproxy->errmsg[rc].str = err;
2224 curproxy->errmsg[rc].len = errlen;
2225 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002228
2229 if (rc >= HTTP_ERR_SIZE) {
2230 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2231 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002232 free(err);
2233 }
2234 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002235 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2236 int errnum, errlen, fd;
2237 char *err;
2238 struct stat stat;
2239
2240 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2241 return 0;
2242
2243 if (*(args[2]) == 0) {
2244 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2245 return -1;
2246 }
2247
2248 fd = open(args[2], O_RDONLY);
2249 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2250 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2251 file, linenum, args[2], args[1]);
2252 if (fd >= 0)
2253 close(fd);
2254 return -1;
2255 }
2256
2257 if (stat.st_size <= BUFSIZE) {
2258 errlen = stat.st_size;
2259 } else {
2260 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2261 file, linenum, args[2], BUFSIZE);
2262 errlen = BUFSIZE;
2263 }
2264
2265 err = malloc(errlen); /* malloc() must succeed during parsing */
2266 errnum = read(fd, err, errlen);
2267 if (errnum != errlen) {
2268 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2269 file, linenum, args[2], args[1]);
2270 close(fd);
2271 free(err);
2272 return -1;
2273 }
2274 close(fd);
2275
2276 errnum = atol(args[1]);
2277 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2278 if (http_err_codes[rc] == errnum) {
2279 if (curproxy->errmsg[rc].str)
2280 free(curproxy->errmsg[rc].str);
2281 curproxy->errmsg[rc].str = err;
2282 curproxy->errmsg[rc].len = errlen;
2283 break;
2284 }
2285 }
2286
2287 if (rc >= HTTP_ERR_SIZE) {
2288 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2289 file, linenum, errnum);
2290 free(err);
2291 }
2292 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002293 else {
2294 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2295 return -1;
2296 }
2297 return 0;
2298}
2299
2300
2301/*
2302 * This function reads and parses the configuration file given in the argument.
2303 * returns 0 if OK, -1 if error.
2304 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002305int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002307 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002308 FILE *f;
2309 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002310 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002311 int confsect = CFG_NONE;
2312
2313 struct proxy *curproxy = NULL;
2314 struct server *newsrv = NULL;
2315
2316 if ((f=fopen(file,"r")) == NULL)
2317 return -1;
2318
2319 init_default_instance();
2320
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002321 while (fgets(thisline, sizeof(thisline), f) != NULL) {
2322 int arg;
2323 char *end;
2324 char *args[MAX_LINE_ARGS + 1];
2325 char *line = thisline;
2326
Willy Tarreaubaaee002006-06-26 02:48:02 +02002327 linenum++;
2328
2329 end = line + strlen(line);
2330
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002331 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2332 /* Check if we reached the limit and the last char is not \n.
2333 * Watch out for the last line without the terminating '\n'!
2334 */
2335 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2336 file, linenum, sizeof(thisline)-1);
2337 return -1;
2338 }
2339
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002341 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 line++;
2343
2344 arg = 0;
2345 args[arg] = line;
2346
2347 while (*line && arg < MAX_LINE_ARGS) {
2348 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2349 * C equivalent value. Other combinations left unchanged (eg: \1).
2350 */
2351 if (*line == '\\') {
2352 int skip = 0;
2353 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2354 *line = line[1];
2355 skip = 1;
2356 }
2357 else if (line[1] == 'r') {
2358 *line = '\r';
2359 skip = 1;
2360 }
2361 else if (line[1] == 'n') {
2362 *line = '\n';
2363 skip = 1;
2364 }
2365 else if (line[1] == 't') {
2366 *line = '\t';
2367 skip = 1;
2368 }
2369 else if (line[1] == 'x') {
2370 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2371 unsigned char hex1, hex2;
2372 hex1 = toupper(line[2]) - '0';
2373 hex2 = toupper(line[3]) - '0';
2374 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2375 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2376 *line = (hex1<<4) + hex2;
2377 skip = 3;
2378 }
2379 else {
2380 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2381 return -1;
2382 }
2383 }
2384 if (skip) {
2385 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2386 end -= skip;
2387 }
2388 line++;
2389 }
2390 else if (*line == '#' || *line == '\n' || *line == '\r') {
2391 /* end of string, end of loop */
2392 *line = 0;
2393 break;
2394 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002395 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002397 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002398 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 line++;
2400 args[++arg] = line;
2401 }
2402 else {
2403 line++;
2404 }
2405 }
2406
2407 /* empty line */
2408 if (!**args)
2409 continue;
2410
Willy Tarreau540abe42007-05-02 20:50:16 +02002411 /* zero out remaining args and ensure that at least one entry
2412 * is zeroed out.
2413 */
2414 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 args[arg] = line;
2416 }
2417
Willy Tarreau977b8e42006-12-29 14:19:17 +01002418 if (!strcmp(args[0], "listen") ||
2419 !strcmp(args[0], "frontend") ||
2420 !strcmp(args[0], "backend") ||
2421 !strcmp(args[0], "ruleset") ||
2422 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423 confsect = CFG_LISTEN;
2424 else if (!strcmp(args[0], "global")) /* global config */
2425 confsect = CFG_GLOBAL;
2426 /* else it's a section keyword */
2427
2428 switch (confsect) {
2429 case CFG_LISTEN:
2430 if (cfg_parse_listen(file, linenum, args) < 0)
2431 return -1;
2432 break;
2433 case CFG_GLOBAL:
2434 if (cfg_parse_global(file, linenum, args) < 0)
2435 return -1;
2436 break;
2437 default:
2438 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2439 return -1;
2440 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 }
2442 fclose(f);
2443
2444 /*
2445 * Now, check for the integrity of all that we have collected.
2446 */
2447
2448 /* will be needed further to delay some tasks */
2449 tv_now(&now);
2450
2451 if ((curproxy = proxy) == NULL) {
2452 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2453 file);
2454 return -1;
2455 }
2456
2457 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002458 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002459 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002460
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 if (curproxy->state == PR_STSTOPPED) {
2462 curproxy = curproxy->next;
2463 continue;
2464 }
2465
Willy Tarreau977b8e42006-12-29 14:19:17 +01002466 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2467 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 +01002468 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002469 cfgerr++;
2470 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002471 else if (curproxy->cap & PR_CAP_BE &&
2472 ((curproxy->mode != PR_MODE_HEALTH) &&
2473 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
2474 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2475 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 +01002476 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 cfgerr++;
2478 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002479
2480 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002482 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002483 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002484 cfgerr++;
2485 }
2486#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2487 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002488 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002489 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002490 cfgerr++;
2491 }
2492#endif
2493 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002494 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002495 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 }
2497 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002498
2499 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002501 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002502 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002503 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002505 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002506 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002507 }
2508 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002509 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002510 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002511 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002512 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002513 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002514 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002515 }
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002516 if (curproxy->options & PR_O_BALANCE_L7) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002517 curproxy->options &= ~PR_O_BALANCE;
2518 curproxy->options |= PR_O_BALANCE_RR;
2519
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002520 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002521 file, proxy_type_str(curproxy), curproxy->id);
2522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002524
2525 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2526 if ((newsrv = curproxy->srv) != NULL) {
2527 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2528 file, proxy_type_str(curproxy), curproxy->id);
2529 }
2530 }
2531
2532 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2534 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2535 file, curproxy->id);
2536 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002537 }
2538 }
2539
2540 /* if a default backend was specified, let's find it */
2541 if (curproxy->defbe.name) {
2542 struct proxy *target;
2543
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002544 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2545 if (!target) {
2546 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2547 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002548 cfgerr++;
2549 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002550 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2551 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002552 } else {
2553 free(curproxy->defbe.name);
2554 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 }
2556 }
2557
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002558 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002559 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2560 /* map jump target for ACT_SETBE in req_rep chain */
2561 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002562 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002563 struct proxy *target;
2564
Willy Tarreaua496b602006-12-17 23:15:24 +01002565 if (exp->action != ACT_SETBE)
2566 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002567
2568 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2569 if (!target) {
2570 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2571 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002572 cfgerr++;
2573 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002574 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2575 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002576 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002577 } else {
2578 free((void *)exp->replace);
2579 exp->replace = (const char *)target;
2580 }
2581 }
2582 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002583
2584 /* find the target proxy for 'use_backend' rules */
2585 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002586 struct proxy *target;
2587
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002588 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002589
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002590 if (!target) {
2591 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2592 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002593 cfgerr++;
2594 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002595 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2596 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002597 cfgerr++;
2598 } else {
2599 free((void *)rule->be.name);
2600 rule->be.backend = target;
2601 }
2602 }
2603
Willy Tarreau2738a142006-07-08 17:28:09 +02002604 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002605 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2606 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2607 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002608 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002609 " | While not properly invalid, you will certainly encounter various problems\n"
2610 " | with such a configuration. To fix this, please ensure that all following\n"
2611 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002612 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002613 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002614
2615 if (curproxy->options & PR_O_SSL3_CHK) {
2616 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2617 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2618 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2619 }
2620
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002621 /* The small pools required for the capture lists */
2622 if (curproxy->nb_req_cap)
2623 curproxy->req_cap_pool = create_pool("ptrcap",
2624 curproxy->nb_req_cap * sizeof(char *),
2625 MEM_F_SHARED);
2626 if (curproxy->nb_rsp_cap)
2627 curproxy->rsp_cap_pool = create_pool("ptrcap",
2628 curproxy->nb_rsp_cap * sizeof(char *),
2629 MEM_F_SHARED);
2630
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002631 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2632 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2633 MEM_F_SHARED);
2634
Willy Tarreau86034312006-12-29 00:10:33 +01002635 /* for backwards compatibility with "listen" instances, if
2636 * fullconn is not set but maxconn is set, then maxconn
2637 * is used.
2638 */
2639 if (!curproxy->fullconn)
2640 curproxy->fullconn = curproxy->maxconn;
2641
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642 /* first, we will invert the servers list order */
2643 newsrv = NULL;
2644 while (curproxy->srv) {
2645 struct server *next;
2646
2647 next = curproxy->srv->next;
2648 curproxy->srv->next = newsrv;
2649 newsrv = curproxy->srv;
2650 if (!next)
2651 break;
2652 curproxy->srv = next;
2653 }
2654
Willy Tarreau20697042007-11-15 23:26:18 +01002655 curproxy->lbprm.wmult = 1; /* default weight multiplier */
2656
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657 /* now, newsrv == curproxy->srv */
2658 if (newsrv) {
2659 struct server *srv;
2660 int pgcd;
2661 int act, bck;
2662
2663 /* We will factor the weights to reduce the table,
2664 * using Euclide's largest common divisor algorithm
2665 */
Willy Tarreau417fae02007-03-25 21:16:40 +02002666 pgcd = newsrv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2668 int t, w;
2669
Willy Tarreau417fae02007-03-25 21:16:40 +02002670 w = srv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002671 while (w) {
2672 t = pgcd % w;
2673 pgcd = w;
2674 w = t;
2675 }
2676 }
2677
Willy Tarreau20697042007-11-15 23:26:18 +01002678 /* It is sometimes useful to know what factor to apply
2679 * to the backend's effective weight to know its real
2680 * weight.
2681 */
2682 curproxy->lbprm.wmult = pgcd;
2683
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 act = bck = 0;
2685 for (srv = newsrv; srv; srv = srv->next) {
Willy Tarreau417fae02007-03-25 21:16:40 +02002686 srv->eweight = srv->uweight / pgcd;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 if (srv->state & SRV_BACKUP)
Willy Tarreau417fae02007-03-25 21:16:40 +02002688 bck += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 else
Willy Tarreau417fae02007-03-25 21:16:40 +02002690 act += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 }
2692
2693 /* this is the largest map we will ever need for this servers list */
2694 if (act < bck)
2695 act = bck;
2696
Willy Tarreau20697042007-11-15 23:26:18 +01002697 curproxy->lbprm.map.srv = (struct server **)calloc(act, sizeof(struct server *));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 /* recounts servers and their weights */
Willy Tarreau20697042007-11-15 23:26:18 +01002699 curproxy->lbprm.map.state = PR_MAP_RECALC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 recount_servers(curproxy);
2701 recalc_server_map(curproxy);
2702 }
2703
2704 if (curproxy->options & PR_O_LOGASAP)
2705 curproxy->to_log &= ~LW_BYTES;
2706
Willy Tarreaubaaee002006-06-26 02:48:02 +02002707 /*
2708 * If this server supports a maxconn parameter, it needs a dedicated
2709 * tasks to fill the emptied slots when a connection leaves.
2710 */
2711 newsrv = curproxy->srv;
2712 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002713 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002714 /* Only 'minconn' was specified, or it was higher than or equal
2715 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2716 * this will avoid further useless expensive computations.
2717 */
2718 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002719 } else if (newsrv->maxconn && !newsrv->minconn) {
2720 /* minconn was not specified, so we set it to maxconn */
2721 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002722 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2723 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002724 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002725 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002726 }
2727
2728 if (newsrv->maxconn > 0) {
2729 struct task *t;
2730
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002731 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2733 return -1;
2734 }
2735
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002736 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002737 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002738 t->state = TASK_IDLE;
2739 t->process = process_srv_queue;
2740 t->context = newsrv;
2741 newsrv->queue_mgt = t;
2742
2743 /* never run it unless specifically woken up */
2744 tv_eternity(&t->expire);
2745 task_queue(t);
2746 }
2747 newsrv = newsrv->next;
2748 }
2749
Willy Tarreaue6b98942007-10-29 01:09:36 +01002750 /* adjust this proxy's listeners */
2751 listener = curproxy->listen;
2752 while (listener) {
2753 if (curproxy->options & PR_O_TCP_NOLING)
2754 listener->options |= LI_O_NOLINGER;
2755 listener->maxconn = curproxy->maxconn;
2756 listener->timeout = &curproxy->clitimeout;
2757 listener->accept = event_accept;
2758 listener->private = curproxy;
2759
2760 listener = listener->next;
2761 }
2762
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 curproxy = curproxy->next;
2764 }
2765 if (cfgerr > 0) {
2766 Alert("Errors found in configuration file, aborting.\n");
2767 return -1;
2768 }
2769 else
2770 return 0;
2771}
2772
2773
2774
2775/*
2776 * Local variables:
2777 * c-indent-level: 8
2778 * c-basic-offset: 8
2779 * End:
2780 */