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