blob: e347cff8fbdfce70ba98d3297d749e58e71673f9 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau0b4ed902007-03-26 00:18:40 +02004 * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
27#include <common/config.h>
28#include <common/memory.h>
29#include <common/standard.h>
30#include <common/time.h>
31#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020032
33#include <types/capture.h>
34#include <types/global.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010035#include <types/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <types/polling.h>
37#include <types/proxy.h>
38#include <types/queue.h>
39
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010045#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020046#include <proto/log.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010047#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <proto/server.h>
49#include <proto/task.h>
50
51
Willy Tarreauf3c69202006-07-09 16:42:34 +020052/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
53 * ssl-hello-chk option to ensure that the remote server speaks SSL.
54 *
55 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
56 */
57const char sslv3_client_hello_pkt[] = {
58 "\x16" /* ContentType : 0x16 = Hanshake */
59 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
60 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
61 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
62 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
63 "\x03\x00" /* Hello Version : 0x0300 = v3 */
64 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
65 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
66 "\x00" /* Session ID length : empty (no session ID) */
67 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
68 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
69 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
70 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
71 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
72 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
73 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
74 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
75 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
76 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
77 "\x00\x38" "\x00\x39" "\x00\x3A"
78 "\x01" /* Compression Length : 0x01 = 1 byte for types */
79 "\x00" /* Compression Type : 0x00 = NULL compression */
80};
81
Willy Tarreau13943ab2006-12-31 00:24:10 +010082/* some of the most common options which are also the easiest to handle */
83static const struct {
84 const char *name;
85 unsigned int val;
86 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010087 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010088} cfg_opts[] =
89{
90#ifdef TPROXY
91 { "transparent", PR_O_TRANSP, PR_CAP_FE },
92#endif
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
94 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010095 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
Alexandre Cassen87ea5482007-10-11 20:48:58 +020096 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010097 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
98 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
99 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
100 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
101 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
102 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
103 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
104 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
105 { "forceclose", PR_O_FORCE_CLO | PR_O_HTTP_CLOSE, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100106#ifdef CONFIG_HAP_TCPSPLICE
107 { "tcpsplice", PR_O_TCPSPLICE , PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
108#endif
109
Willy Tarreau13943ab2006-12-31 00:24:10 +0100110 { NULL, 0, 0 }
111};
112
Willy Tarreaubaaee002006-06-26 02:48:02 +0200113
114static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
115int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
116int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
117
118/*
119 * converts <str> to a list of listeners which are dynamically allocated.
120 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
121 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
122 * - <port> is a numerical port from 1 to 65535 ;
123 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
124 * This can be repeated as many times as necessary, separated by a coma.
125 * The <tail> argument is a pointer to a current list which should be appended
126 * to the tail of the new list. The pointer to the new list is returned.
127 */
128static struct listener *str2listener(char *str, struct listener *tail)
129{
130 struct listener *l;
131 char *c, *next, *range, *dupstr;
132 int port, end;
133
134 next = dupstr = strdup(str);
135
136 while (next && *next) {
137 struct sockaddr_storage ss;
138
139 str = next;
140 /* 1) look for the end of the first address */
141 if ((next = strrchr(str, ',')) != NULL) {
142 *next++ = 0;
143 }
144
145 /* 2) look for the addr/port delimiter, it's the last colon. */
146 if ((range = strrchr(str, ':')) == NULL) {
147 Alert("Missing port number: '%s'\n", str);
148 goto fail;
149 }
150
151 *range++ = 0;
152
153 if (strrchr(str, ':') != NULL) {
154 /* IPv6 address contains ':' */
155 memset(&ss, 0, sizeof(ss));
156 ss.ss_family = AF_INET6;
157
158 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
159 Alert("Invalid server address: '%s'\n", str);
160 goto fail;
161 }
162 }
163 else {
164 memset(&ss, 0, sizeof(ss));
165 ss.ss_family = AF_INET;
166
167 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
168 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
169 }
170 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
171 struct hostent *he;
172
173 if ((he = gethostbyname(str)) == NULL) {
174 Alert("Invalid server name: '%s'\n", str);
175 goto fail;
176 }
177 else
178 ((struct sockaddr_in *)&ss)->sin_addr =
179 *(struct in_addr *) *(he->h_addr_list);
180 }
181 }
182
183 /* 3) look for the port-end delimiter */
184 if ((c = strchr(range, '-')) != NULL) {
185 *c++ = 0;
186 end = atol(c);
187 }
188 else {
189 end = atol(range);
190 }
191
192 port = atol(range);
193
194 if (port < 1 || port > 65535) {
195 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
196 goto fail;
197 }
198
199 if (end < 1 || end > 65535) {
200 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
201 goto fail;
202 }
203
204 for (; port <= end; port++) {
205 l = (struct listener *)calloc(1, sizeof(struct listener));
206 l->next = tail;
207 tail = l;
208
209 l->fd = -1;
210 l->addr = ss;
211 if (ss.ss_family == AF_INET6)
212 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
213 else
214 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
215
216 } /* end for(port) */
217 } /* end while(next) */
218 free(dupstr);
219 return tail;
220 fail:
221 free(dupstr);
222 return NULL;
223}
224
Willy Tarreau977b8e42006-12-29 14:19:17 +0100225/*
226 * Sends a warning if proxy <proxy> does not have at least one of the
227 * capabilities in <cap>. An optionnal <hint> may be added at the end
228 * of the warning to help the user. Returns 1 if a warning was emitted
229 * or 0 if the condition is valid.
230 */
231int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
232{
233 char *msg;
234
235 switch (cap) {
236 case PR_CAP_BE: msg = "no backend"; break;
237 case PR_CAP_FE: msg = "no frontend"; break;
238 case PR_CAP_RS: msg = "no ruleset"; break;
239 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
240 default: msg = "not enough"; break;
241 }
242
243 if (!(proxy->cap & cap)) {
244 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100245 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100246 return 1;
247 }
248 return 0;
249}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
251/*
252 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
253 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200254int cfg_parse_global(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255{
256
257 if (!strcmp(args[0], "global")) { /* new section */
258 /* no option, nothing special to do */
259 return 0;
260 }
261 else if (!strcmp(args[0], "daemon")) {
262 global.mode |= MODE_DAEMON;
263 }
264 else if (!strcmp(args[0], "debug")) {
265 global.mode |= MODE_DEBUG;
266 }
267 else if (!strcmp(args[0], "noepoll")) {
268 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
269 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200270 else if (!strcmp(args[0], "nosepoll")) {
271 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
272 }
273 else if (!strcmp(args[0], "nokqueue")) {
274 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200276 else if (!strcmp(args[0], "nopoll")) {
277 cfg_polling_mechanism &= ~POLL_USE_POLL;
278 }
279 else if (!strcmp(args[0], "quiet")) {
280 global.mode |= MODE_QUIET;
281 }
282 else if (!strcmp(args[0], "stats")) {
Willy Tarreaufbee7132007-10-18 13:53:22 +0200283 memcpy(trash, "error near 'stats'", 19);
284 if (stats_parse_global((const char **)args + 1, trash, sizeof(trash)) < 0) {
285 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
286 return -1;
287 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200289 else if (!strcmp(args[0], "tune.maxpollevents")) {
290 if (global.tune.maxpollevents != 0) {
291 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
292 return 0;
293 }
294 if (*(args[1]) == 0) {
295 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
296 return -1;
297 }
298 global.tune.maxpollevents = atol(args[1]);
299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300 else if (!strcmp(args[0], "uid")) {
301 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200302 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200303 return 0;
304 }
305 if (*(args[1]) == 0) {
306 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
307 return -1;
308 }
309 global.uid = atol(args[1]);
310 }
311 else if (!strcmp(args[0], "gid")) {
312 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200313 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200314 return 0;
315 }
316 if (*(args[1]) == 0) {
317 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
318 return -1;
319 }
320 global.gid = atol(args[1]);
321 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200322 /* user/group name handling */
323 else if (!strcmp(args[0], "user")) {
324 struct passwd *ha_user;
325 if (global.uid != 0) {
326 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
327 return 0;
328 }
329 errno = 0;
330 ha_user = getpwnam(args[1]);
331 if (ha_user != NULL) {
332 global.uid = (int)ha_user->pw_uid;
333 }
334 else {
335 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
336 exit(1);
337 }
338 }
339 else if (!strcmp(args[0], "group")) {
340 struct group *ha_group;
341 if (global.gid != 0) {
342 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
343 return 0;
344 }
345 errno = 0;
346 ha_group = getgrnam(args[1]);
347 if (ha_group != NULL) {
348 global.gid = (int)ha_group->gr_gid;
349 }
350 else {
351 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
352 exit(1);
353 }
354 }
355 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200356 else if (!strcmp(args[0], "nbproc")) {
357 if (global.nbproc != 0) {
358 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
359 return 0;
360 }
361 if (*(args[1]) == 0) {
362 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
363 return -1;
364 }
365 global.nbproc = atol(args[1]);
366 }
367 else if (!strcmp(args[0], "maxconn")) {
368 if (global.maxconn != 0) {
369 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
370 return 0;
371 }
372 if (*(args[1]) == 0) {
373 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
374 return -1;
375 }
376 global.maxconn = atol(args[1]);
377#ifdef SYSTEM_MAXCONN
378 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
379 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
380 global.maxconn = DEFAULT_MAXCONN;
381 }
382#endif /* SYSTEM_MAXCONN */
383 }
384 else if (!strcmp(args[0], "ulimit-n")) {
385 if (global.rlimit_nofile != 0) {
386 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
387 return 0;
388 }
389 if (*(args[1]) == 0) {
390 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
391 return -1;
392 }
393 global.rlimit_nofile = atol(args[1]);
394 }
395 else if (!strcmp(args[0], "chroot")) {
396 if (global.chroot != NULL) {
397 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
398 return 0;
399 }
400 if (*(args[1]) == 0) {
401 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
402 return -1;
403 }
404 global.chroot = strdup(args[1]);
405 }
406 else if (!strcmp(args[0], "pidfile")) {
407 if (global.pidfile != NULL) {
408 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
409 return 0;
410 }
411 if (*(args[1]) == 0) {
412 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
413 return -1;
414 }
415 global.pidfile = strdup(args[1]);
416 }
417 else if (!strcmp(args[0], "log")) { /* syslog server address */
418 struct sockaddr_in *sa;
419 int facility, level;
420
421 if (*(args[1]) == 0 || *(args[2]) == 0) {
422 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
423 return -1;
424 }
425
426 facility = get_log_facility(args[2]);
427 if (facility < 0) {
428 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
429 exit(1);
430 }
431
432 level = 7; /* max syslog level = debug */
433 if (*(args[3])) {
434 level = get_log_level(args[3]);
435 if (level < 0) {
436 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
437 exit(1);
438 }
439 }
440
441 sa = str2sa(args[1]);
442 if (!sa->sin_port)
443 sa->sin_port = htons(SYSLOG_PORT);
444
445 if (global.logfac1 == -1) {
446 global.logsrv1 = *sa;
447 global.logfac1 = facility;
448 global.loglev1 = level;
449 }
450 else if (global.logfac2 == -1) {
451 global.logsrv2 = *sa;
452 global.logfac2 = facility;
453 global.loglev2 = level;
454 }
455 else {
456 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
457 return -1;
458 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200459 }
460 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
461 if (global.spread_checks != 0) {
462 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
463 return 0;
464 }
465 if (*(args[1]) == 0) {
466 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
467 return -1;
468 }
469 global.spread_checks = atol(args[1]);
470 if (global.spread_checks < 0 || global.spread_checks > 50) {
471 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
472 return -1;
473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200474 }
475 else {
476 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
477 return -1;
478 }
479 return 0;
480}
481
482
483static void init_default_instance()
484{
485 memset(&defproxy, 0, sizeof(defproxy));
486 defproxy.mode = PR_MODE_TCP;
487 defproxy.state = PR_STNEW;
488 defproxy.maxconn = cfg_maxpconn;
489 defproxy.conn_retries = CONN_RETRIES;
490 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaufdd0f552007-09-17 11:12:40 +0200491 tv_eternity(&defproxy.clitimeout);
492 tv_eternity(&defproxy.contimeout);
493 tv_eternity(&defproxy.srvtimeout);
494 tv_eternity(&defproxy.appsession_timeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200495}
496
497/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100498 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
499 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200500 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200501int cfg_parse_listen(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200502{
503 static struct proxy *curproxy = NULL;
504 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200505 const char *err;
Willy Tarreauee991362007-05-14 14:37:50 +0200506 int rc, val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200507
Willy Tarreau977b8e42006-12-29 14:19:17 +0100508 if (!strcmp(args[0], "listen"))
509 rc = PR_CAP_LISTEN;
510 else if (!strcmp(args[0], "frontend"))
511 rc = PR_CAP_FE | PR_CAP_RS;
512 else if (!strcmp(args[0], "backend"))
513 rc = PR_CAP_BE | PR_CAP_RS;
514 else if (!strcmp(args[0], "ruleset"))
515 rc = PR_CAP_RS;
516 else
517 rc = PR_CAP_NONE;
518
519 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520 if (!*args[1]) {
521 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
522 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
523 file, linenum, args[0]);
524 return -1;
525 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200526
527 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
528 /*
529 * If there are two proxies with the same name only following
530 * combinations are allowed:
531 *
532 * listen backend frontend ruleset
533 * listen - - - -
534 * backend - - OK -
535 * frontend - OK - -
536 * ruleset - - - -
537 */
538
539 if (!strcmp(curproxy->id, args[1]) &&
540 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
541 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
542 Alert("parsing %s: duplicated proxy %s with conflicting capabilities: %X/%X!\n",
543 file, args[1], curproxy->cap, rc);
544 return -1;
545 }
546 }
547
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
549 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
550 return -1;
551 }
552
553 curproxy->next = proxy;
554 proxy = curproxy;
555 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200556 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200557 LIST_INIT(&curproxy->block_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200558 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200559
Willy Tarreauee991362007-05-14 14:37:50 +0200560 /* Timeouts are defined as -1, so we cannot use the zeroed area
561 * as a default value.
562 */
563 tv_eternity(&curproxy->clitimeout);
564 tv_eternity(&curproxy->srvtimeout);
565 tv_eternity(&curproxy->contimeout);
566 tv_eternity(&curproxy->appsession_timeout);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200567
568 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200569 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100570 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200571
572 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100573 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200574 curproxy->listen = str2listener(args[2], curproxy->listen);
575 if (!curproxy->listen)
576 return -1;
577 global.maxsock++;
578 }
579
580 /* set default values */
581 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582 curproxy->options = defproxy.options;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200583 curproxy->except_net = defproxy.except_net;
584 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585
Willy Tarreau977b8e42006-12-29 14:19:17 +0100586 if (curproxy->cap & PR_CAP_FE) {
587 curproxy->maxconn = defproxy.maxconn;
588
589 /* initialize error relocations */
590 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
591 if (defproxy.errmsg[rc].str)
592 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
593 }
594
595 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
596 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200597
Willy Tarreau977b8e42006-12-29 14:19:17 +0100598 if (curproxy->cap & PR_CAP_BE) {
599 curproxy->fullconn = defproxy.fullconn;
600 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601
Willy Tarreau977b8e42006-12-29 14:19:17 +0100602 if (defproxy.check_req)
603 curproxy->check_req = strdup(defproxy.check_req);
604 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200605
Willy Tarreau977b8e42006-12-29 14:19:17 +0100606 if (defproxy.cookie_name)
607 curproxy->cookie_name = strdup(defproxy.cookie_name);
608 curproxy->cookie_len = defproxy.cookie_len;
609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610
Willy Tarreau977b8e42006-12-29 14:19:17 +0100611 if (curproxy->cap & PR_CAP_RS) {
612 if (defproxy.capture_name)
613 curproxy->capture_name = strdup(defproxy.capture_name);
614 curproxy->capture_namelen = defproxy.capture_namelen;
615 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100616 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617
Willy Tarreau977b8e42006-12-29 14:19:17 +0100618 if (curproxy->cap & PR_CAP_FE) {
619 curproxy->clitimeout = defproxy.clitimeout;
620 curproxy->uri_auth = defproxy.uri_auth;
621 curproxy->mon_net = defproxy.mon_net;
622 curproxy->mon_mask = defproxy.mon_mask;
623 if (defproxy.monitor_uri)
624 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
625 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100626 if (defproxy.defbe.name)
627 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100628 }
629
630 if (curproxy->cap & PR_CAP_BE) {
631 curproxy->contimeout = defproxy.contimeout;
632 curproxy->srvtimeout = defproxy.srvtimeout;
633 curproxy->source_addr = defproxy.source_addr;
634 }
635
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 curproxy->mode = defproxy.mode;
637 curproxy->logfac1 = defproxy.logfac1;
638 curproxy->logsrv1 = defproxy.logsrv1;
639 curproxy->loglev1 = defproxy.loglev1;
640 curproxy->logfac2 = defproxy.logfac2;
641 curproxy->logsrv2 = defproxy.logsrv2;
642 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200643 curproxy->grace = defproxy.grace;
Willy Tarreau1c47f852006-07-09 08:22:27 +0200644
Willy Tarreaubaaee002006-06-26 02:48:02 +0200645 return 0;
646 }
647 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
648 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100649 /* FIXME-20070101: we should do this too at the end of the
650 * config parsing to free all default values.
651 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 if (defproxy.check_req) free(defproxy.check_req);
653 if (defproxy.cookie_name) free(defproxy.cookie_name);
654 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200655 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100656 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100657
658 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
659 if (defproxy.errmsg[rc].len)
660 free(defproxy.errmsg[rc].str);
661 }
662
Willy Tarreaubaaee002006-06-26 02:48:02 +0200663 /* we cannot free uri_auth because it might already be used */
664 init_default_instance();
665 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100666 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200667 return 0;
668 }
669 else if (curproxy == NULL) {
670 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
671 return -1;
672 }
673
Willy Tarreau977b8e42006-12-29 14:19:17 +0100674
675 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676 if (!strcmp(args[0], "bind")) { /* new listen addresses */
677 if (curproxy == &defproxy) {
678 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
679 return -1;
680 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100681 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
682 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200683
684 if (strchr(args[1], ':') == NULL) {
685 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
686 file, linenum, args[0]);
687 return -1;
688 }
689 curproxy->listen = str2listener(args[1], curproxy->listen);
690 if (!curproxy->listen)
691 return -1;
692 global.maxsock++;
693 return 0;
694 }
695 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
696 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
697 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
698 file, linenum, args[0]);
699 return -1;
700 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100701 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
702 return 0;
703
Willy Tarreaubaaee002006-06-26 02:48:02 +0200704 /* flush useless bits */
705 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
706 return 0;
707 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200708 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100709 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
710 return 0;
711
Willy Tarreau1c47f852006-07-09 08:22:27 +0200712 if (!*args[1]) {
713 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
714 file, linenum, args[0]);
715 return -1;
716 }
717
718 if (curproxy->monitor_uri != NULL)
719 free(curproxy->monitor_uri);
720
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100721 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200722 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100723 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200724 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
725
726 return 0;
727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200728 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
729 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
730 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
731 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
732 else {
733 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
734 return -1;
735 }
736 }
737 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
738 curproxy->state = PR_STSTOPPED;
739 }
740 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
741 curproxy->state = PR_STNEW;
742 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200743 else if (!strcmp(args[0], "acl")) { /* add an ACL */
744 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
745 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
746 file, linenum, args[1]);
747 return -1;
748 }
749 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200750 else if (!strcmp(args[0], "cookie")) { /* cookie name */
751 int cur_arg;
752 // if (curproxy == &defproxy) {
753 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
754 // return -1;
755 // }
756
Willy Tarreau977b8e42006-12-29 14:19:17 +0100757 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
758 return 0;
759
Willy Tarreaubaaee002006-06-26 02:48:02 +0200760 if (curproxy->cookie_name != NULL) {
761 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
762 // file, linenum);
763 // return 0;
764 free(curproxy->cookie_name);
765 }
766
767 if (*(args[1]) == 0) {
768 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
769 file, linenum, args[0]);
770 return -1;
771 }
772 curproxy->cookie_name = strdup(args[1]);
773 curproxy->cookie_len = strlen(curproxy->cookie_name);
774
775 cur_arg = 2;
776 while (*(args[cur_arg])) {
777 if (!strcmp(args[cur_arg], "rewrite")) {
778 curproxy->options |= PR_O_COOK_RW;
779 }
780 else if (!strcmp(args[cur_arg], "indirect")) {
781 curproxy->options |= PR_O_COOK_IND;
782 }
783 else if (!strcmp(args[cur_arg], "insert")) {
784 curproxy->options |= PR_O_COOK_INS;
785 }
786 else if (!strcmp(args[cur_arg], "nocache")) {
787 curproxy->options |= PR_O_COOK_NOC;
788 }
789 else if (!strcmp(args[cur_arg], "postonly")) {
790 curproxy->options |= PR_O_COOK_POST;
791 }
792 else if (!strcmp(args[cur_arg], "prefix")) {
793 curproxy->options |= PR_O_COOK_PFX;
794 }
795 else {
796 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
797 file, linenum, args[0]);
798 return -1;
799 }
800 cur_arg++;
801 }
802 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
803 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
804 file, linenum);
805 return -1;
806 }
807
808 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
809 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
810 file, linenum);
811 return -1;
812 }
813 }/* end else if (!strcmp(args[0], "cookie")) */
814 else if (!strcmp(args[0], "appsession")) { /* cookie name */
815 // if (curproxy == &defproxy) {
816 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
817 // return -1;
818 // }
819
Willy Tarreau977b8e42006-12-29 14:19:17 +0100820 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
821 return 0;
822
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823 if (curproxy->appsession_name != NULL) {
824 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
825 // file, linenum);
826 // return 0;
827 free(curproxy->appsession_name);
828 }
829
830 if (*(args[5]) == 0) {
831 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
832 file, linenum, args[0]);
833 return -1;
834 }
835 have_appsession = 1;
836 curproxy->appsession_name = strdup(args[1]);
837 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
838 curproxy->appsession_len = atoi(args[3]);
Willy Tarreauee991362007-05-14 14:37:50 +0200839 val = atoi(args[5]);
840 if (val > 0)
841 __tv_from_ms(&curproxy->appsession_timeout, val);
842 else
843 tv_eternity(&curproxy->appsession_timeout);
844
Willy Tarreau51041c72007-09-09 21:56:53 +0200845 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
846 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200847 return -1;
848 }
849 } /* Url App Session */
850 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100851 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
852 return 0;
853
Willy Tarreaubaaee002006-06-26 02:48:02 +0200854 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
855 // if (curproxy == &defproxy) {
856 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
857 // return -1;
858 // }
859
860 if (curproxy->capture_name != NULL) {
861 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
862 // file, linenum, args[0]);
863 // return 0;
864 free(curproxy->capture_name);
865 }
866
867 if (*(args[4]) == 0) {
868 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
869 file, linenum, args[0]);
870 return -1;
871 }
872 curproxy->capture_name = strdup(args[2]);
873 curproxy->capture_namelen = strlen(curproxy->capture_name);
874 curproxy->capture_len = atol(args[4]);
875 if (curproxy->capture_len >= CAPTURE_LEN) {
876 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
877 file, linenum, CAPTURE_LEN - 1);
878 curproxy->capture_len = CAPTURE_LEN - 1;
879 }
880 curproxy->to_log |= LW_COOKIE;
881 }
882 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
883 struct cap_hdr *hdr;
884
885 if (curproxy == &defproxy) {
886 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
887 return -1;
888 }
889
890 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
891 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
892 file, linenum, args[0], args[1]);
893 return -1;
894 }
895
896 hdr = calloc(sizeof(struct cap_hdr), 1);
897 hdr->next = curproxy->req_cap;
898 hdr->name = strdup(args[3]);
899 hdr->namelen = strlen(args[3]);
900 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200901 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902 hdr->index = curproxy->nb_req_cap++;
903 curproxy->req_cap = hdr;
904 curproxy->to_log |= LW_REQHDR;
905 }
906 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
907 struct cap_hdr *hdr;
908
909 if (curproxy == &defproxy) {
910 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
911 return -1;
912 }
913
914 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
915 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
916 file, linenum, args[0], args[1]);
917 return -1;
918 }
919 hdr = calloc(sizeof(struct cap_hdr), 1);
920 hdr->next = curproxy->rsp_cap;
921 hdr->name = strdup(args[3]);
922 hdr->namelen = strlen(args[3]);
923 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200924 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200925 hdr->index = curproxy->nb_rsp_cap++;
926 curproxy->rsp_cap = hdr;
927 curproxy->to_log |= LW_RSPHDR;
928 }
929 else {
930 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
931 file, linenum, args[0]);
932 return -1;
933 }
934 }
935 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200936 if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
938 return 0;
939 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100940 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
941 return 0;
942
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 if (*(args[1]) == 0) {
944 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
945 file, linenum, args[0]);
946 return -1;
947 }
Willy Tarreauee991362007-05-14 14:37:50 +0200948 val = atoi(args[1]);
949 if (val > 0)
950 __tv_from_ms(&curproxy->contimeout, val);
951 else
952 tv_eternity(&curproxy->contimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953 }
954 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200955 if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200956 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
957 file, linenum, args[0]);
958 return 0;
959 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100960 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
961 return 0;
962
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 if (*(args[1]) == 0) {
964 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
965 file, linenum, args[0]);
966 return -1;
967 }
Willy Tarreauee991362007-05-14 14:37:50 +0200968 val = atoi(args[1]);
969 if (val > 0)
970 __tv_from_ms(&curproxy->clitimeout, val);
971 else
972 tv_eternity(&curproxy->clitimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
974 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200975 if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200976 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
977 return 0;
978 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100979 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
980 return 0;
981
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982 if (*(args[1]) == 0) {
983 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
984 file, linenum, args[0]);
985 return -1;
986 }
Willy Tarreauee991362007-05-14 14:37:50 +0200987 val = atoi(args[1]);
988 if (val > 0)
989 __tv_from_ms(&curproxy->srvtimeout, val);
990 else
991 tv_eternity(&curproxy->srvtimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 }
993 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100994 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 argument (dispatch counts for one).\n",
999 file, linenum, args[0]);
1000 return -1;
1001 }
1002 curproxy->conn_retries = atol(args[1]);
1003 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001004 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1005 int pol = ACL_COND_NONE;
1006 struct acl_cond *cond;
1007
1008 if (!strcmp(args[1], "if"))
1009 pol = ACL_COND_IF;
1010 else if (!strcmp(args[1], "unless"))
1011 pol = ACL_COND_UNLESS;
1012
1013 if (pol == ACL_COND_NONE) {
1014 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1015 file, linenum, args[0]);
1016 return -1;
1017 }
1018
1019 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1020 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1021 file, linenum);
1022 return -1;
1023 }
1024 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1025 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001026 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1027 int pol = ACL_COND_NONE;
1028 struct acl_cond *cond;
1029 struct switching_rule *rule;
1030
1031 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1032 return 0;
1033
1034 if (*(args[1]) == 0) {
1035 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1036 return -1;
1037 }
1038
1039 if (!strcmp(args[2], "if"))
1040 pol = ACL_COND_IF;
1041 else if (!strcmp(args[2], "unless"))
1042 pol = ACL_COND_UNLESS;
1043
1044 if (pol == ACL_COND_NONE) {
1045 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1046 file, linenum, args[0]);
1047 return -1;
1048 }
1049
1050 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1051 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1052 file, linenum);
1053 return -1;
1054 }
1055
1056 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1057 rule->cond = cond;
1058 rule->be.name = strdup(args[1]);
1059 LIST_INIT(&rule->list);
1060 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001063 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1064 return 0;
1065
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1067 curproxy->uri_auth = NULL; /* we must detach from the default config */
1068
1069 if (*(args[1]) == 0) {
1070 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1071 return -1;
1072 } else if (!strcmp(args[1], "uri")) {
1073 if (*(args[2]) == 0) {
1074 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1075 return -1;
1076 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1077 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1078 return -1;
1079 }
1080 } else if (!strcmp(args[1], "realm")) {
1081 if (*(args[2]) == 0) {
1082 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1083 return -1;
1084 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1085 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1086 return -1;
1087 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001088 } else if (!strcmp(args[1], "refresh")) {
1089 int interval = atoi(args[2]);
1090
1091 if (interval < 0) {
1092 Alert("parsing [%s:%d] : 'refresh' needs a positive interval in seconds.\n", file, linenum);
1093 return -1;
1094 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1095 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1096 return -1;
1097 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 } else if (!strcmp(args[1], "auth")) {
1099 if (*(args[2]) == 0) {
1100 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1101 return -1;
1102 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1103 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1104 return -1;
1105 }
1106 } else if (!strcmp(args[1], "scope")) {
1107 if (*(args[2]) == 0) {
1108 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1109 return -1;
1110 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1111 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1112 return -1;
1113 }
1114 } else if (!strcmp(args[1], "enable")) {
1115 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1116 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1117 return -1;
1118 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001119 } else if (!strcmp(args[1], "hide-version")) {
1120 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1121 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1122 return -1;
1123 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001124 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001125 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001126 file, linenum, args[0]);
1127 return -1;
1128 }
1129 }
1130 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001131 int optnum;
1132
Willy Tarreaubaaee002006-06-26 02:48:02 +02001133 if (*(args[1]) == 0) {
1134 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
1135 return -1;
1136 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001137
1138 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1139 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1140 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1141 return 0;
1142 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001143 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001144 return 0;
1145 }
1146 }
1147
1148 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 /* generate a complete HTTP log */
1150 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1151 else if (!strcmp(args[1], "tcplog"))
1152 /* generate a detailed TCP log */
1153 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154 else if (!strcmp(args[1], "tcpka")) {
1155 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001156 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1157 return 0;
1158
1159 if (curproxy->cap & PR_CAP_FE)
1160 curproxy->options |= PR_O_TCP_CLI_KA;
1161 if (curproxy->cap & PR_CAP_BE)
1162 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 }
1164 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001165 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1166 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167 /* use HTTP request to check servers' health */
1168 if (curproxy->check_req != NULL) {
1169 free(curproxy->check_req);
1170 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001171 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001172 curproxy->options &= ~PR_O_SMTP_CHK;
1173 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001174 if (!*args[2]) { /* no argument */
1175 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1176 curproxy->check_len = strlen(DEF_CHECK_REQ);
1177 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001178 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001179 curproxy->check_req = (char *)malloc(reqlen);
1180 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1181 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1182 } else { /* more arguments : METHOD URI [HTTP_VER] */
1183 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1184 if (*args[4])
1185 reqlen += strlen(args[4]);
1186 else
1187 reqlen += strlen("HTTP/1.0");
1188
1189 curproxy->check_req = (char *)malloc(reqlen);
1190 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1191 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1192 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001193 }
1194 else if (!strcmp(args[1], "ssl-hello-chk")) {
1195 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001196 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1197 return 0;
1198
Willy Tarreauf3c69202006-07-09 16:42:34 +02001199 if (curproxy->check_req != NULL) {
1200 free(curproxy->check_req);
1201 }
1202 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001203 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001204 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 }
Willy Tarreau23677902007-05-08 23:50:35 +02001206 else if (!strcmp(args[1], "smtpchk")) {
1207 /* use SMTP request to check servers' health */
1208 if (curproxy->check_req != NULL) {
1209 free(curproxy->check_req);
1210 }
1211 curproxy->options &= ~PR_O_HTTP_CHK;
1212 curproxy->options &= ~PR_O_SSL3_CHK;
1213 curproxy->options |= PR_O_SMTP_CHK;
1214
1215 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1216 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1217 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1218 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1219 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1220 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1221 curproxy->check_req = (char *)malloc(reqlen);
1222 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1223 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1224 } else {
1225 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1226 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1227 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1228 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1229 }
1230 }
1231 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001232 else if (!strcmp(args[1], "forwardfor")) {
1233 /* insert x-forwarded-for field, but not for the
1234 * IP address listed as an except.
1235 */
1236 if (*(args[2])) {
1237 if (!strcmp(args[2], "except")) {
1238 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1239 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1240 file, linenum, args[0]);
1241 return -1;
1242 }
1243 /* flush useless bits */
1244 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1245 } else {
1246 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1247 file, linenum, args[0]);
1248 return -1;
1249 }
1250 }
1251 curproxy->options |= PR_O_FWDFOR;
1252 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 else {
1254 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1255 return -1;
1256 }
1257 return 0;
1258 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001259 else if (!strcmp(args[0], "default_backend")) {
1260 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1261 return 0;
1262
1263 if (*(args[1]) == 0) {
1264 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1265 return -1;
1266 }
1267 if (curproxy->defbe.name)
1268 free(curproxy->defbe.name);
1269 curproxy->defbe.name = strdup(args[1]);
1270 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001271 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001272 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1273 return 0;
1274
Willy Tarreaubaaee002006-06-26 02:48:02 +02001275 /* enable reconnections to dispatch */
1276 curproxy->options |= PR_O_REDISP;
1277 }
1278#ifdef TPROXY
1279 else if (!strcmp(args[0], "transparent")) {
1280 /* enable transparent proxy connections */
1281 curproxy->options |= PR_O_TRANSP;
1282 }
1283#endif
1284 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001285 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1286 return 0;
1287
Willy Tarreaubaaee002006-06-26 02:48:02 +02001288 if (*(args[1]) == 0) {
1289 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1290 return -1;
1291 }
1292 curproxy->maxconn = atol(args[1]);
1293 }
Willy Tarreau86034312006-12-29 00:10:33 +01001294 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001295 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1296 return 0;
1297
Willy Tarreau86034312006-12-29 00:10:33 +01001298 if (*(args[1]) == 0) {
1299 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1300 return -1;
1301 }
1302 curproxy->fullconn = atol(args[1]);
1303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1305 if (*(args[1]) == 0) {
1306 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1307 return -1;
1308 }
1309 curproxy->grace = atol(args[1]);
1310 }
1311 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1312 if (curproxy == &defproxy) {
1313 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1314 return -1;
1315 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001316 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1317 return 0;
1318
Willy Tarreaubaaee002006-06-26 02:48:02 +02001319 if (strchr(args[1], ':') == NULL) {
1320 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1321 return -1;
1322 }
1323 curproxy->dispatch_addr = *str2sa(args[1]);
1324 }
1325 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001326 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1327 return 0;
1328
Willy Tarreaubaaee002006-06-26 02:48:02 +02001329 if (*(args[1])) {
1330 if (!strcmp(args[1], "roundrobin")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001331 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001332 curproxy->options |= PR_O_BALANCE_RR;
1333 }
1334 else if (!strcmp(args[1], "source")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001335 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001336 curproxy->options |= PR_O_BALANCE_SH;
1337 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001338 else if (!strcmp(args[1], "uri")) {
1339 curproxy->options &= ~PR_O_BALANCE;
1340 curproxy->options |= PR_O_BALANCE_UH;
1341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001342 else {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001343 Alert("parsing [%s:%d] : '%s' only supports 'roundrobin', 'source' and 'uri' options.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001344 return -1;
1345 }
1346 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001347 else {/* if no option is set, use round-robin by default */
1348 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 curproxy->options |= PR_O_BALANCE_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001350 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001351 }
1352 else if (!strcmp(args[0], "server")) { /* server address */
1353 int cur_arg;
1354 char *rport;
1355 char *raddr;
1356 short realport;
1357 int do_check;
1358
1359 if (curproxy == &defproxy) {
1360 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1361 return -1;
1362 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001363 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1364 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365
1366 if (!*args[2]) {
1367 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1368 file, linenum, args[0]);
1369 return -1;
1370 }
1371 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1372 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1373 return -1;
1374 }
1375
1376 /* the servers are linked backwards first */
1377 newsrv->next = curproxy->srv;
1378 curproxy->srv = newsrv;
1379 newsrv->proxy = curproxy;
1380
1381 LIST_INIT(&newsrv->pendconns);
1382 do_check = 0;
1383 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001384 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 newsrv->id = strdup(args[1]);
1386
1387 /* several ways to check the port component :
1388 * - IP => port=+0, relative
1389 * - IP: => port=+0, relative
1390 * - IP:N => port=N, absolute
1391 * - IP:+N => port=+N, relative
1392 * - IP:-N => port=-N, relative
1393 */
1394 raddr = strdup(args[2]);
1395 rport = strchr(raddr, ':');
1396 if (rport) {
1397 *rport++ = 0;
1398 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001399 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 newsrv->state |= SRV_MAPPORTS;
1401 } else {
1402 realport = 0;
1403 newsrv->state |= SRV_MAPPORTS;
1404 }
1405
1406 newsrv->addr = *str2sa(raddr);
1407 newsrv->addr.sin_port = htons(realport);
1408 free(raddr);
1409
1410 newsrv->curfd = -1; /* no health-check in progress */
1411 newsrv->inter = DEF_CHKINTR;
1412 newsrv->rise = DEF_RISETIME;
1413 newsrv->fall = DEF_FALLTIME;
1414 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001415 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001416 newsrv->maxqueue = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001417
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418 cur_arg = 3;
1419 while (*args[cur_arg]) {
1420 if (!strcmp(args[cur_arg], "cookie")) {
1421 newsrv->cookie = strdup(args[cur_arg + 1]);
1422 newsrv->cklen = strlen(args[cur_arg + 1]);
1423 cur_arg += 2;
1424 }
1425 else if (!strcmp(args[cur_arg], "rise")) {
1426 newsrv->rise = atol(args[cur_arg + 1]);
1427 newsrv->health = newsrv->rise;
1428 cur_arg += 2;
1429 }
1430 else if (!strcmp(args[cur_arg], "fall")) {
1431 newsrv->fall = atol(args[cur_arg + 1]);
1432 cur_arg += 2;
1433 }
1434 else if (!strcmp(args[cur_arg], "inter")) {
1435 newsrv->inter = atol(args[cur_arg + 1]);
1436 cur_arg += 2;
1437 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001438 else if (!strcmp(args[cur_arg], "addr")) {
1439 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001440 cur_arg += 2;
1441 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001442 else if (!strcmp(args[cur_arg], "port")) {
1443 newsrv->check_port = atol(args[cur_arg + 1]);
1444 cur_arg += 2;
1445 }
1446 else if (!strcmp(args[cur_arg], "backup")) {
1447 newsrv->state |= SRV_BACKUP;
1448 cur_arg ++;
1449 }
1450 else if (!strcmp(args[cur_arg], "weight")) {
1451 int w;
1452 w = atol(args[cur_arg + 1]);
1453 if (w < 1 || w > 256) {
1454 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1455 file, linenum, newsrv->id, w);
1456 return -1;
1457 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001458 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 cur_arg += 2;
1460 }
1461 else if (!strcmp(args[cur_arg], "minconn")) {
1462 newsrv->minconn = atol(args[cur_arg + 1]);
1463 cur_arg += 2;
1464 }
1465 else if (!strcmp(args[cur_arg], "maxconn")) {
1466 newsrv->maxconn = atol(args[cur_arg + 1]);
1467 cur_arg += 2;
1468 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001469 else if (!strcmp(args[cur_arg], "maxqueue")) {
1470 newsrv->maxqueue = atol(args[cur_arg + 1]);
1471 cur_arg += 2;
1472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473 else if (!strcmp(args[cur_arg], "check")) {
1474 global.maxsock++;
1475 do_check = 1;
1476 cur_arg += 1;
1477 }
1478 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1479 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001480#ifdef CONFIG_HAP_CTTPROXY
1481 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1482 file, linenum, "source", "usesrc");
1483#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001484 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1485 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001486#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487 return -1;
1488 }
1489 newsrv->state |= SRV_BIND_SRC;
1490 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1491 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001492 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001493#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001494 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001495 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1496 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001497 return -1;
1498 }
1499 if (!*args[cur_arg + 1]) {
1500 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1501 file, linenum, "usesrc");
1502 return -1;
1503 }
1504 if (!strcmp(args[cur_arg + 1], "client")) {
1505 newsrv->state |= SRV_TPROXY_CLI;
1506 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1507 newsrv->state |= SRV_TPROXY_CIP;
1508 } else {
1509 newsrv->state |= SRV_TPROXY_ADDR;
1510 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1511 }
1512 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1513 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001514#else /* no CTTPROXY support */
1515 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1516 file, linenum, "usesrc");
1517 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001518#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001519 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001520 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001521#ifdef CONFIG_HAP_CTTPROXY
1522 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1523 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1524 file, linenum, "usesrc", "source");
1525 return -1;
1526 }
1527#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001528 else {
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001529 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 +02001530 file, linenum, newsrv->id);
1531 return -1;
1532 }
1533 }
1534
1535 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001536 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1537 newsrv->check_port = newsrv->check_addr.sin_port;
1538
Willy Tarreaubaaee002006-06-26 02:48:02 +02001539 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1540 newsrv->check_port = realport; /* by default */
1541 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001542 /* not yet valid, because no port was set on
1543 * the server either. We'll check if we have
1544 * a known port on the first listener.
1545 */
1546 struct listener *l;
1547 l = curproxy->listen;
1548 if (l) {
1549 int port;
1550 port = (l->addr.ss_family == AF_INET6)
1551 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1552 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1553 newsrv->check_port = port;
1554 }
1555 }
1556 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1558 file, linenum, newsrv->id);
1559 return -1;
1560 }
1561 newsrv->state |= SRV_CHECKED;
1562 }
1563
1564 if (newsrv->state & SRV_BACKUP)
1565 curproxy->srv_bck++;
1566 else
1567 curproxy->srv_act++;
1568 }
1569 else if (!strcmp(args[0], "log")) { /* syslog server address */
1570 struct sockaddr_in *sa;
1571 int facility;
1572
1573 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1574 curproxy->logfac1 = global.logfac1;
1575 curproxy->logsrv1 = global.logsrv1;
1576 curproxy->loglev1 = global.loglev1;
1577 curproxy->logfac2 = global.logfac2;
1578 curproxy->logsrv2 = global.logsrv2;
1579 curproxy->loglev2 = global.loglev2;
1580 }
1581 else if (*(args[1]) && *(args[2])) {
1582 int level;
1583
1584 facility = get_log_facility(args[2]);
1585 if (facility < 0) {
1586 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1587 exit(1);
1588 }
1589
1590 level = 7; /* max syslog level = debug */
1591 if (*(args[3])) {
1592 level = get_log_level(args[3]);
1593 if (level < 0) {
1594 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1595 exit(1);
1596 }
1597 }
1598
1599 sa = str2sa(args[1]);
1600 if (!sa->sin_port)
1601 sa->sin_port = htons(SYSLOG_PORT);
1602
1603 if (curproxy->logfac1 == -1) {
1604 curproxy->logsrv1 = *sa;
1605 curproxy->logfac1 = facility;
1606 curproxy->loglev1 = level;
1607 }
1608 else if (curproxy->logfac2 == -1) {
1609 curproxy->logsrv2 = *sa;
1610 curproxy->logfac2 = facility;
1611 curproxy->loglev2 = level;
1612 }
1613 else {
1614 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1615 return -1;
1616 }
1617 }
1618 else {
1619 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1620 file, linenum);
1621 return -1;
1622 }
1623 }
1624 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001625 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1626 return 0;
1627
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001629#ifdef CONFIG_HAP_CTTPROXY
1630 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1631 file, linenum, "source", "usesrc");
1632#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1634 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001635#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636 return -1;
1637 }
1638
1639 curproxy->source_addr = *str2sa(args[1]);
1640 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001641 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001642#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001643 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1644 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1645 file, linenum, "usesrc");
1646 return -1;
1647 }
1648 if (!*args[3]) {
1649 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1650 file, linenum, "usesrc");
1651 return -1;
1652 }
1653
1654 if (!strcmp(args[3], "client")) {
1655 curproxy->options |= PR_O_TPXY_CLI;
1656 } else if (!strcmp(args[3], "clientip")) {
1657 curproxy->options |= PR_O_TPXY_CIP;
1658 } else {
1659 curproxy->options |= PR_O_TPXY_ADDR;
1660 curproxy->tproxy_addr = *str2sa(args[3]);
1661 }
1662 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001663#else /* no CTTPROXY support */
1664 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1665 file, linenum, "usesrc");
1666 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001667#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001669 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001670#ifdef CONFIG_HAP_CTTPROXY
1671 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1672 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1673 file, linenum, "usesrc", "source");
1674 return -1;
1675 }
1676#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001677 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1678 regex_t *preg;
1679 if (curproxy == &defproxy) {
1680 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1681 return -1;
1682 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001683 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1684 return 0;
1685
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 if (*(args[1]) == 0 || *(args[2]) == 0) {
1687 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1688 file, linenum, args[0]);
1689 return -1;
1690 }
1691
1692 preg = calloc(1, sizeof(regex_t));
1693 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1694 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1695 return -1;
1696 }
1697
1698 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1699 if (err) {
1700 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1701 file, linenum, *err);
1702 return -1;
1703 }
1704 }
1705 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1706 regex_t *preg;
1707 if (curproxy == &defproxy) {
1708 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1709 return -1;
1710 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001711 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1712 return 0;
1713
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 if (*(args[1]) == 0) {
1715 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1716 return -1;
1717 }
1718
1719 preg = calloc(1, sizeof(regex_t));
1720 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1721 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1722 return -1;
1723 }
1724
1725 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1726 }
1727 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1728 regex_t *preg;
1729 if (curproxy == &defproxy) {
1730 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1731 return -1;
1732 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001733 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1734 return 0;
1735
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 if (*(args[1]) == 0) {
1737 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1738 return -1;
1739 }
1740
1741 preg = calloc(1, sizeof(regex_t));
1742 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1743 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1744 return -1;
1745 }
1746
1747 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1748 }
1749 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1750 regex_t *preg;
1751 if (curproxy == &defproxy) {
1752 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1753 return -1;
1754 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001755 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1756 return 0;
1757
Willy Tarreaubaaee002006-06-26 02:48:02 +02001758 if (*(args[1]) == 0) {
1759 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1760 return -1;
1761 }
1762
1763 preg = calloc(1, sizeof(regex_t));
1764 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1765 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1766 return -1;
1767 }
1768
1769 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1770 }
1771 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1772 regex_t *preg;
1773 if (curproxy == &defproxy) {
1774 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1775 return -1;
1776 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001777 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1778 return 0;
1779
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 if (*(args[1]) == 0) {
1781 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1782 return -1;
1783 }
1784
1785 preg = calloc(1, sizeof(regex_t));
1786 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1787 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1788 return -1;
1789 }
1790
1791 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1792 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001793 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1794 regex_t *preg;
1795 if (curproxy == &defproxy) {
1796 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1797 return -1;
1798 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001799 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1800 return 0;
1801
Willy Tarreaub8750a82006-09-03 09:56:00 +02001802 if (*(args[1]) == 0) {
1803 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1804 return -1;
1805 }
1806
1807 preg = calloc(1, sizeof(regex_t));
1808 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1809 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1810 return -1;
1811 }
1812
1813 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1814 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001815 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1816 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001817 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001818 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1819 return -1;
1820 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001821 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1822 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001823
Willy Tarreau977b8e42006-12-29 14:19:17 +01001824 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001825 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1826 file, linenum, args[0]);
1827 return -1;
1828 }
1829
1830 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001831 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001832 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1833 }
1834
1835 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1836 }
1837 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1838 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001839 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001840 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1841 return -1;
1842 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001843 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1844 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001845
Willy Tarreau977b8e42006-12-29 14:19:17 +01001846 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001847 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1848 file, linenum, args[0]);
1849 return -1;
1850 }
1851
1852 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001853 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001854 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1855 }
1856
1857 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1858 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001859 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1860 regex_t *preg;
1861 if (curproxy == &defproxy) {
1862 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1863 return -1;
1864 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001865 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1866 return 0;
1867
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 if (*(args[1]) == 0 || *(args[2]) == 0) {
1869 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1870 file, linenum, args[0]);
1871 return -1;
1872 }
1873
1874 preg = calloc(1, sizeof(regex_t));
1875 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1876 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1877 return -1;
1878 }
1879
1880 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1881 if (err) {
1882 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1883 file, linenum, *err);
1884 return -1;
1885 }
1886 }
1887 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1888 regex_t *preg;
1889 if (curproxy == &defproxy) {
1890 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1891 return -1;
1892 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001893 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1894 return 0;
1895
Willy Tarreaubaaee002006-06-26 02:48:02 +02001896 if (*(args[1]) == 0) {
1897 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1898 return -1;
1899 }
1900
1901 preg = calloc(1, sizeof(regex_t));
1902 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1903 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1904 return -1;
1905 }
1906
1907 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1908 }
1909 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1910 regex_t *preg;
1911 if (curproxy == &defproxy) {
1912 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1913 return -1;
1914 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001915 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1916 return 0;
1917
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 if (*(args[1]) == 0) {
1919 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1920 return -1;
1921 }
1922
1923 preg = calloc(1, sizeof(regex_t));
1924 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1925 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1926 return -1;
1927 }
1928
1929 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1930 }
1931 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1932 regex_t *preg;
1933 if (curproxy == &defproxy) {
1934 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1935 return -1;
1936 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001937 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1938 return 0;
1939
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 if (*(args[1]) == 0) {
1941 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1942 return -1;
1943 }
1944
1945 preg = calloc(1, sizeof(regex_t));
1946 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1947 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1948 return -1;
1949 }
1950
1951 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1952 }
1953 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1954 regex_t *preg;
1955 if (curproxy == &defproxy) {
1956 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1957 return -1;
1958 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001959 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1960 return 0;
1961
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962 if (*(args[1]) == 0) {
1963 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1964 return -1;
1965 }
1966
1967 preg = calloc(1, sizeof(regex_t));
1968 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1969 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1970 return -1;
1971 }
1972
1973 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1974 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001975 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1976 regex_t *preg;
1977 if (curproxy == &defproxy) {
1978 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1979 return -1;
1980 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001981 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1982 return 0;
1983
Willy Tarreaub8750a82006-09-03 09:56:00 +02001984 if (*(args[1]) == 0) {
1985 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1986 return -1;
1987 }
1988
1989 preg = calloc(1, sizeof(regex_t));
1990 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1991 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1992 return -1;
1993 }
1994
1995 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1996 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001997 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1998 if (curproxy == &defproxy) {
1999 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2000 return -1;
2001 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002002 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2003 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004
2005 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2006 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2007 return 0;
2008 }
2009
2010 if (*(args[1]) == 0) {
2011 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2012 return -1;
2013 }
2014
2015 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2016 }
2017 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2018 regex_t *preg;
2019
2020 if (*(args[1]) == 0 || *(args[2]) == 0) {
2021 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2022 file, linenum, args[0]);
2023 return -1;
2024 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002025 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2026 return 0;
2027
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028 preg = calloc(1, sizeof(regex_t));
2029 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2030 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2031 return -1;
2032 }
2033
2034 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2035 if (err) {
2036 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2037 file, linenum, *err);
2038 return -1;
2039 }
2040 }
2041 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2042 regex_t *preg;
2043 if (curproxy == &defproxy) {
2044 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2045 return -1;
2046 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002047 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2048 return 0;
2049
Willy Tarreaubaaee002006-06-26 02:48:02 +02002050 if (*(args[1]) == 0) {
2051 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2052 return -1;
2053 }
2054
2055 preg = calloc(1, sizeof(regex_t));
2056 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2057 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2058 return -1;
2059 }
2060
2061 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2062 if (err) {
2063 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2064 file, linenum, *err);
2065 return -1;
2066 }
2067 }
2068 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2069 regex_t *preg;
2070 if (curproxy == &defproxy) {
2071 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2072 return -1;
2073 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002074 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2075 return 0;
2076
Willy Tarreaubaaee002006-06-26 02:48:02 +02002077 if (*(args[1]) == 0) {
2078 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2079 return -1;
2080 }
2081
2082 preg = calloc(1, sizeof(regex_t));
2083 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2084 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2085 return -1;
2086 }
2087
2088 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2089 if (err) {
2090 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2091 file, linenum, *err);
2092 return -1;
2093 }
2094 }
2095 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2096 regex_t *preg;
2097 if (curproxy == &defproxy) {
2098 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2099 return -1;
2100 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002101 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2102 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103
2104 if (*(args[1]) == 0 || *(args[2]) == 0) {
2105 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2106 file, linenum, args[0]);
2107 return -1;
2108 }
2109
2110 preg = calloc(1, sizeof(regex_t));
2111 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2112 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2113 return -1;
2114 }
2115
2116 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2117 if (err) {
2118 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2119 file, linenum, *err);
2120 return -1;
2121 }
2122 }
2123 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2124 regex_t *preg;
2125 if (curproxy == &defproxy) {
2126 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2127 return -1;
2128 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002129 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2130 return 0;
2131
Willy Tarreaubaaee002006-06-26 02:48:02 +02002132 if (*(args[1]) == 0) {
2133 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2134 return -1;
2135 }
2136
2137 preg = calloc(1, sizeof(regex_t));
2138 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2139 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2140 return -1;
2141 }
2142
2143 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2144 if (err) {
2145 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2146 file, linenum, *err);
2147 return -1;
2148 }
2149 }
2150 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2151 regex_t *preg;
2152 if (curproxy == &defproxy) {
2153 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2154 return -1;
2155 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002156 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2157 return 0;
2158
Willy Tarreaubaaee002006-06-26 02:48:02 +02002159 if (*(args[1]) == 0) {
2160 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2161 return -1;
2162 }
2163
2164 preg = calloc(1, sizeof(regex_t));
2165 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2166 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2167 return -1;
2168 }
2169
2170 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2171 if (err) {
2172 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2173 file, linenum, *err);
2174 return -1;
2175 }
2176 }
2177 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2178 if (curproxy == &defproxy) {
2179 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2180 return -1;
2181 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002182 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2183 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184
2185 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2186 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2187 return 0;
2188 }
2189
2190 if (*(args[1]) == 0) {
2191 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2192 return -1;
2193 }
2194
2195 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2196 }
2197 else if (!strcmp(args[0], "errorloc") ||
2198 !strcmp(args[0], "errorloc302") ||
2199 !strcmp(args[0], "errorloc303")) { /* error location */
2200 int errnum, errlen;
2201 char *err;
2202
Willy Tarreau977b8e42006-12-29 14:19:17 +01002203 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2204 return 0;
2205
Willy Tarreaubaaee002006-06-26 02:48:02 +02002206 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002207 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002208 return -1;
2209 }
2210
2211 errnum = atol(args[1]);
2212 if (!strcmp(args[0], "errorloc303")) {
2213 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2214 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2215 } else {
2216 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2217 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2218 }
2219
Willy Tarreau0f772532006-12-23 20:51:41 +01002220 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2221 if (http_err_codes[rc] == errnum) {
2222 if (curproxy->errmsg[rc].str)
2223 free(curproxy->errmsg[rc].str);
2224 curproxy->errmsg[rc].str = err;
2225 curproxy->errmsg[rc].len = errlen;
2226 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002229
2230 if (rc >= HTTP_ERR_SIZE) {
2231 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2232 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233 free(err);
2234 }
2235 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002236 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2237 int errnum, errlen, fd;
2238 char *err;
2239 struct stat stat;
2240
2241 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2242 return 0;
2243
2244 if (*(args[2]) == 0) {
2245 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2246 return -1;
2247 }
2248
2249 fd = open(args[2], O_RDONLY);
2250 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2251 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2252 file, linenum, args[2], args[1]);
2253 if (fd >= 0)
2254 close(fd);
2255 return -1;
2256 }
2257
2258 if (stat.st_size <= BUFSIZE) {
2259 errlen = stat.st_size;
2260 } else {
2261 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2262 file, linenum, args[2], BUFSIZE);
2263 errlen = BUFSIZE;
2264 }
2265
2266 err = malloc(errlen); /* malloc() must succeed during parsing */
2267 errnum = read(fd, err, errlen);
2268 if (errnum != errlen) {
2269 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2270 file, linenum, args[2], args[1]);
2271 close(fd);
2272 free(err);
2273 return -1;
2274 }
2275 close(fd);
2276
2277 errnum = atol(args[1]);
2278 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2279 if (http_err_codes[rc] == errnum) {
2280 if (curproxy->errmsg[rc].str)
2281 free(curproxy->errmsg[rc].str);
2282 curproxy->errmsg[rc].str = err;
2283 curproxy->errmsg[rc].len = errlen;
2284 break;
2285 }
2286 }
2287
2288 if (rc >= HTTP_ERR_SIZE) {
2289 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2290 file, linenum, errnum);
2291 free(err);
2292 }
2293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 else {
2295 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2296 return -1;
2297 }
2298 return 0;
2299}
2300
2301
2302/*
2303 * This function reads and parses the configuration file given in the argument.
2304 * returns 0 if OK, -1 if error.
2305 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002306int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002307{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002308 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 FILE *f;
2310 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002311 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 int confsect = CFG_NONE;
2313
2314 struct proxy *curproxy = NULL;
2315 struct server *newsrv = NULL;
2316
2317 if ((f=fopen(file,"r")) == NULL)
2318 return -1;
2319
2320 init_default_instance();
2321
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002322 while (fgets(thisline, sizeof(thisline), f) != NULL) {
2323 int arg;
2324 char *end;
2325 char *args[MAX_LINE_ARGS + 1];
2326 char *line = thisline;
2327
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 linenum++;
2329
2330 end = line + strlen(line);
2331
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002332 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2333 /* Check if we reached the limit and the last char is not \n.
2334 * Watch out for the last line without the terminating '\n'!
2335 */
2336 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2337 file, linenum, sizeof(thisline)-1);
2338 return -1;
2339 }
2340
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002342 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002343 line++;
2344
2345 arg = 0;
2346 args[arg] = line;
2347
2348 while (*line && arg < MAX_LINE_ARGS) {
2349 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2350 * C equivalent value. Other combinations left unchanged (eg: \1).
2351 */
2352 if (*line == '\\') {
2353 int skip = 0;
2354 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2355 *line = line[1];
2356 skip = 1;
2357 }
2358 else if (line[1] == 'r') {
2359 *line = '\r';
2360 skip = 1;
2361 }
2362 else if (line[1] == 'n') {
2363 *line = '\n';
2364 skip = 1;
2365 }
2366 else if (line[1] == 't') {
2367 *line = '\t';
2368 skip = 1;
2369 }
2370 else if (line[1] == 'x') {
2371 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2372 unsigned char hex1, hex2;
2373 hex1 = toupper(line[2]) - '0';
2374 hex2 = toupper(line[3]) - '0';
2375 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2376 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2377 *line = (hex1<<4) + hex2;
2378 skip = 3;
2379 }
2380 else {
2381 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2382 return -1;
2383 }
2384 }
2385 if (skip) {
2386 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2387 end -= skip;
2388 }
2389 line++;
2390 }
2391 else if (*line == '#' || *line == '\n' || *line == '\r') {
2392 /* end of string, end of loop */
2393 *line = 0;
2394 break;
2395 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002396 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002398 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002399 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 line++;
2401 args[++arg] = line;
2402 }
2403 else {
2404 line++;
2405 }
2406 }
2407
2408 /* empty line */
2409 if (!**args)
2410 continue;
2411
Willy Tarreau540abe42007-05-02 20:50:16 +02002412 /* zero out remaining args and ensure that at least one entry
2413 * is zeroed out.
2414 */
2415 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002416 args[arg] = line;
2417 }
2418
Willy Tarreau977b8e42006-12-29 14:19:17 +01002419 if (!strcmp(args[0], "listen") ||
2420 !strcmp(args[0], "frontend") ||
2421 !strcmp(args[0], "backend") ||
2422 !strcmp(args[0], "ruleset") ||
2423 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 confsect = CFG_LISTEN;
2425 else if (!strcmp(args[0], "global")) /* global config */
2426 confsect = CFG_GLOBAL;
2427 /* else it's a section keyword */
2428
2429 switch (confsect) {
2430 case CFG_LISTEN:
2431 if (cfg_parse_listen(file, linenum, args) < 0)
2432 return -1;
2433 break;
2434 case CFG_GLOBAL:
2435 if (cfg_parse_global(file, linenum, args) < 0)
2436 return -1;
2437 break;
2438 default:
2439 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2440 return -1;
2441 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
2443 fclose(f);
2444
2445 /*
2446 * Now, check for the integrity of all that we have collected.
2447 */
2448
2449 /* will be needed further to delay some tasks */
2450 tv_now(&now);
2451
2452 if ((curproxy = proxy) == NULL) {
2453 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2454 file);
2455 return -1;
2456 }
2457
2458 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002459 struct switching_rule *rule;
2460
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 Tarreau2fcb5002007-05-08 13:35:26 +02002516 if (curproxy->options & PR_O_BALANCE_UH) {
2517 curproxy->options &= ~PR_O_BALANCE;
2518 curproxy->options |= PR_O_BALANCE_RR;
2519
2520 Warning("parsing %s : URI hash will be ignored for %s '%s'. Falling back to round robin.\n",
2521 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
2544 for (target = proxy; target != NULL; target = target->next) {
Krzysztof Oledzki02594192007-10-31 09:07:24 +01002545 if ((target->cap & PR_CAP_BE) && !strcmp(target->id, curproxy->defbe.name))
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002546 break;
2547 }
2548 if (target == NULL) {
Krzysztof Oledzki02594192007-10-31 09:07:24 +01002549 Alert("parsing %s: default proxy '%s' with backend capability in HTTP %s '%s' was not found!\n",
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002550 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2551 cfgerr++;
2552 } else if (target == curproxy) {
2553 Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
2554 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002555 } else if (target->mode != curproxy->mode) {
2556 Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
2557 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2558 cfgerr++;
2559 } else {
2560 free(curproxy->defbe.name);
2561 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 }
2563 }
2564
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002565 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002566 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2567 /* map jump target for ACT_SETBE in req_rep chain */
2568 struct hdr_exp *exp;
2569 struct proxy *target;
2570 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
2571 if (exp->action != ACT_SETBE)
2572 continue;
2573 for (target = proxy; target != NULL; target = target->next) {
Krzysztof Oledzki02594192007-10-31 09:07:24 +01002574 if ((target->cap & PR_CAP_BE) && !strcmp(target->id, exp->replace))
Willy Tarreaua496b602006-12-17 23:15:24 +01002575 break;
2576 }
2577 if (target == NULL) {
Krzysztof Oledzki02594192007-10-31 09:07:24 +01002578 Alert("parsing %s: proxy '%s' with backend capability in HTTP %s '%s' was not found!\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002579 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaua496b602006-12-17 23:15:24 +01002580 cfgerr++;
2581 } else if (target == curproxy) {
2582 Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
2583 cfgerr++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002584 } else if (target->mode != PR_MODE_HTTP) {
2585 Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002586 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002587 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002588 } else {
2589 free((void *)exp->replace);
2590 exp->replace = (const char *)target;
2591 }
2592 }
2593 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002594
2595 /* find the target proxy for 'use_backend' rules */
2596 list_for_each_entry(rule, &curproxy->switching_rules, list) {
2597 /* map jump target for ACT_SETBE in req_rep chain */
2598 struct proxy *target;
2599
2600 for (target = proxy; target != NULL; target = target->next) {
Krzysztof Oledzki02594192007-10-31 09:07:24 +01002601 if ((target->cap & PR_CAP_BE) && !strcmp(target->id, rule->be.name))
Willy Tarreau55ea7572007-06-17 19:56:27 +02002602 break;
2603 }
2604
2605 if (target == NULL) {
Krzysztof Oledzki02594192007-10-31 09:07:24 +01002606 Alert("parsing %s: proxy '%s' with backend capability in HTTP %s '%s' was not found!\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002607 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2608 cfgerr++;
2609 } else if (target == curproxy) {
2610 Alert("parsing %s : loop detected for backend %s !\n", file, rule->be.name);
2611 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002612 } else if (target->mode != curproxy->mode) {
2613 Alert("parsing %s : backend '%s' referenced in %s '%s' is of different mode !\n",
2614 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2615 cfgerr++;
2616 } else {
2617 free((void *)rule->be.name);
2618 rule->be.backend = target;
2619 }
2620 }
2621
Willy Tarreau2738a142006-07-08 17:28:09 +02002622 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002623 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2624 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2625 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002626 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002627 " | While not properly invalid, you will certainly encounter various problems\n"
2628 " | with such a configuration. To fix this, please ensure that all following\n"
2629 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002630 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002631 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002632
2633 if (curproxy->options & PR_O_SSL3_CHK) {
2634 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2635 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2636 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2637 }
2638
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002639 /* The small pools required for the capture lists */
2640 if (curproxy->nb_req_cap)
2641 curproxy->req_cap_pool = create_pool("ptrcap",
2642 curproxy->nb_req_cap * sizeof(char *),
2643 MEM_F_SHARED);
2644 if (curproxy->nb_rsp_cap)
2645 curproxy->rsp_cap_pool = create_pool("ptrcap",
2646 curproxy->nb_rsp_cap * sizeof(char *),
2647 MEM_F_SHARED);
2648
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002649 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2650 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2651 MEM_F_SHARED);
2652
Willy Tarreau86034312006-12-29 00:10:33 +01002653 /* for backwards compatibility with "listen" instances, if
2654 * fullconn is not set but maxconn is set, then maxconn
2655 * is used.
2656 */
2657 if (!curproxy->fullconn)
2658 curproxy->fullconn = curproxy->maxconn;
2659
Willy Tarreaubaaee002006-06-26 02:48:02 +02002660 /* first, we will invert the servers list order */
2661 newsrv = NULL;
2662 while (curproxy->srv) {
2663 struct server *next;
2664
2665 next = curproxy->srv->next;
2666 curproxy->srv->next = newsrv;
2667 newsrv = curproxy->srv;
2668 if (!next)
2669 break;
2670 curproxy->srv = next;
2671 }
2672
2673 /* now, newsrv == curproxy->srv */
2674 if (newsrv) {
2675 struct server *srv;
2676 int pgcd;
2677 int act, bck;
2678
2679 /* We will factor the weights to reduce the table,
2680 * using Euclide's largest common divisor algorithm
2681 */
Willy Tarreau417fae02007-03-25 21:16:40 +02002682 pgcd = newsrv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002683 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2684 int t, w;
2685
Willy Tarreau417fae02007-03-25 21:16:40 +02002686 w = srv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 while (w) {
2688 t = pgcd % w;
2689 pgcd = w;
2690 w = t;
2691 }
2692 }
2693
2694 act = bck = 0;
2695 for (srv = newsrv; srv; srv = srv->next) {
Willy Tarreau417fae02007-03-25 21:16:40 +02002696 srv->eweight = srv->uweight / pgcd;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002697 if (srv->state & SRV_BACKUP)
Willy Tarreau417fae02007-03-25 21:16:40 +02002698 bck += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 else
Willy Tarreau417fae02007-03-25 21:16:40 +02002700 act += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002701 }
2702
2703 /* this is the largest map we will ever need for this servers list */
2704 if (act < bck)
2705 act = bck;
2706
2707 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2708 /* recounts servers and their weights */
Willy Tarreau5af3a692007-07-24 23:32:33 +02002709 curproxy->map_state = PR_MAP_RECALC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002710 recount_servers(curproxy);
2711 recalc_server_map(curproxy);
2712 }
2713
2714 if (curproxy->options & PR_O_LOGASAP)
2715 curproxy->to_log &= ~LW_BYTES;
2716
Willy Tarreaubaaee002006-06-26 02:48:02 +02002717 /*
2718 * If this server supports a maxconn parameter, it needs a dedicated
2719 * tasks to fill the emptied slots when a connection leaves.
2720 */
2721 newsrv = curproxy->srv;
2722 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002723 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002724 /* Only 'minconn' was specified, or it was higher than or equal
2725 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2726 * this will avoid further useless expensive computations.
2727 */
2728 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002729 } else if (newsrv->maxconn && !newsrv->minconn) {
2730 /* minconn was not specified, so we set it to maxconn */
2731 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002732 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2733 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002734 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002735 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002736 }
2737
2738 if (newsrv->maxconn > 0) {
2739 struct task *t;
2740
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002741 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2743 return -1;
2744 }
2745
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002746 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002747 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748 t->state = TASK_IDLE;
2749 t->process = process_srv_queue;
2750 t->context = newsrv;
2751 newsrv->queue_mgt = t;
2752
2753 /* never run it unless specifically woken up */
2754 tv_eternity(&t->expire);
2755 task_queue(t);
2756 }
2757 newsrv = newsrv->next;
2758 }
2759
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 curproxy = curproxy->next;
2761 }
2762 if (cfgerr > 0) {
2763 Alert("Errors found in configuration file, aborting.\n");
2764 return -1;
2765 }
2766 else
2767 return 0;
2768}
2769
2770
2771
2772/*
2773 * Local variables:
2774 * c-indent-level: 8
2775 * c-basic-offset: 8
2776 * End:
2777 */