blob: b64d4c6b47f56d9c6d019f43a0b5b059fb2b959d [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
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100537 err = invalid_char(args[1]);
538 if (err) {
539 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
540 file, linenum, *err, args[0], args[1]);
541 return -1;
542 }
543
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200544 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
545 /*
546 * If there are two proxies with the same name only following
547 * combinations are allowed:
548 *
549 * listen backend frontend ruleset
550 * listen - - - -
551 * backend - - OK -
552 * frontend - OK - -
553 * ruleset - - - -
554 */
555
556 if (!strcmp(curproxy->id, args[1]) &&
557 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
558 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100559 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
560 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200561 }
562 }
563
Willy Tarreaubaaee002006-06-26 02:48:02 +0200564 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
565 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
566 return -1;
567 }
568
569 curproxy->next = proxy;
570 proxy = curproxy;
571 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200572 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200573 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100574 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200575 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200576
Willy Tarreauee991362007-05-14 14:37:50 +0200577 /* Timeouts are defined as -1, so we cannot use the zeroed area
578 * as a default value.
579 */
580 tv_eternity(&curproxy->clitimeout);
581 tv_eternity(&curproxy->srvtimeout);
582 tv_eternity(&curproxy->contimeout);
583 tv_eternity(&curproxy->appsession_timeout);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200584
585 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200586 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100587 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200588
589 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100590 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200591 curproxy->listen = str2listener(args[2], curproxy->listen);
592 if (!curproxy->listen)
593 return -1;
594 global.maxsock++;
595 }
596
597 /* set default values */
598 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100600 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200601 curproxy->except_net = defproxy.except_net;
602 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603
Willy Tarreau977b8e42006-12-29 14:19:17 +0100604 if (curproxy->cap & PR_CAP_FE) {
605 curproxy->maxconn = defproxy.maxconn;
606
607 /* initialize error relocations */
608 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
609 if (defproxy.errmsg[rc].str)
610 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
611 }
612
613 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
614 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615
Willy Tarreau977b8e42006-12-29 14:19:17 +0100616 if (curproxy->cap & PR_CAP_BE) {
617 curproxy->fullconn = defproxy.fullconn;
618 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200619
Willy Tarreau977b8e42006-12-29 14:19:17 +0100620 if (defproxy.check_req)
621 curproxy->check_req = strdup(defproxy.check_req);
622 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623
Willy Tarreau977b8e42006-12-29 14:19:17 +0100624 if (defproxy.cookie_name)
625 curproxy->cookie_name = strdup(defproxy.cookie_name);
626 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100627
628 if (defproxy.url_param_name)
629 curproxy->url_param_name = strdup(defproxy.url_param_name);
630 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632
Willy Tarreau977b8e42006-12-29 14:19:17 +0100633 if (curproxy->cap & PR_CAP_RS) {
634 if (defproxy.capture_name)
635 curproxy->capture_name = strdup(defproxy.capture_name);
636 curproxy->capture_namelen = defproxy.capture_namelen;
637 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100638 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639
Willy Tarreau977b8e42006-12-29 14:19:17 +0100640 if (curproxy->cap & PR_CAP_FE) {
641 curproxy->clitimeout = defproxy.clitimeout;
642 curproxy->uri_auth = defproxy.uri_auth;
643 curproxy->mon_net = defproxy.mon_net;
644 curproxy->mon_mask = defproxy.mon_mask;
645 if (defproxy.monitor_uri)
646 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
647 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100648 if (defproxy.defbe.name)
649 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100650 }
651
652 if (curproxy->cap & PR_CAP_BE) {
653 curproxy->contimeout = defproxy.contimeout;
654 curproxy->srvtimeout = defproxy.srvtimeout;
655 curproxy->source_addr = defproxy.source_addr;
656 }
657
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658 curproxy->mode = defproxy.mode;
659 curproxy->logfac1 = defproxy.logfac1;
660 curproxy->logsrv1 = defproxy.logsrv1;
661 curproxy->loglev1 = defproxy.loglev1;
662 curproxy->logfac2 = defproxy.logfac2;
663 curproxy->logsrv2 = defproxy.logsrv2;
664 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100666 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
667 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200668
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669 return 0;
670 }
671 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
672 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100673 /* FIXME-20070101: we should do this too at the end of the
674 * config parsing to free all default values.
675 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676 if (defproxy.check_req) free(defproxy.check_req);
677 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100678 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200679 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200680 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100681 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100682
683 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
684 if (defproxy.errmsg[rc].len)
685 free(defproxy.errmsg[rc].str);
686 }
687
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 /* we cannot free uri_auth because it might already be used */
689 init_default_instance();
690 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100691 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692 return 0;
693 }
694 else if (curproxy == NULL) {
695 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
696 return -1;
697 }
698
Willy Tarreau977b8e42006-12-29 14:19:17 +0100699
700 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 if (!strcmp(args[0], "bind")) { /* new listen addresses */
702 if (curproxy == &defproxy) {
703 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
704 return -1;
705 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100706 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
707 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200708
709 if (strchr(args[1], ':') == NULL) {
710 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
711 file, linenum, args[0]);
712 return -1;
713 }
714 curproxy->listen = str2listener(args[1], curproxy->listen);
715 if (!curproxy->listen)
716 return -1;
717 global.maxsock++;
718 return 0;
719 }
720 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
721 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
722 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
723 file, linenum, args[0]);
724 return -1;
725 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100726 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
727 return 0;
728
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729 /* flush useless bits */
730 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
731 return 0;
732 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200733 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100734 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
735 return 0;
736
Willy Tarreau1c47f852006-07-09 08:22:27 +0200737 if (!*args[1]) {
738 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
739 file, linenum, args[0]);
740 return -1;
741 }
742
743 if (curproxy->monitor_uri != NULL)
744 free(curproxy->monitor_uri);
745
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100746 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200747 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100748 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200749 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
750
751 return 0;
752 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200753 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
754 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
755 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
756 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
757 else {
758 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
759 return -1;
760 }
761 }
762 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
763 curproxy->state = PR_STSTOPPED;
764 }
765 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
766 curproxy->state = PR_STNEW;
767 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200768 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100769 err = invalid_char(args[1]);
770 if (err) {
771 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
772 file, linenum, *err, args[1]);
773 return -1;
774 }
775
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200776 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
777 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
778 file, linenum, args[1]);
779 return -1;
780 }
781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 else if (!strcmp(args[0], "cookie")) { /* cookie name */
783 int cur_arg;
784 // if (curproxy == &defproxy) {
785 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
786 // return -1;
787 // }
788
Willy Tarreau977b8e42006-12-29 14:19:17 +0100789 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
790 return 0;
791
Willy Tarreaubaaee002006-06-26 02:48:02 +0200792 if (curproxy->cookie_name != NULL) {
793 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
794 // file, linenum);
795 // return 0;
796 free(curproxy->cookie_name);
797 }
798
799 if (*(args[1]) == 0) {
800 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
801 file, linenum, args[0]);
802 return -1;
803 }
804 curproxy->cookie_name = strdup(args[1]);
805 curproxy->cookie_len = strlen(curproxy->cookie_name);
806
807 cur_arg = 2;
808 while (*(args[cur_arg])) {
809 if (!strcmp(args[cur_arg], "rewrite")) {
810 curproxy->options |= PR_O_COOK_RW;
811 }
812 else if (!strcmp(args[cur_arg], "indirect")) {
813 curproxy->options |= PR_O_COOK_IND;
814 }
815 else if (!strcmp(args[cur_arg], "insert")) {
816 curproxy->options |= PR_O_COOK_INS;
817 }
818 else if (!strcmp(args[cur_arg], "nocache")) {
819 curproxy->options |= PR_O_COOK_NOC;
820 }
821 else if (!strcmp(args[cur_arg], "postonly")) {
822 curproxy->options |= PR_O_COOK_POST;
823 }
824 else if (!strcmp(args[cur_arg], "prefix")) {
825 curproxy->options |= PR_O_COOK_PFX;
826 }
827 else {
828 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
829 file, linenum, args[0]);
830 return -1;
831 }
832 cur_arg++;
833 }
834 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
835 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
836 file, linenum);
837 return -1;
838 }
839
840 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
841 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
842 file, linenum);
843 return -1;
844 }
845 }/* end else if (!strcmp(args[0], "cookie")) */
846 else if (!strcmp(args[0], "appsession")) { /* cookie name */
847 // if (curproxy == &defproxy) {
848 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
849 // return -1;
850 // }
851
Willy Tarreau977b8e42006-12-29 14:19:17 +0100852 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
853 return 0;
854
Willy Tarreaubaaee002006-06-26 02:48:02 +0200855 if (curproxy->appsession_name != NULL) {
856 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
857 // file, linenum);
858 // return 0;
859 free(curproxy->appsession_name);
860 }
861
862 if (*(args[5]) == 0) {
863 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
864 file, linenum, args[0]);
865 return -1;
866 }
867 have_appsession = 1;
868 curproxy->appsession_name = strdup(args[1]);
869 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
870 curproxy->appsession_len = atoi(args[3]);
Willy Tarreauee991362007-05-14 14:37:50 +0200871 val = atoi(args[5]);
872 if (val > 0)
873 __tv_from_ms(&curproxy->appsession_timeout, val);
874 else
875 tv_eternity(&curproxy->appsession_timeout);
876
Willy Tarreau51041c72007-09-09 21:56:53 +0200877 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
878 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879 return -1;
880 }
881 } /* Url App Session */
882 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100883 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
884 return 0;
885
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
887 // if (curproxy == &defproxy) {
888 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
889 // return -1;
890 // }
891
892 if (curproxy->capture_name != NULL) {
893 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
894 // file, linenum, args[0]);
895 // return 0;
896 free(curproxy->capture_name);
897 }
898
899 if (*(args[4]) == 0) {
900 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
901 file, linenum, args[0]);
902 return -1;
903 }
904 curproxy->capture_name = strdup(args[2]);
905 curproxy->capture_namelen = strlen(curproxy->capture_name);
906 curproxy->capture_len = atol(args[4]);
907 if (curproxy->capture_len >= CAPTURE_LEN) {
908 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
909 file, linenum, CAPTURE_LEN - 1);
910 curproxy->capture_len = CAPTURE_LEN - 1;
911 }
912 curproxy->to_log |= LW_COOKIE;
913 }
914 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
915 struct cap_hdr *hdr;
916
917 if (curproxy == &defproxy) {
918 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
919 return -1;
920 }
921
922 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
923 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
924 file, linenum, args[0], args[1]);
925 return -1;
926 }
927
928 hdr = calloc(sizeof(struct cap_hdr), 1);
929 hdr->next = curproxy->req_cap;
930 hdr->name = strdup(args[3]);
931 hdr->namelen = strlen(args[3]);
932 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200933 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934 hdr->index = curproxy->nb_req_cap++;
935 curproxy->req_cap = hdr;
936 curproxy->to_log |= LW_REQHDR;
937 }
938 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
939 struct cap_hdr *hdr;
940
941 if (curproxy == &defproxy) {
942 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
943 return -1;
944 }
945
946 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
947 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
948 file, linenum, args[0], args[1]);
949 return -1;
950 }
951 hdr = calloc(sizeof(struct cap_hdr), 1);
952 hdr->next = curproxy->rsp_cap;
953 hdr->name = strdup(args[3]);
954 hdr->namelen = strlen(args[3]);
955 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200956 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 hdr->index = curproxy->nb_rsp_cap++;
958 curproxy->rsp_cap = hdr;
959 curproxy->to_log |= LW_RSPHDR;
960 }
961 else {
962 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
963 file, linenum, args[0]);
964 return -1;
965 }
966 }
967 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200968 if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200969 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
970 return 0;
971 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100972 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
973 return 0;
974
Willy Tarreaubaaee002006-06-26 02:48:02 +0200975 if (*(args[1]) == 0) {
976 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
977 file, linenum, args[0]);
978 return -1;
979 }
Willy Tarreauee991362007-05-14 14:37:50 +0200980 val = atoi(args[1]);
981 if (val > 0)
982 __tv_from_ms(&curproxy->contimeout, val);
983 else
984 tv_eternity(&curproxy->contimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 }
986 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200987 if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
989 file, linenum, args[0]);
990 return 0;
991 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100992 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
993 return 0;
994
Willy Tarreaubaaee002006-06-26 02:48:02 +0200995 if (*(args[1]) == 0) {
996 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
997 file, linenum, args[0]);
998 return -1;
999 }
Willy Tarreauee991362007-05-14 14:37:50 +02001000 val = atoi(args[1]);
1001 if (val > 0)
1002 __tv_from_ms(&curproxy->clitimeout, val);
1003 else
1004 tv_eternity(&curproxy->clitimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005 }
1006 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +02001007 if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001008 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1009 return 0;
1010 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001011 else 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 <time_in_ms> as argument.\n",
1016 file, linenum, args[0]);
1017 return -1;
1018 }
Willy Tarreauee991362007-05-14 14:37:50 +02001019 val = atoi(args[1]);
1020 if (val > 0)
1021 __tv_from_ms(&curproxy->srvtimeout, val);
1022 else
1023 tv_eternity(&curproxy->srvtimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001024 }
1025 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001026 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1027 return 0;
1028
Willy Tarreaubaaee002006-06-26 02:48:02 +02001029 if (*(args[1]) == 0) {
1030 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1031 file, linenum, args[0]);
1032 return -1;
1033 }
1034 curproxy->conn_retries = atol(args[1]);
1035 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001036 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1037 int pol = ACL_COND_NONE;
1038 struct acl_cond *cond;
1039
1040 if (!strcmp(args[1], "if"))
1041 pol = ACL_COND_IF;
1042 else if (!strcmp(args[1], "unless"))
1043 pol = ACL_COND_UNLESS;
1044
1045 if (pol == ACL_COND_NONE) {
1046 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1047 file, linenum, args[0]);
1048 return -1;
1049 }
1050
1051 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1052 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1053 file, linenum);
1054 return -1;
1055 }
1056 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1057 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001058 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1059 int pol = ACL_COND_NONE;
1060 struct acl_cond *cond;
1061 struct switching_rule *rule;
1062
1063 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1064 return 0;
1065
1066 if (*(args[1]) == 0) {
1067 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1068 return -1;
1069 }
1070
1071 if (!strcmp(args[2], "if"))
1072 pol = ACL_COND_IF;
1073 else if (!strcmp(args[2], "unless"))
1074 pol = ACL_COND_UNLESS;
1075
1076 if (pol == ACL_COND_NONE) {
1077 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1078 file, linenum, args[0]);
1079 return -1;
1080 }
1081
1082 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1083 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1084 file, linenum);
1085 return -1;
1086 }
1087
1088 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1089 rule->cond = cond;
1090 rule->be.name = strdup(args[1]);
1091 LIST_INIT(&rule->list);
1092 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001095 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1096 return 0;
1097
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1099 curproxy->uri_auth = NULL; /* we must detach from the default config */
1100
1101 if (*(args[1]) == 0) {
1102 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1103 return -1;
1104 } else if (!strcmp(args[1], "uri")) {
1105 if (*(args[2]) == 0) {
1106 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1107 return -1;
1108 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1109 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1110 return -1;
1111 }
1112 } else if (!strcmp(args[1], "realm")) {
1113 if (*(args[2]) == 0) {
1114 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1115 return -1;
1116 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1117 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1118 return -1;
1119 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001120 } else if (!strcmp(args[1], "refresh")) {
1121 int interval = atoi(args[2]);
1122
1123 if (interval < 0) {
1124 Alert("parsing [%s:%d] : 'refresh' needs a positive interval in seconds.\n", file, linenum);
1125 return -1;
1126 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1127 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1128 return -1;
1129 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130 } else if (!strcmp(args[1], "auth")) {
1131 if (*(args[2]) == 0) {
1132 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1133 return -1;
1134 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1135 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1136 return -1;
1137 }
1138 } else if (!strcmp(args[1], "scope")) {
1139 if (*(args[2]) == 0) {
1140 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1141 return -1;
1142 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1143 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1144 return -1;
1145 }
1146 } else if (!strcmp(args[1], "enable")) {
1147 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1148 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1149 return -1;
1150 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001151 } else if (!strcmp(args[1], "hide-version")) {
1152 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1153 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1154 return -1;
1155 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001157 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158 file, linenum, args[0]);
1159 return -1;
1160 }
1161 }
1162 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001163 int optnum;
1164
Willy Tarreaubaaee002006-06-26 02:48:02 +02001165 if (*(args[1]) == 0) {
1166 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
1167 return -1;
1168 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001169
1170 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1171 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1172 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1173 return 0;
1174 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001175 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001176 return 0;
1177 }
1178 }
1179
1180 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001181 /* generate a complete HTTP log */
1182 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1183 else if (!strcmp(args[1], "tcplog"))
1184 /* generate a detailed TCP log */
1185 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001186 else if (!strcmp(args[1], "tcpka")) {
1187 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001188 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1189 return 0;
1190
1191 if (curproxy->cap & PR_CAP_FE)
1192 curproxy->options |= PR_O_TCP_CLI_KA;
1193 if (curproxy->cap & PR_CAP_BE)
1194 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001195 }
1196 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001197 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1198 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001199 /* use HTTP request to check servers' health */
1200 if (curproxy->check_req != NULL) {
1201 free(curproxy->check_req);
1202 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001203 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001204 curproxy->options &= ~PR_O_SMTP_CHK;
1205 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001206 if (!*args[2]) { /* no argument */
1207 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1208 curproxy->check_len = strlen(DEF_CHECK_REQ);
1209 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001210 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001211 curproxy->check_req = (char *)malloc(reqlen);
1212 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1213 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1214 } else { /* more arguments : METHOD URI [HTTP_VER] */
1215 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1216 if (*args[4])
1217 reqlen += strlen(args[4]);
1218 else
1219 reqlen += strlen("HTTP/1.0");
1220
1221 curproxy->check_req = (char *)malloc(reqlen);
1222 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1223 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1224 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001225 }
1226 else if (!strcmp(args[1], "ssl-hello-chk")) {
1227 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001228 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1229 return 0;
1230
Willy Tarreauf3c69202006-07-09 16:42:34 +02001231 if (curproxy->check_req != NULL) {
1232 free(curproxy->check_req);
1233 }
1234 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001235 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001236 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001237 }
Willy Tarreau23677902007-05-08 23:50:35 +02001238 else if (!strcmp(args[1], "smtpchk")) {
1239 /* use SMTP request to check servers' health */
1240 if (curproxy->check_req != NULL) {
1241 free(curproxy->check_req);
1242 }
1243 curproxy->options &= ~PR_O_HTTP_CHK;
1244 curproxy->options &= ~PR_O_SSL3_CHK;
1245 curproxy->options |= PR_O_SMTP_CHK;
1246
1247 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1248 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1249 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1250 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1251 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1252 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1253 curproxy->check_req = (char *)malloc(reqlen);
1254 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1255 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1256 } else {
1257 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1258 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1259 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1260 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1261 }
1262 }
1263 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001264 else if (!strcmp(args[1], "forwardfor")) {
1265 /* insert x-forwarded-for field, but not for the
1266 * IP address listed as an except.
1267 */
1268 if (*(args[2])) {
1269 if (!strcmp(args[2], "except")) {
1270 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1271 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1272 file, linenum, args[0]);
1273 return -1;
1274 }
1275 /* flush useless bits */
1276 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1277 } else {
1278 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1279 file, linenum, args[0]);
1280 return -1;
1281 }
1282 }
1283 curproxy->options |= PR_O_FWDFOR;
1284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001285 else {
1286 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1287 return -1;
1288 }
1289 return 0;
1290 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001291 else if (!strcmp(args[0], "default_backend")) {
1292 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1293 return 0;
1294
1295 if (*(args[1]) == 0) {
1296 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1297 return -1;
1298 }
1299 if (curproxy->defbe.name)
1300 free(curproxy->defbe.name);
1301 curproxy->defbe.name = strdup(args[1]);
1302 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001303 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001304 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1305 return 0;
1306
Willy Tarreaubaaee002006-06-26 02:48:02 +02001307 /* enable reconnections to dispatch */
1308 curproxy->options |= PR_O_REDISP;
1309 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001310 else if (!strcmp(args[0], "http-check")) {
1311 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1312 return 0;
1313
1314 if (strcmp(args[1], "disable-on-404") == 0) {
1315 /* enable a graceful server shutdown on an HTTP 404 response */
1316 curproxy->options |= PR_O_DISABLE404;
1317 }
1318 else {
1319 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1320 return -1;
1321 }
1322 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001323 else if (!strcmp(args[0], "monitor")) {
1324 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1325 return 0;
1326
1327 if (strcmp(args[1], "fail") == 0) {
1328 /* add a condition to fail monitor requests */
1329 int pol = ACL_COND_NONE;
1330 struct acl_cond *cond;
1331
1332 if (!strcmp(args[2], "if"))
1333 pol = ACL_COND_IF;
1334 else if (!strcmp(args[2], "unless"))
1335 pol = ACL_COND_UNLESS;
1336
1337 if (pol == ACL_COND_NONE) {
1338 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1339 file, linenum, args[0], args[1]);
1340 return -1;
1341 }
1342
1343 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1344 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1345 file, linenum, args[0], args[1]);
1346 return -1;
1347 }
1348 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1349 }
1350 else {
1351 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1352 return -1;
1353 }
1354 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001355#ifdef TPROXY
1356 else if (!strcmp(args[0], "transparent")) {
1357 /* enable transparent proxy connections */
1358 curproxy->options |= PR_O_TRANSP;
1359 }
1360#endif
1361 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001362 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1363 return 0;
1364
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365 if (*(args[1]) == 0) {
1366 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1367 return -1;
1368 }
1369 curproxy->maxconn = atol(args[1]);
1370 }
Willy Tarreau86034312006-12-29 00:10:33 +01001371 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001372 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1373 return 0;
1374
Willy Tarreau86034312006-12-29 00:10:33 +01001375 if (*(args[1]) == 0) {
1376 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1377 return -1;
1378 }
1379 curproxy->fullconn = atol(args[1]);
1380 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001381 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1382 if (*(args[1]) == 0) {
1383 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1384 return -1;
1385 }
1386 curproxy->grace = atol(args[1]);
1387 }
1388 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1389 if (curproxy == &defproxy) {
1390 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1391 return -1;
1392 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001393 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1394 return 0;
1395
Willy Tarreaubaaee002006-06-26 02:48:02 +02001396 if (strchr(args[1], ':') == NULL) {
1397 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1398 return -1;
1399 }
1400 curproxy->dispatch_addr = *str2sa(args[1]);
1401 }
1402 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001403 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1404 return 0;
1405
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001406 memcpy(trash, "error near 'balance'", 19);
1407 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1408 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1409 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001410 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411 }
1412 else if (!strcmp(args[0], "server")) { /* server address */
1413 int cur_arg;
1414 char *rport;
1415 char *raddr;
1416 short realport;
1417 int do_check;
1418
1419 if (curproxy == &defproxy) {
1420 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1421 return -1;
1422 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001423 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1424 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001425
1426 if (!*args[2]) {
1427 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1428 file, linenum, args[0]);
1429 return -1;
1430 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001431
1432 err = invalid_char(args[1]);
1433 if (err) {
1434 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1435 file, linenum, *err, args[1]);
1436 return -1;
1437 }
1438
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1440 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1441 return -1;
1442 }
1443
1444 /* the servers are linked backwards first */
1445 newsrv->next = curproxy->srv;
1446 curproxy->srv = newsrv;
1447 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001448 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001449
1450 LIST_INIT(&newsrv->pendconns);
1451 do_check = 0;
1452 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001453 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 newsrv->id = strdup(args[1]);
1455
1456 /* several ways to check the port component :
1457 * - IP => port=+0, relative
1458 * - IP: => port=+0, relative
1459 * - IP:N => port=N, absolute
1460 * - IP:+N => port=+N, relative
1461 * - IP:-N => port=-N, relative
1462 */
1463 raddr = strdup(args[2]);
1464 rport = strchr(raddr, ':');
1465 if (rport) {
1466 *rport++ = 0;
1467 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001468 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001469 newsrv->state |= SRV_MAPPORTS;
1470 } else {
1471 realport = 0;
1472 newsrv->state |= SRV_MAPPORTS;
1473 }
1474
1475 newsrv->addr = *str2sa(raddr);
1476 newsrv->addr.sin_port = htons(realport);
1477 free(raddr);
1478
1479 newsrv->curfd = -1; /* no health-check in progress */
1480 newsrv->inter = DEF_CHKINTR;
1481 newsrv->rise = DEF_RISETIME;
1482 newsrv->fall = DEF_FALLTIME;
1483 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001484 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001485 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001486 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001487
Willy Tarreaubaaee002006-06-26 02:48:02 +02001488 cur_arg = 3;
1489 while (*args[cur_arg]) {
1490 if (!strcmp(args[cur_arg], "cookie")) {
1491 newsrv->cookie = strdup(args[cur_arg + 1]);
1492 newsrv->cklen = strlen(args[cur_arg + 1]);
1493 cur_arg += 2;
1494 }
1495 else if (!strcmp(args[cur_arg], "rise")) {
1496 newsrv->rise = atol(args[cur_arg + 1]);
1497 newsrv->health = newsrv->rise;
1498 cur_arg += 2;
1499 }
1500 else if (!strcmp(args[cur_arg], "fall")) {
1501 newsrv->fall = atol(args[cur_arg + 1]);
1502 cur_arg += 2;
1503 }
1504 else if (!strcmp(args[cur_arg], "inter")) {
1505 newsrv->inter = atol(args[cur_arg + 1]);
1506 cur_arg += 2;
1507 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001508 else if (!strcmp(args[cur_arg], "addr")) {
1509 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001510 cur_arg += 2;
1511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001512 else if (!strcmp(args[cur_arg], "port")) {
1513 newsrv->check_port = atol(args[cur_arg + 1]);
1514 cur_arg += 2;
1515 }
1516 else if (!strcmp(args[cur_arg], "backup")) {
1517 newsrv->state |= SRV_BACKUP;
1518 cur_arg ++;
1519 }
1520 else if (!strcmp(args[cur_arg], "weight")) {
1521 int w;
1522 w = atol(args[cur_arg + 1]);
1523 if (w < 1 || w > 256) {
1524 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1525 file, linenum, newsrv->id, w);
1526 return -1;
1527 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001528 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529 cur_arg += 2;
1530 }
1531 else if (!strcmp(args[cur_arg], "minconn")) {
1532 newsrv->minconn = atol(args[cur_arg + 1]);
1533 cur_arg += 2;
1534 }
1535 else if (!strcmp(args[cur_arg], "maxconn")) {
1536 newsrv->maxconn = atol(args[cur_arg + 1]);
1537 cur_arg += 2;
1538 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001539 else if (!strcmp(args[cur_arg], "maxqueue")) {
1540 newsrv->maxqueue = atol(args[cur_arg + 1]);
1541 cur_arg += 2;
1542 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001543 else if (!strcmp(args[cur_arg], "slowstart")) {
1544 /* slowstart is stored in seconds */
1545 newsrv->slowstart = (atol(args[cur_arg + 1]) + 999) / 1000;
1546 cur_arg += 2;
1547 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001548 else if (!strcmp(args[cur_arg], "check")) {
1549 global.maxsock++;
1550 do_check = 1;
1551 cur_arg += 1;
1552 }
1553 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1554 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001555#ifdef CONFIG_HAP_CTTPROXY
1556 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1557 file, linenum, "source", "usesrc");
1558#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1560 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001561#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562 return -1;
1563 }
1564 newsrv->state |= SRV_BIND_SRC;
1565 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1566 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001567 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001568#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001569 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001570 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1571 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001572 return -1;
1573 }
1574 if (!*args[cur_arg + 1]) {
1575 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1576 file, linenum, "usesrc");
1577 return -1;
1578 }
1579 if (!strcmp(args[cur_arg + 1], "client")) {
1580 newsrv->state |= SRV_TPROXY_CLI;
1581 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1582 newsrv->state |= SRV_TPROXY_CIP;
1583 } else {
1584 newsrv->state |= SRV_TPROXY_ADDR;
1585 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1586 }
1587 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1588 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001589#else /* no CTTPROXY support */
1590 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1591 file, linenum, "usesrc");
1592 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001593#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001594 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001595 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001596#ifdef CONFIG_HAP_CTTPROXY
1597 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1598 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1599 file, linenum, "usesrc", "source");
1600 return -1;
1601 }
1602#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 else {
Willy Tarreau9909fc12007-11-30 17:42:05 +01001604 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 file, linenum, newsrv->id);
1606 return -1;
1607 }
1608 }
1609
1610 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001611 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1612 newsrv->check_port = newsrv->check_addr.sin_port;
1613
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1615 newsrv->check_port = realport; /* by default */
1616 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001617 /* not yet valid, because no port was set on
1618 * the server either. We'll check if we have
1619 * a known port on the first listener.
1620 */
1621 struct listener *l;
1622 l = curproxy->listen;
1623 if (l) {
1624 int port;
1625 port = (l->addr.ss_family == AF_INET6)
1626 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1627 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1628 newsrv->check_port = port;
1629 }
1630 }
1631 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001632 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1633 file, linenum, newsrv->id);
1634 return -1;
1635 }
1636 newsrv->state |= SRV_CHECKED;
1637 }
1638
1639 if (newsrv->state & SRV_BACKUP)
1640 curproxy->srv_bck++;
1641 else
1642 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001643
1644 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001645 }
1646 else if (!strcmp(args[0], "log")) { /* syslog server address */
1647 struct sockaddr_in *sa;
1648 int facility;
1649
1650 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1651 curproxy->logfac1 = global.logfac1;
1652 curproxy->logsrv1 = global.logsrv1;
1653 curproxy->loglev1 = global.loglev1;
1654 curproxy->logfac2 = global.logfac2;
1655 curproxy->logsrv2 = global.logsrv2;
1656 curproxy->loglev2 = global.loglev2;
1657 }
1658 else if (*(args[1]) && *(args[2])) {
1659 int level;
1660
1661 facility = get_log_facility(args[2]);
1662 if (facility < 0) {
1663 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1664 exit(1);
1665 }
1666
1667 level = 7; /* max syslog level = debug */
1668 if (*(args[3])) {
1669 level = get_log_level(args[3]);
1670 if (level < 0) {
1671 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1672 exit(1);
1673 }
1674 }
1675
1676 sa = str2sa(args[1]);
1677 if (!sa->sin_port)
1678 sa->sin_port = htons(SYSLOG_PORT);
1679
1680 if (curproxy->logfac1 == -1) {
1681 curproxy->logsrv1 = *sa;
1682 curproxy->logfac1 = facility;
1683 curproxy->loglev1 = level;
1684 }
1685 else if (curproxy->logfac2 == -1) {
1686 curproxy->logsrv2 = *sa;
1687 curproxy->logfac2 = facility;
1688 curproxy->loglev2 = level;
1689 }
1690 else {
1691 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1692 return -1;
1693 }
1694 }
1695 else {
1696 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1697 file, linenum);
1698 return -1;
1699 }
1700 }
1701 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001702 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1703 return 0;
1704
Willy Tarreaubaaee002006-06-26 02:48:02 +02001705 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001706#ifdef CONFIG_HAP_CTTPROXY
1707 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1708 file, linenum, "source", "usesrc");
1709#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1711 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001712#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 return -1;
1714 }
1715
1716 curproxy->source_addr = *str2sa(args[1]);
1717 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001718 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001719#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001720 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1721 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1722 file, linenum, "usesrc");
1723 return -1;
1724 }
1725 if (!*args[3]) {
1726 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1727 file, linenum, "usesrc");
1728 return -1;
1729 }
1730
1731 if (!strcmp(args[3], "client")) {
1732 curproxy->options |= PR_O_TPXY_CLI;
1733 } else if (!strcmp(args[3], "clientip")) {
1734 curproxy->options |= PR_O_TPXY_CIP;
1735 } else {
1736 curproxy->options |= PR_O_TPXY_ADDR;
1737 curproxy->tproxy_addr = *str2sa(args[3]);
1738 }
1739 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001740#else /* no CTTPROXY support */
1741 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1742 file, linenum, "usesrc");
1743 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001744#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001745 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001747#ifdef CONFIG_HAP_CTTPROXY
1748 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1749 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1750 file, linenum, "usesrc", "source");
1751 return -1;
1752 }
1753#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1755 regex_t *preg;
1756 if (curproxy == &defproxy) {
1757 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1758 return -1;
1759 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001760 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1761 return 0;
1762
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763 if (*(args[1]) == 0 || *(args[2]) == 0) {
1764 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1765 file, linenum, args[0]);
1766 return -1;
1767 }
1768
1769 preg = calloc(1, sizeof(regex_t));
1770 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1771 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1772 return -1;
1773 }
1774
1775 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1776 if (err) {
1777 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1778 file, linenum, *err);
1779 return -1;
1780 }
1781 }
1782 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1783 regex_t *preg;
1784 if (curproxy == &defproxy) {
1785 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1786 return -1;
1787 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001788 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1789 return 0;
1790
Willy Tarreaubaaee002006-06-26 02:48:02 +02001791 if (*(args[1]) == 0) {
1792 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1793 return -1;
1794 }
1795
1796 preg = calloc(1, sizeof(regex_t));
1797 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1798 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1799 return -1;
1800 }
1801
1802 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1803 }
1804 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1805 regex_t *preg;
1806 if (curproxy == &defproxy) {
1807 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1808 return -1;
1809 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001810 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1811 return 0;
1812
Willy Tarreaubaaee002006-06-26 02:48:02 +02001813 if (*(args[1]) == 0) {
1814 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1815 return -1;
1816 }
1817
1818 preg = calloc(1, sizeof(regex_t));
1819 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1820 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1821 return -1;
1822 }
1823
1824 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1825 }
1826 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1827 regex_t *preg;
1828 if (curproxy == &defproxy) {
1829 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1830 return -1;
1831 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001832 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1833 return 0;
1834
Willy Tarreaubaaee002006-06-26 02:48:02 +02001835 if (*(args[1]) == 0) {
1836 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1837 return -1;
1838 }
1839
1840 preg = calloc(1, sizeof(regex_t));
1841 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1842 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1843 return -1;
1844 }
1845
1846 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1847 }
1848 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1849 regex_t *preg;
1850 if (curproxy == &defproxy) {
1851 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1852 return -1;
1853 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001854 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1855 return 0;
1856
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857 if (*(args[1]) == 0) {
1858 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1859 return -1;
1860 }
1861
1862 preg = calloc(1, sizeof(regex_t));
1863 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1864 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1865 return -1;
1866 }
1867
1868 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1869 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001870 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1871 regex_t *preg;
1872 if (curproxy == &defproxy) {
1873 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1874 return -1;
1875 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001876 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1877 return 0;
1878
Willy Tarreaub8750a82006-09-03 09:56:00 +02001879 if (*(args[1]) == 0) {
1880 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1881 return -1;
1882 }
1883
1884 preg = calloc(1, sizeof(regex_t));
1885 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1886 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1887 return -1;
1888 }
1889
1890 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1891 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001892 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1893 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001894 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001895 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1896 return -1;
1897 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001898 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1899 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001900
Willy Tarreau977b8e42006-12-29 14:19:17 +01001901 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001902 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1903 file, linenum, args[0]);
1904 return -1;
1905 }
1906
1907 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001908 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001909 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1910 }
1911
1912 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1913 }
1914 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1915 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001916 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001917 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1918 return -1;
1919 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001920 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1921 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001922
Willy Tarreau977b8e42006-12-29 14:19:17 +01001923 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001924 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1925 file, linenum, args[0]);
1926 return -1;
1927 }
1928
1929 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001930 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001931 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1932 }
1933
1934 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1935 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1937 regex_t *preg;
1938 if (curproxy == &defproxy) {
1939 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1940 return -1;
1941 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001942 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1943 return 0;
1944
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 if (*(args[1]) == 0 || *(args[2]) == 0) {
1946 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1947 file, linenum, args[0]);
1948 return -1;
1949 }
1950
1951 preg = calloc(1, sizeof(regex_t));
1952 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1953 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1954 return -1;
1955 }
1956
1957 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1958 if (err) {
1959 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1960 file, linenum, *err);
1961 return -1;
1962 }
1963 }
1964 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1965 regex_t *preg;
1966 if (curproxy == &defproxy) {
1967 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1968 return -1;
1969 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001970 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1971 return 0;
1972
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 if (*(args[1]) == 0) {
1974 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1975 return -1;
1976 }
1977
1978 preg = calloc(1, sizeof(regex_t));
1979 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1980 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1981 return -1;
1982 }
1983
1984 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1985 }
1986 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1987 regex_t *preg;
1988 if (curproxy == &defproxy) {
1989 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1990 return -1;
1991 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001992 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1993 return 0;
1994
Willy Tarreaubaaee002006-06-26 02:48:02 +02001995 if (*(args[1]) == 0) {
1996 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1997 return -1;
1998 }
1999
2000 preg = calloc(1, sizeof(regex_t));
2001 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2002 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2003 return -1;
2004 }
2005
2006 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2007 }
2008 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2009 regex_t *preg;
2010 if (curproxy == &defproxy) {
2011 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2012 return -1;
2013 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002014 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2015 return 0;
2016
Willy Tarreaubaaee002006-06-26 02:48:02 +02002017 if (*(args[1]) == 0) {
2018 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2019 return -1;
2020 }
2021
2022 preg = calloc(1, sizeof(regex_t));
2023 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2024 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2025 return -1;
2026 }
2027
2028 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2029 }
2030 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2031 regex_t *preg;
2032 if (curproxy == &defproxy) {
2033 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2034 return -1;
2035 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002036 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2037 return 0;
2038
Willy Tarreaubaaee002006-06-26 02:48:02 +02002039 if (*(args[1]) == 0) {
2040 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2041 return -1;
2042 }
2043
2044 preg = calloc(1, sizeof(regex_t));
2045 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2046 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2047 return -1;
2048 }
2049
2050 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2051 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002052 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2053 regex_t *preg;
2054 if (curproxy == &defproxy) {
2055 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2056 return -1;
2057 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002058 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2059 return 0;
2060
Willy Tarreaub8750a82006-09-03 09:56:00 +02002061 if (*(args[1]) == 0) {
2062 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2063 return -1;
2064 }
2065
2066 preg = calloc(1, sizeof(regex_t));
2067 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2068 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2069 return -1;
2070 }
2071
2072 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2073 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2075 if (curproxy == &defproxy) {
2076 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2077 return -1;
2078 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002079 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2080 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081
2082 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2083 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2084 return 0;
2085 }
2086
2087 if (*(args[1]) == 0) {
2088 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2089 return -1;
2090 }
2091
2092 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2093 }
2094 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2095 regex_t *preg;
2096
2097 if (*(args[1]) == 0 || *(args[2]) == 0) {
2098 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2099 file, linenum, args[0]);
2100 return -1;
2101 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002102 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2103 return 0;
2104
Willy Tarreaubaaee002006-06-26 02:48:02 +02002105 preg = calloc(1, sizeof(regex_t));
2106 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2107 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2108 return -1;
2109 }
2110
2111 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2112 if (err) {
2113 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2114 file, linenum, *err);
2115 return -1;
2116 }
2117 }
2118 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2119 regex_t *preg;
2120 if (curproxy == &defproxy) {
2121 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2122 return -1;
2123 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002124 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2125 return 0;
2126
Willy Tarreaubaaee002006-06-26 02:48:02 +02002127 if (*(args[1]) == 0) {
2128 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2129 return -1;
2130 }
2131
2132 preg = calloc(1, sizeof(regex_t));
2133 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2134 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2135 return -1;
2136 }
2137
2138 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2139 if (err) {
2140 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2141 file, linenum, *err);
2142 return -1;
2143 }
2144 }
2145 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2146 regex_t *preg;
2147 if (curproxy == &defproxy) {
2148 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2149 return -1;
2150 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002151 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2152 return 0;
2153
Willy Tarreaubaaee002006-06-26 02:48:02 +02002154 if (*(args[1]) == 0) {
2155 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2156 return -1;
2157 }
2158
2159 preg = calloc(1, sizeof(regex_t));
2160 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2161 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2162 return -1;
2163 }
2164
2165 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2166 if (err) {
2167 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2168 file, linenum, *err);
2169 return -1;
2170 }
2171 }
2172 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2173 regex_t *preg;
2174 if (curproxy == &defproxy) {
2175 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2176 return -1;
2177 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002178 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2179 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002180
2181 if (*(args[1]) == 0 || *(args[2]) == 0) {
2182 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2183 file, linenum, args[0]);
2184 return -1;
2185 }
2186
2187 preg = calloc(1, sizeof(regex_t));
2188 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2189 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2190 return -1;
2191 }
2192
2193 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2194 if (err) {
2195 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2196 file, linenum, *err);
2197 return -1;
2198 }
2199 }
2200 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2201 regex_t *preg;
2202 if (curproxy == &defproxy) {
2203 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2204 return -1;
2205 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002206 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2207 return 0;
2208
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 if (*(args[1]) == 0) {
2210 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2211 return -1;
2212 }
2213
2214 preg = calloc(1, sizeof(regex_t));
2215 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2216 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2217 return -1;
2218 }
2219
2220 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2221 if (err) {
2222 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2223 file, linenum, *err);
2224 return -1;
2225 }
2226 }
2227 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2228 regex_t *preg;
2229 if (curproxy == &defproxy) {
2230 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2231 return -1;
2232 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002233 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2234 return 0;
2235
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 if (*(args[1]) == 0) {
2237 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2238 return -1;
2239 }
2240
2241 preg = calloc(1, sizeof(regex_t));
2242 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2243 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2244 return -1;
2245 }
2246
2247 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2248 if (err) {
2249 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2250 file, linenum, *err);
2251 return -1;
2252 }
2253 }
2254 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2255 if (curproxy == &defproxy) {
2256 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2257 return -1;
2258 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002259 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2260 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261
2262 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2263 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2264 return 0;
2265 }
2266
2267 if (*(args[1]) == 0) {
2268 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2269 return -1;
2270 }
2271
2272 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2273 }
2274 else if (!strcmp(args[0], "errorloc") ||
2275 !strcmp(args[0], "errorloc302") ||
2276 !strcmp(args[0], "errorloc303")) { /* error location */
2277 int errnum, errlen;
2278 char *err;
2279
Willy Tarreau977b8e42006-12-29 14:19:17 +01002280 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2281 return 0;
2282
Willy Tarreaubaaee002006-06-26 02:48:02 +02002283 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002284 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285 return -1;
2286 }
2287
2288 errnum = atol(args[1]);
2289 if (!strcmp(args[0], "errorloc303")) {
2290 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2291 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2292 } else {
2293 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2294 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2295 }
2296
Willy Tarreau0f772532006-12-23 20:51:41 +01002297 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2298 if (http_err_codes[rc] == errnum) {
2299 if (curproxy->errmsg[rc].str)
2300 free(curproxy->errmsg[rc].str);
2301 curproxy->errmsg[rc].str = err;
2302 curproxy->errmsg[rc].len = errlen;
2303 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002304 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002305 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002306
2307 if (rc >= HTTP_ERR_SIZE) {
2308 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2309 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002310 free(err);
2311 }
2312 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002313 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2314 int errnum, errlen, fd;
2315 char *err;
2316 struct stat stat;
2317
2318 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2319 return 0;
2320
2321 if (*(args[2]) == 0) {
2322 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2323 return -1;
2324 }
2325
2326 fd = open(args[2], O_RDONLY);
2327 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2328 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2329 file, linenum, args[2], args[1]);
2330 if (fd >= 0)
2331 close(fd);
2332 return -1;
2333 }
2334
2335 if (stat.st_size <= BUFSIZE) {
2336 errlen = stat.st_size;
2337 } else {
2338 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2339 file, linenum, args[2], BUFSIZE);
2340 errlen = BUFSIZE;
2341 }
2342
2343 err = malloc(errlen); /* malloc() must succeed during parsing */
2344 errnum = read(fd, err, errlen);
2345 if (errnum != errlen) {
2346 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2347 file, linenum, args[2], args[1]);
2348 close(fd);
2349 free(err);
2350 return -1;
2351 }
2352 close(fd);
2353
2354 errnum = atol(args[1]);
2355 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2356 if (http_err_codes[rc] == errnum) {
2357 if (curproxy->errmsg[rc].str)
2358 free(curproxy->errmsg[rc].str);
2359 curproxy->errmsg[rc].str = err;
2360 curproxy->errmsg[rc].len = errlen;
2361 break;
2362 }
2363 }
2364
2365 if (rc >= HTTP_ERR_SIZE) {
2366 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2367 file, linenum, errnum);
2368 free(err);
2369 }
2370 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 else {
2372 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2373 return -1;
2374 }
2375 return 0;
2376}
2377
2378
2379/*
2380 * This function reads and parses the configuration file given in the argument.
2381 * returns 0 if OK, -1 if error.
2382 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002383int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002385 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 FILE *f;
2387 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 int confsect = CFG_NONE;
2390
2391 struct proxy *curproxy = NULL;
2392 struct server *newsrv = NULL;
2393
2394 if ((f=fopen(file,"r")) == NULL)
2395 return -1;
2396
2397 init_default_instance();
2398
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002399 while (fgets(thisline, sizeof(thisline), f) != NULL) {
2400 int arg;
2401 char *end;
2402 char *args[MAX_LINE_ARGS + 1];
2403 char *line = thisline;
2404
Willy Tarreaubaaee002006-06-26 02:48:02 +02002405 linenum++;
2406
2407 end = line + strlen(line);
2408
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002409 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2410 /* Check if we reached the limit and the last char is not \n.
2411 * Watch out for the last line without the terminating '\n'!
2412 */
2413 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2414 file, linenum, sizeof(thisline)-1);
2415 return -1;
2416 }
2417
Willy Tarreaubaaee002006-06-26 02:48:02 +02002418 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002419 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 line++;
2421
2422 arg = 0;
2423 args[arg] = line;
2424
2425 while (*line && arg < MAX_LINE_ARGS) {
2426 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2427 * C equivalent value. Other combinations left unchanged (eg: \1).
2428 */
2429 if (*line == '\\') {
2430 int skip = 0;
2431 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2432 *line = line[1];
2433 skip = 1;
2434 }
2435 else if (line[1] == 'r') {
2436 *line = '\r';
2437 skip = 1;
2438 }
2439 else if (line[1] == 'n') {
2440 *line = '\n';
2441 skip = 1;
2442 }
2443 else if (line[1] == 't') {
2444 *line = '\t';
2445 skip = 1;
2446 }
2447 else if (line[1] == 'x') {
2448 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2449 unsigned char hex1, hex2;
2450 hex1 = toupper(line[2]) - '0';
2451 hex2 = toupper(line[3]) - '0';
2452 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2453 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2454 *line = (hex1<<4) + hex2;
2455 skip = 3;
2456 }
2457 else {
2458 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2459 return -1;
2460 }
2461 }
2462 if (skip) {
2463 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2464 end -= skip;
2465 }
2466 line++;
2467 }
2468 else if (*line == '#' || *line == '\n' || *line == '\r') {
2469 /* end of string, end of loop */
2470 *line = 0;
2471 break;
2472 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002473 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002475 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002476 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 line++;
2478 args[++arg] = line;
2479 }
2480 else {
2481 line++;
2482 }
2483 }
2484
2485 /* empty line */
2486 if (!**args)
2487 continue;
2488
Willy Tarreau540abe42007-05-02 20:50:16 +02002489 /* zero out remaining args and ensure that at least one entry
2490 * is zeroed out.
2491 */
2492 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002493 args[arg] = line;
2494 }
2495
Willy Tarreau977b8e42006-12-29 14:19:17 +01002496 if (!strcmp(args[0], "listen") ||
2497 !strcmp(args[0], "frontend") ||
2498 !strcmp(args[0], "backend") ||
2499 !strcmp(args[0], "ruleset") ||
2500 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 confsect = CFG_LISTEN;
2502 else if (!strcmp(args[0], "global")) /* global config */
2503 confsect = CFG_GLOBAL;
2504 /* else it's a section keyword */
2505
2506 switch (confsect) {
2507 case CFG_LISTEN:
2508 if (cfg_parse_listen(file, linenum, args) < 0)
2509 return -1;
2510 break;
2511 case CFG_GLOBAL:
2512 if (cfg_parse_global(file, linenum, args) < 0)
2513 return -1;
2514 break;
2515 default:
2516 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2517 return -1;
2518 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002519 }
2520 fclose(f);
2521
2522 /*
2523 * Now, check for the integrity of all that we have collected.
2524 */
2525
2526 /* will be needed further to delay some tasks */
2527 tv_now(&now);
2528
2529 if ((curproxy = proxy) == NULL) {
2530 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2531 file);
2532 return -1;
2533 }
2534
2535 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002536 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002537 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002538
Willy Tarreaubaaee002006-06-26 02:48:02 +02002539 if (curproxy->state == PR_STSTOPPED) {
2540 curproxy = curproxy->next;
2541 continue;
2542 }
2543
Willy Tarreau977b8e42006-12-29 14:19:17 +01002544 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2545 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 +01002546 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 cfgerr++;
2548 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002549 else if (curproxy->cap & PR_CAP_BE &&
2550 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002551 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002552 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002553 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2554 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 +01002555 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 cfgerr++;
2557 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002558
Willy Tarreau31682232007-11-29 15:38:04 +01002559 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002561 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002562 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 cfgerr++;
2564 }
2565#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2566 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002567 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002568 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 cfgerr++;
2570 }
2571#endif
2572 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002573 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002574 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 }
2576 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002577
2578 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002580 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002581 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002584 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002585 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 }
2587 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002588 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002589 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002591 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002592 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002593 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002594 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002595 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002596 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2597 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002598
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002599 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002600 file, proxy_type_str(curproxy), curproxy->id);
2601 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002603
2604 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2605 if ((newsrv = curproxy->srv) != NULL) {
2606 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2607 file, proxy_type_str(curproxy), curproxy->id);
2608 }
2609 }
2610
2611 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2613 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2614 file, curproxy->id);
2615 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002616 }
2617 }
2618
Willy Tarreau82936582007-11-30 15:20:09 +01002619 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2620 curproxy->options &= ~PR_O_DISABLE404;
2621 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2622 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2623 }
2624
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002625 /* if a default backend was specified, let's find it */
2626 if (curproxy->defbe.name) {
2627 struct proxy *target;
2628
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002629 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2630 if (!target) {
2631 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2632 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002633 cfgerr++;
2634 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002635 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2636 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002637 } else {
2638 free(curproxy->defbe.name);
2639 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002640 }
2641 }
2642
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002643 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002644 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2645 /* map jump target for ACT_SETBE in req_rep chain */
2646 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002647 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002648 struct proxy *target;
2649
Willy Tarreaua496b602006-12-17 23:15:24 +01002650 if (exp->action != ACT_SETBE)
2651 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002652
2653 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2654 if (!target) {
2655 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2656 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002657 cfgerr++;
2658 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002659 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2660 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002661 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002662 } else {
2663 free((void *)exp->replace);
2664 exp->replace = (const char *)target;
2665 }
2666 }
2667 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002668
2669 /* find the target proxy for 'use_backend' rules */
2670 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002671 struct proxy *target;
2672
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002673 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002674
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002675 if (!target) {
2676 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2677 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002678 cfgerr++;
2679 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002680 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2681 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002682 cfgerr++;
2683 } else {
2684 free((void *)rule->be.name);
2685 rule->be.backend = target;
2686 }
2687 }
2688
Willy Tarreau2738a142006-07-08 17:28:09 +02002689 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002690 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2691 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2692 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002693 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002694 " | While not properly invalid, you will certainly encounter various problems\n"
2695 " | with such a configuration. To fix this, please ensure that all following\n"
2696 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002697 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002698 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002699
2700 if (curproxy->options & PR_O_SSL3_CHK) {
2701 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2702 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2703 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2704 }
2705
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002706 /* The small pools required for the capture lists */
2707 if (curproxy->nb_req_cap)
2708 curproxy->req_cap_pool = create_pool("ptrcap",
2709 curproxy->nb_req_cap * sizeof(char *),
2710 MEM_F_SHARED);
2711 if (curproxy->nb_rsp_cap)
2712 curproxy->rsp_cap_pool = create_pool("ptrcap",
2713 curproxy->nb_rsp_cap * sizeof(char *),
2714 MEM_F_SHARED);
2715
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002716 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2717 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2718 MEM_F_SHARED);
2719
Willy Tarreau86034312006-12-29 00:10:33 +01002720 /* for backwards compatibility with "listen" instances, if
2721 * fullconn is not set but maxconn is set, then maxconn
2722 * is used.
2723 */
2724 if (!curproxy->fullconn)
2725 curproxy->fullconn = curproxy->maxconn;
2726
Willy Tarreaubaaee002006-06-26 02:48:02 +02002727 /* first, we will invert the servers list order */
2728 newsrv = NULL;
2729 while (curproxy->srv) {
2730 struct server *next;
2731
2732 next = curproxy->srv->next;
2733 curproxy->srv->next = newsrv;
2734 newsrv = curproxy->srv;
2735 if (!next)
2736 break;
2737 curproxy->srv = next;
2738 }
2739
Willy Tarreau20697042007-11-15 23:26:18 +01002740 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01002741 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742
Willy Tarreaub625a082007-11-26 01:15:43 +01002743 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01002744 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01002745 fwrr_init_server_groups(curproxy);
2746 else
2747 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748
2749 if (curproxy->options & PR_O_LOGASAP)
2750 curproxy->to_log &= ~LW_BYTES;
2751
Willy Tarreaubaaee002006-06-26 02:48:02 +02002752 /*
2753 * If this server supports a maxconn parameter, it needs a dedicated
2754 * tasks to fill the emptied slots when a connection leaves.
2755 */
2756 newsrv = curproxy->srv;
2757 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002758 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 /* Only 'minconn' was specified, or it was higher than or equal
2760 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2761 * this will avoid further useless expensive computations.
2762 */
2763 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002764 } else if (newsrv->maxconn && !newsrv->minconn) {
2765 /* minconn was not specified, so we set it to maxconn */
2766 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002767 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2768 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002769 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002770 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002771 }
2772
2773 if (newsrv->maxconn > 0) {
2774 struct task *t;
2775
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002776 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002777 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2778 return -1;
2779 }
2780
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002781 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002782 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 t->state = TASK_IDLE;
2784 t->process = process_srv_queue;
2785 t->context = newsrv;
2786 newsrv->queue_mgt = t;
2787
2788 /* never run it unless specifically woken up */
2789 tv_eternity(&t->expire);
2790 task_queue(t);
2791 }
2792 newsrv = newsrv->next;
2793 }
2794
Willy Tarreaue6b98942007-10-29 01:09:36 +01002795 /* adjust this proxy's listeners */
2796 listener = curproxy->listen;
2797 while (listener) {
2798 if (curproxy->options & PR_O_TCP_NOLING)
2799 listener->options |= LI_O_NOLINGER;
2800 listener->maxconn = curproxy->maxconn;
2801 listener->timeout = &curproxy->clitimeout;
2802 listener->accept = event_accept;
2803 listener->private = curproxy;
2804
2805 listener = listener->next;
2806 }
2807
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808 curproxy = curproxy->next;
2809 }
2810 if (cfgerr > 0) {
2811 Alert("Errors found in configuration file, aborting.\n");
2812 return -1;
2813 }
2814 else
2815 return 0;
2816}
2817
2818
2819
2820/*
2821 * Local variables:
2822 * c-indent-level: 8
2823 * c-basic-offset: 8
2824 * End:
2825 */