blob: 9610cf4c3d352339dfa83ee673301126d73121ea [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 */
Robert Tsai81ae1952007-12-05 10:47:29 +0100428 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200429 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
Robert Tsai81ae1952007-12-05 10:47:29 +0100451 if (args[1][0] == '/') {
452 logsrv.u.addr.sa_family = AF_UNIX;
453 logsrv.u.un = *str2sun(args[1]);
454 } else {
455 logsrv.u.addr.sa_family = AF_INET;
456 logsrv.u.in = *str2sa(args[1]);
457 if (!logsrv.u.in.sin_port)
458 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460
461 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100462 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463 global.logfac1 = facility;
464 global.loglev1 = level;
465 }
466 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100467 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468 global.logfac2 = facility;
469 global.loglev2 = level;
470 }
471 else {
472 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
473 return -1;
474 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200475 }
476 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
477 if (global.spread_checks != 0) {
478 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
479 return 0;
480 }
481 if (*(args[1]) == 0) {
482 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
483 return -1;
484 }
485 global.spread_checks = atol(args[1]);
486 if (global.spread_checks < 0 || global.spread_checks > 50) {
487 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
488 return -1;
489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200490 }
491 else {
492 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
493 return -1;
494 }
495 return 0;
496}
497
498
499static void init_default_instance()
500{
501 memset(&defproxy, 0, sizeof(defproxy));
502 defproxy.mode = PR_MODE_TCP;
503 defproxy.state = PR_STNEW;
504 defproxy.maxconn = cfg_maxpconn;
505 defproxy.conn_retries = CONN_RETRIES;
506 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100507 tv_eternity(&defproxy.timeout.client);
508 tv_eternity(&defproxy.timeout.connect);
509 tv_eternity(&defproxy.timeout.server);
510 tv_eternity(&defproxy.timeout.appsession);
Willy Tarreau1fa31262007-12-03 00:36:16 +0100511 tv_eternity(&defproxy.timeout.queue);
512 tv_eternity(&defproxy.timeout.tarpit);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200513}
514
515/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100516 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
517 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200519int cfg_parse_listen(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520{
521 static struct proxy *curproxy = NULL;
522 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200523 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100524 int rc;
525 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200526
Willy Tarreau977b8e42006-12-29 14:19:17 +0100527 if (!strcmp(args[0], "listen"))
528 rc = PR_CAP_LISTEN;
529 else if (!strcmp(args[0], "frontend"))
530 rc = PR_CAP_FE | PR_CAP_RS;
531 else if (!strcmp(args[0], "backend"))
532 rc = PR_CAP_BE | PR_CAP_RS;
533 else if (!strcmp(args[0], "ruleset"))
534 rc = PR_CAP_RS;
535 else
536 rc = PR_CAP_NONE;
537
538 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200539 if (!*args[1]) {
540 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
541 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
542 file, linenum, args[0]);
543 return -1;
544 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200545
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100546 err = invalid_char(args[1]);
547 if (err) {
548 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
549 file, linenum, *err, args[0], args[1]);
550 return -1;
551 }
552
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200553 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
554 /*
555 * If there are two proxies with the same name only following
556 * combinations are allowed:
557 *
558 * listen backend frontend ruleset
559 * listen - - - -
560 * backend - - OK -
561 * frontend - OK - -
562 * ruleset - - - -
563 */
564
565 if (!strcmp(curproxy->id, args[1]) &&
566 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
567 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100568 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
569 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200570 }
571 }
572
Willy Tarreaubaaee002006-06-26 02:48:02 +0200573 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
574 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
575 return -1;
576 }
577
578 curproxy->next = proxy;
579 proxy = curproxy;
580 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200581 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200582 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100583 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200584 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585
Willy Tarreauee991362007-05-14 14:37:50 +0200586 /* Timeouts are defined as -1, so we cannot use the zeroed area
587 * as a default value.
588 */
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100589 tv_eternity(&curproxy->timeout.client);
590 tv_eternity(&curproxy->timeout.server);
591 tv_eternity(&curproxy->timeout.connect);
592 tv_eternity(&curproxy->timeout.appsession);
Willy Tarreau1fa31262007-12-03 00:36:16 +0100593 tv_eternity(&curproxy->timeout.queue);
594 tv_eternity(&curproxy->timeout.tarpit);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200595
596 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200597 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100598 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599
600 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100601 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 curproxy->listen = str2listener(args[2], curproxy->listen);
603 if (!curproxy->listen)
604 return -1;
605 global.maxsock++;
606 }
607
608 /* set default values */
609 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100611 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200612 curproxy->except_net = defproxy.except_net;
613 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200614
Willy Tarreau977b8e42006-12-29 14:19:17 +0100615 if (curproxy->cap & PR_CAP_FE) {
616 curproxy->maxconn = defproxy.maxconn;
617
618 /* initialize error relocations */
619 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
620 if (defproxy.errmsg[rc].str)
621 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
622 }
623
624 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626
Willy Tarreau977b8e42006-12-29 14:19:17 +0100627 if (curproxy->cap & PR_CAP_BE) {
628 curproxy->fullconn = defproxy.fullconn;
629 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630
Willy Tarreau977b8e42006-12-29 14:19:17 +0100631 if (defproxy.check_req)
632 curproxy->check_req = strdup(defproxy.check_req);
633 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634
Willy Tarreau977b8e42006-12-29 14:19:17 +0100635 if (defproxy.cookie_name)
636 curproxy->cookie_name = strdup(defproxy.cookie_name);
637 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100638
639 if (defproxy.url_param_name)
640 curproxy->url_param_name = strdup(defproxy.url_param_name);
641 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100642 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200643
Willy Tarreau977b8e42006-12-29 14:19:17 +0100644 if (curproxy->cap & PR_CAP_RS) {
645 if (defproxy.capture_name)
646 curproxy->capture_name = strdup(defproxy.capture_name);
647 curproxy->capture_namelen = defproxy.capture_namelen;
648 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200650
Willy Tarreau977b8e42006-12-29 14:19:17 +0100651 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100652 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100653 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100654 curproxy->uri_auth = defproxy.uri_auth;
655 curproxy->mon_net = defproxy.mon_net;
656 curproxy->mon_mask = defproxy.mon_mask;
657 if (defproxy.monitor_uri)
658 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
659 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100660 if (defproxy.defbe.name)
661 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100662 }
663
664 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100665 curproxy->timeout.connect = defproxy.timeout.connect;
666 curproxy->timeout.server = defproxy.timeout.server;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100667 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100668 curproxy->source_addr = defproxy.source_addr;
669 }
670
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671 curproxy->mode = defproxy.mode;
672 curproxy->logfac1 = defproxy.logfac1;
673 curproxy->logsrv1 = defproxy.logsrv1;
674 curproxy->loglev1 = defproxy.loglev1;
675 curproxy->logfac2 = defproxy.logfac2;
676 curproxy->logsrv2 = defproxy.logsrv2;
677 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200678 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100679 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
680 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200681
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 return 0;
683 }
684 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
685 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100686 /* FIXME-20070101: we should do this too at the end of the
687 * config parsing to free all default values.
688 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200689 if (defproxy.check_req) free(defproxy.check_req);
690 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100691 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200693 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100694 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100695
696 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
697 if (defproxy.errmsg[rc].len)
698 free(defproxy.errmsg[rc].str);
699 }
700
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 /* we cannot free uri_auth because it might already be used */
702 init_default_instance();
703 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100704 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200705 return 0;
706 }
707 else if (curproxy == NULL) {
708 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
709 return -1;
710 }
711
Willy Tarreau977b8e42006-12-29 14:19:17 +0100712
713 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714 if (!strcmp(args[0], "bind")) { /* new listen addresses */
715 if (curproxy == &defproxy) {
716 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
717 return -1;
718 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100719 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
720 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721
722 if (strchr(args[1], ':') == NULL) {
723 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
724 file, linenum, args[0]);
725 return -1;
726 }
727 curproxy->listen = str2listener(args[1], curproxy->listen);
728 if (!curproxy->listen)
729 return -1;
730 global.maxsock++;
731 return 0;
732 }
733 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
734 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
735 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
736 file, linenum, args[0]);
737 return -1;
738 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100739 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
740 return 0;
741
Willy Tarreaubaaee002006-06-26 02:48:02 +0200742 /* flush useless bits */
743 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
744 return 0;
745 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200746 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100747 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
748 return 0;
749
Willy Tarreau1c47f852006-07-09 08:22:27 +0200750 if (!*args[1]) {
751 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
752 file, linenum, args[0]);
753 return -1;
754 }
755
756 if (curproxy->monitor_uri != NULL)
757 free(curproxy->monitor_uri);
758
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100759 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200760 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100761 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200762 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
763
764 return 0;
765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200766 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
767 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
768 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
769 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
770 else {
771 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
772 return -1;
773 }
774 }
775 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
776 curproxy->state = PR_STSTOPPED;
777 }
778 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
779 curproxy->state = PR_STNEW;
780 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200781 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100782 err = invalid_char(args[1]);
783 if (err) {
784 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
785 file, linenum, *err, args[1]);
786 return -1;
787 }
788
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200789 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
790 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
791 file, linenum, args[1]);
792 return -1;
793 }
794 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200795 else if (!strcmp(args[0], "cookie")) { /* cookie name */
796 int cur_arg;
797 // if (curproxy == &defproxy) {
798 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
799 // return -1;
800 // }
801
Willy Tarreau977b8e42006-12-29 14:19:17 +0100802 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
803 return 0;
804
Willy Tarreaubaaee002006-06-26 02:48:02 +0200805 if (curproxy->cookie_name != NULL) {
806 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
807 // file, linenum);
808 // return 0;
809 free(curproxy->cookie_name);
810 }
811
812 if (*(args[1]) == 0) {
813 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
814 file, linenum, args[0]);
815 return -1;
816 }
817 curproxy->cookie_name = strdup(args[1]);
818 curproxy->cookie_len = strlen(curproxy->cookie_name);
819
820 cur_arg = 2;
821 while (*(args[cur_arg])) {
822 if (!strcmp(args[cur_arg], "rewrite")) {
823 curproxy->options |= PR_O_COOK_RW;
824 }
825 else if (!strcmp(args[cur_arg], "indirect")) {
826 curproxy->options |= PR_O_COOK_IND;
827 }
828 else if (!strcmp(args[cur_arg], "insert")) {
829 curproxy->options |= PR_O_COOK_INS;
830 }
831 else if (!strcmp(args[cur_arg], "nocache")) {
832 curproxy->options |= PR_O_COOK_NOC;
833 }
834 else if (!strcmp(args[cur_arg], "postonly")) {
835 curproxy->options |= PR_O_COOK_POST;
836 }
837 else if (!strcmp(args[cur_arg], "prefix")) {
838 curproxy->options |= PR_O_COOK_PFX;
839 }
840 else {
841 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
842 file, linenum, args[0]);
843 return -1;
844 }
845 cur_arg++;
846 }
847 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
848 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
849 file, linenum);
850 return -1;
851 }
852
853 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
854 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
855 file, linenum);
856 return -1;
857 }
858 }/* end else if (!strcmp(args[0], "cookie")) */
859 else if (!strcmp(args[0], "appsession")) { /* cookie name */
860 // if (curproxy == &defproxy) {
861 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
862 // return -1;
863 // }
864
Willy Tarreau977b8e42006-12-29 14:19:17 +0100865 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
866 return 0;
867
Willy Tarreaubaaee002006-06-26 02:48:02 +0200868 if (curproxy->appsession_name != NULL) {
869 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
870 // file, linenum);
871 // return 0;
872 free(curproxy->appsession_name);
873 }
874
875 if (*(args[5]) == 0) {
876 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
877 file, linenum, args[0]);
878 return -1;
879 }
880 have_appsession = 1;
881 curproxy->appsession_name = strdup(args[1]);
882 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
883 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100884 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
885 if (err) {
886 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
887 file, linenum, *err, args[0]);
888 return -1;
889 }
Willy Tarreauee991362007-05-14 14:37:50 +0200890 if (val > 0)
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100891 __tv_from_ms(&curproxy->timeout.appsession, val);
Willy Tarreauee991362007-05-14 14:37:50 +0200892 else
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100893 tv_eternity(&curproxy->timeout.appsession);
Willy Tarreauee991362007-05-14 14:37:50 +0200894
Willy Tarreau51041c72007-09-09 21:56:53 +0200895 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
896 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897 return -1;
898 }
899 } /* Url App Session */
900 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100901 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
902 return 0;
903
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
905 // if (curproxy == &defproxy) {
906 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
907 // return -1;
908 // }
909
910 if (curproxy->capture_name != NULL) {
911 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
912 // file, linenum, args[0]);
913 // return 0;
914 free(curproxy->capture_name);
915 }
916
917 if (*(args[4]) == 0) {
918 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
919 file, linenum, args[0]);
920 return -1;
921 }
922 curproxy->capture_name = strdup(args[2]);
923 curproxy->capture_namelen = strlen(curproxy->capture_name);
924 curproxy->capture_len = atol(args[4]);
925 if (curproxy->capture_len >= CAPTURE_LEN) {
926 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
927 file, linenum, CAPTURE_LEN - 1);
928 curproxy->capture_len = CAPTURE_LEN - 1;
929 }
930 curproxy->to_log |= LW_COOKIE;
931 }
932 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
933 struct cap_hdr *hdr;
934
935 if (curproxy == &defproxy) {
936 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
937 return -1;
938 }
939
940 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
941 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
942 file, linenum, args[0], args[1]);
943 return -1;
944 }
945
946 hdr = calloc(sizeof(struct cap_hdr), 1);
947 hdr->next = curproxy->req_cap;
948 hdr->name = strdup(args[3]);
949 hdr->namelen = strlen(args[3]);
950 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200951 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 hdr->index = curproxy->nb_req_cap++;
953 curproxy->req_cap = hdr;
954 curproxy->to_log |= LW_REQHDR;
955 }
956 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
957 struct cap_hdr *hdr;
958
959 if (curproxy == &defproxy) {
960 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
961 return -1;
962 }
963
964 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
965 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
966 file, linenum, args[0], args[1]);
967 return -1;
968 }
969 hdr = calloc(sizeof(struct cap_hdr), 1);
970 hdr->next = curproxy->rsp_cap;
971 hdr->name = strdup(args[3]);
972 hdr->namelen = strlen(args[3]);
973 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200974 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200975 hdr->index = curproxy->nb_rsp_cap++;
976 curproxy->rsp_cap = hdr;
977 curproxy->to_log |= LW_RSPHDR;
978 }
979 else {
980 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
981 file, linenum, args[0]);
982 return -1;
983 }
984 }
Willy Tarreaue219db72007-12-03 01:30:13 +0100985 else if (!strcmp(args[0], "contimeout") || !strcmp(args[0], "clitimeout") ||
986 !strcmp(args[0], "srvtimeout") || !strcmp(args[0], "timeout")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100987
Willy Tarreaue219db72007-12-03 01:30:13 +0100988 /* either we have {con|srv|cli}timeout <value> or we have the
989 * new form: timeout <type> <value>. The parser needs the word
990 * preceeding the value.
991 */
992 const char **start_arg = (const char **)args;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100993
Willy Tarreaue219db72007-12-03 01:30:13 +0100994 if (strcmp(args[0], "timeout") == 0)
995 start_arg++;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100996
Willy Tarreaue219db72007-12-03 01:30:13 +0100997 snprintf(trash, sizeof(trash), "error near '%s'", args[0]);
998 rc = proxy_parse_timeout(start_arg, curproxy, &defproxy, trash, sizeof(trash));
999 if (rc < 0) {
1000 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001001 return -1;
1002 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001003 if (rc > 0)
1004 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005 }
1006 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001007 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1008 return 0;
1009
Willy Tarreaubaaee002006-06-26 02:48:02 +02001010 if (*(args[1]) == 0) {
1011 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1012 file, linenum, args[0]);
1013 return -1;
1014 }
1015 curproxy->conn_retries = atol(args[1]);
1016 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001017 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1018 int pol = ACL_COND_NONE;
1019 struct acl_cond *cond;
1020
1021 if (!strcmp(args[1], "if"))
1022 pol = ACL_COND_IF;
1023 else if (!strcmp(args[1], "unless"))
1024 pol = ACL_COND_UNLESS;
1025
1026 if (pol == ACL_COND_NONE) {
1027 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1028 file, linenum, args[0]);
1029 return -1;
1030 }
1031
1032 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1033 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1034 file, linenum);
1035 return -1;
1036 }
1037 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1038 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001039 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1040 int pol = ACL_COND_NONE;
1041 struct acl_cond *cond;
1042 struct switching_rule *rule;
1043
1044 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1045 return 0;
1046
1047 if (*(args[1]) == 0) {
1048 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1049 return -1;
1050 }
1051
1052 if (!strcmp(args[2], "if"))
1053 pol = ACL_COND_IF;
1054 else if (!strcmp(args[2], "unless"))
1055 pol = ACL_COND_UNLESS;
1056
1057 if (pol == ACL_COND_NONE) {
1058 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1059 file, linenum, args[0]);
1060 return -1;
1061 }
1062
1063 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1064 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1065 file, linenum);
1066 return -1;
1067 }
1068
1069 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1070 rule->cond = cond;
1071 rule->be.name = strdup(args[1]);
1072 LIST_INIT(&rule->list);
1073 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1074 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001075 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001076 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1077 return 0;
1078
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1080 curproxy->uri_auth = NULL; /* we must detach from the default config */
1081
1082 if (*(args[1]) == 0) {
1083 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1084 return -1;
1085 } else if (!strcmp(args[1], "uri")) {
1086 if (*(args[2]) == 0) {
1087 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1088 return -1;
1089 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1090 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1091 return -1;
1092 }
1093 } else if (!strcmp(args[1], "realm")) {
1094 if (*(args[2]) == 0) {
1095 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1096 return -1;
1097 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1098 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1099 return -1;
1100 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001101 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001102 unsigned interval;
1103
1104 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1105 if (err) {
1106 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1107 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001108 return -1;
1109 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1110 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1111 return -1;
1112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001113 } else if (!strcmp(args[1], "auth")) {
1114 if (*(args[2]) == 0) {
1115 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1116 return -1;
1117 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1118 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1119 return -1;
1120 }
1121 } else if (!strcmp(args[1], "scope")) {
1122 if (*(args[2]) == 0) {
1123 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1124 return -1;
1125 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1126 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1127 return -1;
1128 }
1129 } else if (!strcmp(args[1], "enable")) {
1130 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1131 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1132 return -1;
1133 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001134 } else if (!strcmp(args[1], "hide-version")) {
1135 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1136 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1137 return -1;
1138 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001139 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001140 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 file, linenum, args[0]);
1142 return -1;
1143 }
1144 }
1145 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001146 int optnum;
1147
Willy Tarreaubaaee002006-06-26 02:48:02 +02001148 if (*(args[1]) == 0) {
1149 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
1150 return -1;
1151 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001152
1153 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1154 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1155 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1156 return 0;
1157 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001158 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001159 return 0;
1160 }
1161 }
1162
1163 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001164 /* generate a complete HTTP log */
1165 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1166 else if (!strcmp(args[1], "tcplog"))
1167 /* generate a detailed TCP log */
1168 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169 else if (!strcmp(args[1], "tcpka")) {
1170 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001171 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1172 return 0;
1173
1174 if (curproxy->cap & PR_CAP_FE)
1175 curproxy->options |= PR_O_TCP_CLI_KA;
1176 if (curproxy->cap & PR_CAP_BE)
1177 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178 }
1179 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001180 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1181 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182 /* use HTTP request to check servers' health */
1183 if (curproxy->check_req != NULL) {
1184 free(curproxy->check_req);
1185 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001186 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001187 curproxy->options &= ~PR_O_SMTP_CHK;
1188 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001189 if (!*args[2]) { /* no argument */
1190 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1191 curproxy->check_len = strlen(DEF_CHECK_REQ);
1192 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001193 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001194 curproxy->check_req = (char *)malloc(reqlen);
1195 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1196 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1197 } else { /* more arguments : METHOD URI [HTTP_VER] */
1198 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1199 if (*args[4])
1200 reqlen += strlen(args[4]);
1201 else
1202 reqlen += strlen("HTTP/1.0");
1203
1204 curproxy->check_req = (char *)malloc(reqlen);
1205 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1206 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1207 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001208 }
1209 else if (!strcmp(args[1], "ssl-hello-chk")) {
1210 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001211 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1212 return 0;
1213
Willy Tarreauf3c69202006-07-09 16:42:34 +02001214 if (curproxy->check_req != NULL) {
1215 free(curproxy->check_req);
1216 }
1217 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001218 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001219 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001220 }
Willy Tarreau23677902007-05-08 23:50:35 +02001221 else if (!strcmp(args[1], "smtpchk")) {
1222 /* use SMTP request to check servers' health */
1223 if (curproxy->check_req != NULL) {
1224 free(curproxy->check_req);
1225 }
1226 curproxy->options &= ~PR_O_HTTP_CHK;
1227 curproxy->options &= ~PR_O_SSL3_CHK;
1228 curproxy->options |= PR_O_SMTP_CHK;
1229
1230 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1231 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1232 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1233 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1234 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1235 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1236 curproxy->check_req = (char *)malloc(reqlen);
1237 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1238 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1239 } else {
1240 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1241 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1242 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1243 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1244 }
1245 }
1246 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001247 else if (!strcmp(args[1], "forwardfor")) {
1248 /* insert x-forwarded-for field, but not for the
1249 * IP address listed as an except.
1250 */
1251 if (*(args[2])) {
1252 if (!strcmp(args[2], "except")) {
1253 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1254 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1255 file, linenum, args[0]);
1256 return -1;
1257 }
1258 /* flush useless bits */
1259 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1260 } else {
1261 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1262 file, linenum, args[0]);
1263 return -1;
1264 }
1265 }
1266 curproxy->options |= PR_O_FWDFOR;
1267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001268 else {
1269 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1270 return -1;
1271 }
1272 return 0;
1273 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001274 else if (!strcmp(args[0], "default_backend")) {
1275 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1276 return 0;
1277
1278 if (*(args[1]) == 0) {
1279 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1280 return -1;
1281 }
1282 if (curproxy->defbe.name)
1283 free(curproxy->defbe.name);
1284 curproxy->defbe.name = strdup(args[1]);
1285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001286 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001287 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1288 return 0;
1289
Willy Tarreaubaaee002006-06-26 02:48:02 +02001290 /* enable reconnections to dispatch */
1291 curproxy->options |= PR_O_REDISP;
1292 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001293 else if (!strcmp(args[0], "http-check")) {
1294 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1295 return 0;
1296
1297 if (strcmp(args[1], "disable-on-404") == 0) {
1298 /* enable a graceful server shutdown on an HTTP 404 response */
1299 curproxy->options |= PR_O_DISABLE404;
1300 }
1301 else {
1302 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1303 return -1;
1304 }
1305 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001306 else if (!strcmp(args[0], "monitor")) {
1307 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1308 return 0;
1309
1310 if (strcmp(args[1], "fail") == 0) {
1311 /* add a condition to fail monitor requests */
1312 int pol = ACL_COND_NONE;
1313 struct acl_cond *cond;
1314
1315 if (!strcmp(args[2], "if"))
1316 pol = ACL_COND_IF;
1317 else if (!strcmp(args[2], "unless"))
1318 pol = ACL_COND_UNLESS;
1319
1320 if (pol == ACL_COND_NONE) {
1321 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1322 file, linenum, args[0], args[1]);
1323 return -1;
1324 }
1325
1326 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1327 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1328 file, linenum, args[0], args[1]);
1329 return -1;
1330 }
1331 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1332 }
1333 else {
1334 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1335 return -1;
1336 }
1337 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338#ifdef TPROXY
1339 else if (!strcmp(args[0], "transparent")) {
1340 /* enable transparent proxy connections */
1341 curproxy->options |= PR_O_TRANSP;
1342 }
1343#endif
1344 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001345 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1346 return 0;
1347
Willy Tarreaubaaee002006-06-26 02:48:02 +02001348 if (*(args[1]) == 0) {
1349 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1350 return -1;
1351 }
1352 curproxy->maxconn = atol(args[1]);
1353 }
Willy Tarreau86034312006-12-29 00:10:33 +01001354 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001355 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1356 return 0;
1357
Willy Tarreau86034312006-12-29 00:10:33 +01001358 if (*(args[1]) == 0) {
1359 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1360 return -1;
1361 }
1362 curproxy->fullconn = atol(args[1]);
1363 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001364 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1365 if (*(args[1]) == 0) {
1366 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1367 return -1;
1368 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001369 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1370 if (err) {
1371 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1372 file, linenum, *err);
1373 return -1;
1374 }
1375 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 }
1377 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1378 if (curproxy == &defproxy) {
1379 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1380 return -1;
1381 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001382 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1383 return 0;
1384
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 if (strchr(args[1], ':') == NULL) {
1386 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1387 return -1;
1388 }
1389 curproxy->dispatch_addr = *str2sa(args[1]);
1390 }
1391 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001392 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1393 return 0;
1394
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001395 memcpy(trash, "error near 'balance'", 19);
1396 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1397 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1398 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001399 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 }
1401 else if (!strcmp(args[0], "server")) { /* server address */
1402 int cur_arg;
1403 char *rport;
1404 char *raddr;
1405 short realport;
1406 int do_check;
1407
1408 if (curproxy == &defproxy) {
1409 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1410 return -1;
1411 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001412 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1413 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414
1415 if (!*args[2]) {
1416 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1417 file, linenum, args[0]);
1418 return -1;
1419 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001420
1421 err = invalid_char(args[1]);
1422 if (err) {
1423 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1424 file, linenum, *err, args[1]);
1425 return -1;
1426 }
1427
Willy Tarreaubaaee002006-06-26 02:48:02 +02001428 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1429 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1430 return -1;
1431 }
1432
1433 /* the servers are linked backwards first */
1434 newsrv->next = curproxy->srv;
1435 curproxy->srv = newsrv;
1436 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001437 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438
1439 LIST_INIT(&newsrv->pendconns);
1440 do_check = 0;
1441 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001442 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001443 newsrv->id = strdup(args[1]);
1444
1445 /* several ways to check the port component :
1446 * - IP => port=+0, relative
1447 * - IP: => port=+0, relative
1448 * - IP:N => port=N, absolute
1449 * - IP:+N => port=+N, relative
1450 * - IP:-N => port=-N, relative
1451 */
1452 raddr = strdup(args[2]);
1453 rport = strchr(raddr, ':');
1454 if (rport) {
1455 *rport++ = 0;
1456 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001457 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001458 newsrv->state |= SRV_MAPPORTS;
1459 } else {
1460 realport = 0;
1461 newsrv->state |= SRV_MAPPORTS;
1462 }
1463
1464 newsrv->addr = *str2sa(raddr);
1465 newsrv->addr.sin_port = htons(realport);
1466 free(raddr);
1467
1468 newsrv->curfd = -1; /* no health-check in progress */
1469 newsrv->inter = DEF_CHKINTR;
1470 newsrv->rise = DEF_RISETIME;
1471 newsrv->fall = DEF_FALLTIME;
1472 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001473 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001474 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001475 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001476
Willy Tarreaubaaee002006-06-26 02:48:02 +02001477 cur_arg = 3;
1478 while (*args[cur_arg]) {
1479 if (!strcmp(args[cur_arg], "cookie")) {
1480 newsrv->cookie = strdup(args[cur_arg + 1]);
1481 newsrv->cklen = strlen(args[cur_arg + 1]);
1482 cur_arg += 2;
1483 }
1484 else if (!strcmp(args[cur_arg], "rise")) {
1485 newsrv->rise = atol(args[cur_arg + 1]);
1486 newsrv->health = newsrv->rise;
1487 cur_arg += 2;
1488 }
1489 else if (!strcmp(args[cur_arg], "fall")) {
1490 newsrv->fall = atol(args[cur_arg + 1]);
1491 cur_arg += 2;
1492 }
1493 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001494 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1495 if (err) {
1496 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1497 file, linenum, *err, newsrv->id);
1498 return -1;
1499 }
1500 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001501 cur_arg += 2;
1502 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001503 else if (!strcmp(args[cur_arg], "addr")) {
1504 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001505 cur_arg += 2;
1506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001507 else if (!strcmp(args[cur_arg], "port")) {
1508 newsrv->check_port = atol(args[cur_arg + 1]);
1509 cur_arg += 2;
1510 }
1511 else if (!strcmp(args[cur_arg], "backup")) {
1512 newsrv->state |= SRV_BACKUP;
1513 cur_arg ++;
1514 }
1515 else if (!strcmp(args[cur_arg], "weight")) {
1516 int w;
1517 w = atol(args[cur_arg + 1]);
1518 if (w < 1 || w > 256) {
1519 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1520 file, linenum, newsrv->id, w);
1521 return -1;
1522 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001523 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001524 cur_arg += 2;
1525 }
1526 else if (!strcmp(args[cur_arg], "minconn")) {
1527 newsrv->minconn = atol(args[cur_arg + 1]);
1528 cur_arg += 2;
1529 }
1530 else if (!strcmp(args[cur_arg], "maxconn")) {
1531 newsrv->maxconn = atol(args[cur_arg + 1]);
1532 cur_arg += 2;
1533 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001534 else if (!strcmp(args[cur_arg], "maxqueue")) {
1535 newsrv->maxqueue = atol(args[cur_arg + 1]);
1536 cur_arg += 2;
1537 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001538 else if (!strcmp(args[cur_arg], "slowstart")) {
1539 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001540 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001541 if (err) {
1542 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1543 file, linenum, *err, newsrv->id);
1544 return -1;
1545 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001546 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001547 cur_arg += 2;
1548 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001549 else if (!strcmp(args[cur_arg], "check")) {
1550 global.maxsock++;
1551 do_check = 1;
1552 cur_arg += 1;
1553 }
1554 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1555 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001556#ifdef CONFIG_HAP_CTTPROXY
1557 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1558 file, linenum, "source", "usesrc");
1559#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1561 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001562#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 return -1;
1564 }
1565 newsrv->state |= SRV_BIND_SRC;
1566 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1567 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001568 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001569#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001570 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001571 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1572 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001573 return -1;
1574 }
1575 if (!*args[cur_arg + 1]) {
1576 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1577 file, linenum, "usesrc");
1578 return -1;
1579 }
1580 if (!strcmp(args[cur_arg + 1], "client")) {
1581 newsrv->state |= SRV_TPROXY_CLI;
1582 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1583 newsrv->state |= SRV_TPROXY_CIP;
1584 } else {
1585 newsrv->state |= SRV_TPROXY_ADDR;
1586 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1587 }
1588 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1589 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001590#else /* no CTTPROXY support */
1591 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1592 file, linenum, "usesrc");
1593 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001594#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001595 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001597#ifdef CONFIG_HAP_CTTPROXY
1598 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1599 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1600 file, linenum, "usesrc", "source");
1601 return -1;
1602 }
1603#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001604 else {
Willy Tarreau9909fc12007-11-30 17:42:05 +01001605 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 +02001606 file, linenum, newsrv->id);
1607 return -1;
1608 }
1609 }
1610
1611 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001612 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1613 newsrv->check_port = newsrv->check_addr.sin_port;
1614
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1616 newsrv->check_port = realport; /* by default */
1617 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001618 /* not yet valid, because no port was set on
1619 * the server either. We'll check if we have
1620 * a known port on the first listener.
1621 */
1622 struct listener *l;
1623 l = curproxy->listen;
1624 if (l) {
1625 int port;
1626 port = (l->addr.ss_family == AF_INET6)
1627 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1628 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1629 newsrv->check_port = port;
1630 }
1631 }
1632 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1634 file, linenum, newsrv->id);
1635 return -1;
1636 }
1637 newsrv->state |= SRV_CHECKED;
1638 }
1639
1640 if (newsrv->state & SRV_BACKUP)
1641 curproxy->srv_bck++;
1642 else
1643 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001644
1645 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001646 }
1647 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001648 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 int facility;
1650
1651 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1652 curproxy->logfac1 = global.logfac1;
1653 curproxy->logsrv1 = global.logsrv1;
1654 curproxy->loglev1 = global.loglev1;
1655 curproxy->logfac2 = global.logfac2;
1656 curproxy->logsrv2 = global.logsrv2;
1657 curproxy->loglev2 = global.loglev2;
1658 }
1659 else if (*(args[1]) && *(args[2])) {
1660 int level;
1661
1662 facility = get_log_facility(args[2]);
1663 if (facility < 0) {
1664 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1665 exit(1);
1666 }
1667
1668 level = 7; /* max syslog level = debug */
1669 if (*(args[3])) {
1670 level = get_log_level(args[3]);
1671 if (level < 0) {
1672 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1673 exit(1);
1674 }
1675 }
1676
Robert Tsai81ae1952007-12-05 10:47:29 +01001677 if (args[1][0] == '/') {
1678 logsrv.u.addr.sa_family = AF_UNIX;
1679 logsrv.u.un = *str2sun(args[1]);
1680 } else {
1681 logsrv.u.addr.sa_family = AF_INET;
1682 logsrv.u.in = *str2sa(args[1]);
1683 if (!logsrv.u.in.sin_port) {
1684 logsrv.u.in.sin_port =
1685 htons(SYSLOG_PORT);
1686 }
1687 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688
1689 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001690 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001691 curproxy->logfac1 = facility;
1692 curproxy->loglev1 = level;
1693 }
1694 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001695 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001696 curproxy->logfac2 = facility;
1697 curproxy->loglev2 = level;
1698 }
1699 else {
1700 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1701 return -1;
1702 }
1703 }
1704 else {
1705 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1706 file, linenum);
1707 return -1;
1708 }
1709 }
1710 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001711 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1712 return 0;
1713
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001715#ifdef CONFIG_HAP_CTTPROXY
1716 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1717 file, linenum, "source", "usesrc");
1718#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001719 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1720 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001721#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001722 return -1;
1723 }
1724
1725 curproxy->source_addr = *str2sa(args[1]);
1726 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001727 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001728#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001729 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1730 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1731 file, linenum, "usesrc");
1732 return -1;
1733 }
1734 if (!*args[3]) {
1735 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1736 file, linenum, "usesrc");
1737 return -1;
1738 }
1739
1740 if (!strcmp(args[3], "client")) {
1741 curproxy->options |= PR_O_TPXY_CLI;
1742 } else if (!strcmp(args[3], "clientip")) {
1743 curproxy->options |= PR_O_TPXY_CIP;
1744 } else {
1745 curproxy->options |= PR_O_TPXY_ADDR;
1746 curproxy->tproxy_addr = *str2sa(args[3]);
1747 }
1748 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001749#else /* no CTTPROXY support */
1750 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1751 file, linenum, "usesrc");
1752 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001753#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001754 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001755 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001756#ifdef CONFIG_HAP_CTTPROXY
1757 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1758 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1759 file, linenum, "usesrc", "source");
1760 return -1;
1761 }
1762#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1764 regex_t *preg;
1765 if (curproxy == &defproxy) {
1766 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1767 return -1;
1768 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001769 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1770 return 0;
1771
Willy Tarreaubaaee002006-06-26 02:48:02 +02001772 if (*(args[1]) == 0 || *(args[2]) == 0) {
1773 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1774 file, linenum, args[0]);
1775 return -1;
1776 }
1777
1778 preg = calloc(1, sizeof(regex_t));
1779 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1780 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1781 return -1;
1782 }
1783
1784 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1785 if (err) {
1786 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1787 file, linenum, *err);
1788 return -1;
1789 }
1790 }
1791 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1792 regex_t *preg;
1793 if (curproxy == &defproxy) {
1794 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1795 return -1;
1796 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001797 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1798 return 0;
1799
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800 if (*(args[1]) == 0) {
1801 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1802 return -1;
1803 }
1804
1805 preg = calloc(1, sizeof(regex_t));
1806 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1807 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1808 return -1;
1809 }
1810
1811 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1812 }
1813 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1814 regex_t *preg;
1815 if (curproxy == &defproxy) {
1816 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1817 return -1;
1818 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001819 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1820 return 0;
1821
Willy Tarreaubaaee002006-06-26 02:48:02 +02001822 if (*(args[1]) == 0) {
1823 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1824 return -1;
1825 }
1826
1827 preg = calloc(1, sizeof(regex_t));
1828 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1829 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1830 return -1;
1831 }
1832
1833 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1834 }
1835 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1836 regex_t *preg;
1837 if (curproxy == &defproxy) {
1838 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1839 return -1;
1840 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001841 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1842 return 0;
1843
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844 if (*(args[1]) == 0) {
1845 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1846 return -1;
1847 }
1848
1849 preg = calloc(1, sizeof(regex_t));
1850 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1851 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1852 return -1;
1853 }
1854
1855 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1856 }
1857 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1858 regex_t *preg;
1859 if (curproxy == &defproxy) {
1860 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1861 return -1;
1862 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001863 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1864 return 0;
1865
Willy Tarreaubaaee002006-06-26 02:48:02 +02001866 if (*(args[1]) == 0) {
1867 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1868 return -1;
1869 }
1870
1871 preg = calloc(1, sizeof(regex_t));
1872 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1873 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1874 return -1;
1875 }
1876
1877 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1878 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001879 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1880 regex_t *preg;
1881 if (curproxy == &defproxy) {
1882 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1883 return -1;
1884 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001885 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1886 return 0;
1887
Willy Tarreaub8750a82006-09-03 09:56:00 +02001888 if (*(args[1]) == 0) {
1889 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1890 return -1;
1891 }
1892
1893 preg = calloc(1, sizeof(regex_t));
1894 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1895 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1896 return -1;
1897 }
1898
1899 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1900 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001901 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1902 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001903 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001904 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1905 return -1;
1906 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001907 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1908 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001909
Willy Tarreau977b8e42006-12-29 14:19:17 +01001910 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001911 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1912 file, linenum, args[0]);
1913 return -1;
1914 }
1915
1916 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001917 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001918 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1919 }
1920
1921 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1922 }
1923 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1924 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001925 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001926 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1927 return -1;
1928 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001929 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1930 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001931
Willy Tarreau977b8e42006-12-29 14:19:17 +01001932 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001933 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1934 file, linenum, args[0]);
1935 return -1;
1936 }
1937
1938 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001939 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001940 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1941 }
1942
1943 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1946 regex_t *preg;
1947 if (curproxy == &defproxy) {
1948 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1949 return -1;
1950 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001951 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1952 return 0;
1953
Willy Tarreaubaaee002006-06-26 02:48:02 +02001954 if (*(args[1]) == 0 || *(args[2]) == 0) {
1955 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1956 file, linenum, args[0]);
1957 return -1;
1958 }
1959
1960 preg = calloc(1, sizeof(regex_t));
1961 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1962 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1963 return -1;
1964 }
1965
1966 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1967 if (err) {
1968 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1969 file, linenum, *err);
1970 return -1;
1971 }
1972 }
1973 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1974 regex_t *preg;
1975 if (curproxy == &defproxy) {
1976 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1977 return -1;
1978 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001979 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1980 return 0;
1981
Willy Tarreaubaaee002006-06-26 02:48:02 +02001982 if (*(args[1]) == 0) {
1983 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1984 return -1;
1985 }
1986
1987 preg = calloc(1, sizeof(regex_t));
1988 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1989 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1990 return -1;
1991 }
1992
1993 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1994 }
1995 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1996 regex_t *preg;
1997 if (curproxy == &defproxy) {
1998 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1999 return -1;
2000 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002001 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2002 return 0;
2003
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004 if (*(args[1]) == 0) {
2005 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2006 return -1;
2007 }
2008
2009 preg = calloc(1, sizeof(regex_t));
2010 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2011 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2012 return -1;
2013 }
2014
2015 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2016 }
2017 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2018 regex_t *preg;
2019 if (curproxy == &defproxy) {
2020 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2021 return -1;
2022 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002023 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2024 return 0;
2025
Willy Tarreaubaaee002006-06-26 02:48:02 +02002026 if (*(args[1]) == 0) {
2027 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2028 return -1;
2029 }
2030
2031 preg = calloc(1, sizeof(regex_t));
2032 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2033 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2034 return -1;
2035 }
2036
2037 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2038 }
2039 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2040 regex_t *preg;
2041 if (curproxy == &defproxy) {
2042 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2043 return -1;
2044 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002045 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2046 return 0;
2047
Willy Tarreaubaaee002006-06-26 02:48:02 +02002048 if (*(args[1]) == 0) {
2049 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2050 return -1;
2051 }
2052
2053 preg = calloc(1, sizeof(regex_t));
2054 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2055 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2056 return -1;
2057 }
2058
2059 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2060 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002061 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2062 regex_t *preg;
2063 if (curproxy == &defproxy) {
2064 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2065 return -1;
2066 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002067 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2068 return 0;
2069
Willy Tarreaub8750a82006-09-03 09:56:00 +02002070 if (*(args[1]) == 0) {
2071 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2072 return -1;
2073 }
2074
2075 preg = calloc(1, sizeof(regex_t));
2076 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2077 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2078 return -1;
2079 }
2080
2081 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2082 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002083 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2084 if (curproxy == &defproxy) {
2085 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2086 return -1;
2087 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002088 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2089 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002090
2091 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2092 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2093 return 0;
2094 }
2095
2096 if (*(args[1]) == 0) {
2097 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2098 return -1;
2099 }
2100
2101 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2102 }
2103 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2104 regex_t *preg;
2105
2106 if (*(args[1]) == 0 || *(args[2]) == 0) {
2107 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2108 file, linenum, args[0]);
2109 return -1;
2110 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002111 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2112 return 0;
2113
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114 preg = calloc(1, sizeof(regex_t));
2115 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2116 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2117 return -1;
2118 }
2119
2120 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2121 if (err) {
2122 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2123 file, linenum, *err);
2124 return -1;
2125 }
2126 }
2127 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2128 regex_t *preg;
2129 if (curproxy == &defproxy) {
2130 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2131 return -1;
2132 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002133 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2134 return 0;
2135
Willy Tarreaubaaee002006-06-26 02:48:02 +02002136 if (*(args[1]) == 0) {
2137 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2138 return -1;
2139 }
2140
2141 preg = calloc(1, sizeof(regex_t));
2142 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2143 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2144 return -1;
2145 }
2146
2147 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2148 if (err) {
2149 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2150 file, linenum, *err);
2151 return -1;
2152 }
2153 }
2154 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2155 regex_t *preg;
2156 if (curproxy == &defproxy) {
2157 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2158 return -1;
2159 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002160 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2161 return 0;
2162
Willy Tarreaubaaee002006-06-26 02:48:02 +02002163 if (*(args[1]) == 0) {
2164 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2165 return -1;
2166 }
2167
2168 preg = calloc(1, sizeof(regex_t));
2169 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2170 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2171 return -1;
2172 }
2173
2174 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2175 if (err) {
2176 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2177 file, linenum, *err);
2178 return -1;
2179 }
2180 }
2181 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2182 regex_t *preg;
2183 if (curproxy == &defproxy) {
2184 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2185 return -1;
2186 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002187 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2188 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002189
2190 if (*(args[1]) == 0 || *(args[2]) == 0) {
2191 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2192 file, linenum, args[0]);
2193 return -1;
2194 }
2195
2196 preg = calloc(1, sizeof(regex_t));
2197 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2198 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2199 return -1;
2200 }
2201
2202 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2203 if (err) {
2204 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2205 file, linenum, *err);
2206 return -1;
2207 }
2208 }
2209 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2210 regex_t *preg;
2211 if (curproxy == &defproxy) {
2212 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2213 return -1;
2214 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002215 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2216 return 0;
2217
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 if (*(args[1]) == 0) {
2219 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2220 return -1;
2221 }
2222
2223 preg = calloc(1, sizeof(regex_t));
2224 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2225 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2226 return -1;
2227 }
2228
2229 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2230 if (err) {
2231 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2232 file, linenum, *err);
2233 return -1;
2234 }
2235 }
2236 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2237 regex_t *preg;
2238 if (curproxy == &defproxy) {
2239 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2240 return -1;
2241 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002242 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2243 return 0;
2244
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 if (*(args[1]) == 0) {
2246 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2247 return -1;
2248 }
2249
2250 preg = calloc(1, sizeof(regex_t));
2251 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2252 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2253 return -1;
2254 }
2255
2256 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2257 if (err) {
2258 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2259 file, linenum, *err);
2260 return -1;
2261 }
2262 }
2263 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2264 if (curproxy == &defproxy) {
2265 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2266 return -1;
2267 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002268 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2269 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270
2271 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2272 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2273 return 0;
2274 }
2275
2276 if (*(args[1]) == 0) {
2277 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2278 return -1;
2279 }
2280
2281 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2282 }
2283 else if (!strcmp(args[0], "errorloc") ||
2284 !strcmp(args[0], "errorloc302") ||
2285 !strcmp(args[0], "errorloc303")) { /* error location */
2286 int errnum, errlen;
2287 char *err;
2288
Willy Tarreau977b8e42006-12-29 14:19:17 +01002289 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2290 return 0;
2291
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002293 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 return -1;
2295 }
2296
2297 errnum = atol(args[1]);
2298 if (!strcmp(args[0], "errorloc303")) {
2299 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2300 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2301 } else {
2302 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2303 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2304 }
2305
Willy Tarreau0f772532006-12-23 20:51:41 +01002306 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2307 if (http_err_codes[rc] == errnum) {
2308 if (curproxy->errmsg[rc].str)
2309 free(curproxy->errmsg[rc].str);
2310 curproxy->errmsg[rc].str = err;
2311 curproxy->errmsg[rc].len = errlen;
2312 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002313 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002314 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002315
2316 if (rc >= HTTP_ERR_SIZE) {
2317 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2318 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 free(err);
2320 }
2321 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002322 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2323 int errnum, errlen, fd;
2324 char *err;
2325 struct stat stat;
2326
2327 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2328 return 0;
2329
2330 if (*(args[2]) == 0) {
2331 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2332 return -1;
2333 }
2334
2335 fd = open(args[2], O_RDONLY);
2336 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2337 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2338 file, linenum, args[2], args[1]);
2339 if (fd >= 0)
2340 close(fd);
2341 return -1;
2342 }
2343
2344 if (stat.st_size <= BUFSIZE) {
2345 errlen = stat.st_size;
2346 } else {
2347 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2348 file, linenum, args[2], BUFSIZE);
2349 errlen = BUFSIZE;
2350 }
2351
2352 err = malloc(errlen); /* malloc() must succeed during parsing */
2353 errnum = read(fd, err, errlen);
2354 if (errnum != errlen) {
2355 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2356 file, linenum, args[2], args[1]);
2357 close(fd);
2358 free(err);
2359 return -1;
2360 }
2361 close(fd);
2362
2363 errnum = atol(args[1]);
2364 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2365 if (http_err_codes[rc] == errnum) {
2366 if (curproxy->errmsg[rc].str)
2367 free(curproxy->errmsg[rc].str);
2368 curproxy->errmsg[rc].str = err;
2369 curproxy->errmsg[rc].len = errlen;
2370 break;
2371 }
2372 }
2373
2374 if (rc >= HTTP_ERR_SIZE) {
2375 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2376 file, linenum, errnum);
2377 free(err);
2378 }
2379 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 else {
2381 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2382 return -1;
2383 }
2384 return 0;
2385}
2386
2387
2388/*
2389 * This function reads and parses the configuration file given in the argument.
2390 * returns 0 if OK, -1 if error.
2391 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002392int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002394 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 FILE *f;
2396 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 int confsect = CFG_NONE;
2399
2400 struct proxy *curproxy = NULL;
2401 struct server *newsrv = NULL;
2402
2403 if ((f=fopen(file,"r")) == NULL)
2404 return -1;
2405
2406 init_default_instance();
2407
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002408 while (fgets(thisline, sizeof(thisline), f) != NULL) {
2409 int arg;
2410 char *end;
2411 char *args[MAX_LINE_ARGS + 1];
2412 char *line = thisline;
2413
Willy Tarreaubaaee002006-06-26 02:48:02 +02002414 linenum++;
2415
2416 end = line + strlen(line);
2417
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002418 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2419 /* Check if we reached the limit and the last char is not \n.
2420 * Watch out for the last line without the terminating '\n'!
2421 */
2422 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2423 file, linenum, sizeof(thisline)-1);
2424 return -1;
2425 }
2426
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002428 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 line++;
2430
2431 arg = 0;
2432 args[arg] = line;
2433
2434 while (*line && arg < MAX_LINE_ARGS) {
2435 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2436 * C equivalent value. Other combinations left unchanged (eg: \1).
2437 */
2438 if (*line == '\\') {
2439 int skip = 0;
2440 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2441 *line = line[1];
2442 skip = 1;
2443 }
2444 else if (line[1] == 'r') {
2445 *line = '\r';
2446 skip = 1;
2447 }
2448 else if (line[1] == 'n') {
2449 *line = '\n';
2450 skip = 1;
2451 }
2452 else if (line[1] == 't') {
2453 *line = '\t';
2454 skip = 1;
2455 }
2456 else if (line[1] == 'x') {
2457 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2458 unsigned char hex1, hex2;
2459 hex1 = toupper(line[2]) - '0';
2460 hex2 = toupper(line[3]) - '0';
2461 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2462 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2463 *line = (hex1<<4) + hex2;
2464 skip = 3;
2465 }
2466 else {
2467 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2468 return -1;
2469 }
2470 }
2471 if (skip) {
2472 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2473 end -= skip;
2474 }
2475 line++;
2476 }
2477 else if (*line == '#' || *line == '\n' || *line == '\r') {
2478 /* end of string, end of loop */
2479 *line = 0;
2480 break;
2481 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002482 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002484 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002485 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002486 line++;
2487 args[++arg] = line;
2488 }
2489 else {
2490 line++;
2491 }
2492 }
2493
2494 /* empty line */
2495 if (!**args)
2496 continue;
2497
Willy Tarreau540abe42007-05-02 20:50:16 +02002498 /* zero out remaining args and ensure that at least one entry
2499 * is zeroed out.
2500 */
2501 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002502 args[arg] = line;
2503 }
2504
Willy Tarreau977b8e42006-12-29 14:19:17 +01002505 if (!strcmp(args[0], "listen") ||
2506 !strcmp(args[0], "frontend") ||
2507 !strcmp(args[0], "backend") ||
2508 !strcmp(args[0], "ruleset") ||
2509 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002510 confsect = CFG_LISTEN;
2511 else if (!strcmp(args[0], "global")) /* global config */
2512 confsect = CFG_GLOBAL;
2513 /* else it's a section keyword */
2514
2515 switch (confsect) {
2516 case CFG_LISTEN:
2517 if (cfg_parse_listen(file, linenum, args) < 0)
2518 return -1;
2519 break;
2520 case CFG_GLOBAL:
2521 if (cfg_parse_global(file, linenum, args) < 0)
2522 return -1;
2523 break;
2524 default:
2525 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2526 return -1;
2527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002528 }
2529 fclose(f);
2530
2531 /*
2532 * Now, check for the integrity of all that we have collected.
2533 */
2534
2535 /* will be needed further to delay some tasks */
2536 tv_now(&now);
2537
2538 if ((curproxy = proxy) == NULL) {
2539 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2540 file);
2541 return -1;
2542 }
2543
2544 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002545 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002546 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002547
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 if (curproxy->state == PR_STSTOPPED) {
2549 curproxy = curproxy->next;
2550 continue;
2551 }
2552
Willy Tarreau977b8e42006-12-29 14:19:17 +01002553 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2554 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 +01002555 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 cfgerr++;
2557 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002558 else if (curproxy->cap & PR_CAP_BE &&
2559 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002560 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002561 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002562 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2563 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 +01002564 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 cfgerr++;
2566 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002567
Willy Tarreau31682232007-11-29 15:38:04 +01002568 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002570 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002571 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 cfgerr++;
2573 }
2574#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2575 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002576 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002577 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 cfgerr++;
2579 }
2580#endif
2581 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002582 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002583 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 }
2585 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002586
2587 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002589 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002590 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002593 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002594 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 }
2596 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002597 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002598 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002600 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002601 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002602 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002603 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002604 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002605 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2606 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002607
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002608 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002609 file, proxy_type_str(curproxy), curproxy->id);
2610 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002612
2613 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2614 if ((newsrv = curproxy->srv) != NULL) {
2615 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2616 file, proxy_type_str(curproxy), curproxy->id);
2617 }
2618 }
2619
2620 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002621 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2622 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2623 file, curproxy->id);
2624 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002625 }
2626 }
2627
Willy Tarreau82936582007-11-30 15:20:09 +01002628 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2629 curproxy->options &= ~PR_O_DISABLE404;
2630 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2631 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2632 }
2633
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002634 /* if a default backend was specified, let's find it */
2635 if (curproxy->defbe.name) {
2636 struct proxy *target;
2637
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002638 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2639 if (!target) {
2640 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2641 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002642 cfgerr++;
2643 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002644 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2645 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002646 } else {
2647 free(curproxy->defbe.name);
2648 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 }
2650 }
2651
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002652 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002653 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2654 /* map jump target for ACT_SETBE in req_rep chain */
2655 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002656 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002657 struct proxy *target;
2658
Willy Tarreaua496b602006-12-17 23:15:24 +01002659 if (exp->action != ACT_SETBE)
2660 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002661
2662 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2663 if (!target) {
2664 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2665 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002666 cfgerr++;
2667 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002668 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2669 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002670 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002671 } else {
2672 free((void *)exp->replace);
2673 exp->replace = (const char *)target;
2674 }
2675 }
2676 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002677
2678 /* find the target proxy for 'use_backend' rules */
2679 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002680 struct proxy *target;
2681
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002682 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002683
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002684 if (!target) {
2685 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2686 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002687 cfgerr++;
2688 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002689 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2690 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002691 cfgerr++;
2692 } else {
2693 free((void *)rule->be.name);
2694 rule->be.backend = target;
2695 }
2696 }
2697
Willy Tarreau2738a142006-07-08 17:28:09 +02002698 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002699 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->timeout.client)) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02002700 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002701 (!tv_isset(&curproxy->timeout.connect) || !tv_isset(&curproxy->timeout.server))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002702 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002703 " | While not properly invalid, you will certainly encounter various problems\n"
2704 " | with such a configuration. To fix this, please ensure that all following\n"
2705 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002706 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002707 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002708
Willy Tarreau1fa31262007-12-03 00:36:16 +01002709 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
2710 * We must still support older configurations, so let's find out whether those
2711 * parameters have been set or must be copied from contimeouts.
2712 */
2713 if (curproxy != &defproxy) {
2714 if ((curproxy->cap & PR_CAP_FE) &&
2715 (!tv_isset(&curproxy->timeout.tarpit) ||
2716 __tv_iseq(&curproxy->timeout.tarpit, &defproxy.timeout.tarpit))) {
2717 /* tarpit timeout not set. We search in the following order:
2718 * default.tarpit, curr.connect, default.connect.
2719 */
2720 if (tv_isset(&defproxy.timeout.tarpit))
2721 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002722 else if (tv_isset(&curproxy->timeout.connect))
2723 curproxy->timeout.tarpit = curproxy->timeout.connect;
2724 else if (tv_isset(&defproxy.timeout.connect))
2725 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002726 }
2727 if ((curproxy->cap & PR_CAP_BE) &&
2728 (!tv_isset(&curproxy->timeout.queue) ||
2729 __tv_iseq(&curproxy->timeout.queue, &defproxy.timeout.queue))) {
2730 /* queue timeout not set. We search in the following order:
2731 * default.queue, curr.connect, default.connect.
2732 */
2733 if (tv_isset(&defproxy.timeout.queue))
2734 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002735 else if (tv_isset(&curproxy->timeout.connect))
2736 curproxy->timeout.queue = curproxy->timeout.connect;
2737 else if (tv_isset(&defproxy.timeout.connect))
2738 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002739 }
2740 }
2741
Willy Tarreauf3c69202006-07-09 16:42:34 +02002742 if (curproxy->options & PR_O_SSL3_CHK) {
2743 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2744 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2745 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2746 }
2747
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002748 /* The small pools required for the capture lists */
2749 if (curproxy->nb_req_cap)
2750 curproxy->req_cap_pool = create_pool("ptrcap",
2751 curproxy->nb_req_cap * sizeof(char *),
2752 MEM_F_SHARED);
2753 if (curproxy->nb_rsp_cap)
2754 curproxy->rsp_cap_pool = create_pool("ptrcap",
2755 curproxy->nb_rsp_cap * sizeof(char *),
2756 MEM_F_SHARED);
2757
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002758 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2759 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2760 MEM_F_SHARED);
2761
Willy Tarreau86034312006-12-29 00:10:33 +01002762 /* for backwards compatibility with "listen" instances, if
2763 * fullconn is not set but maxconn is set, then maxconn
2764 * is used.
2765 */
2766 if (!curproxy->fullconn)
2767 curproxy->fullconn = curproxy->maxconn;
2768
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769 /* first, we will invert the servers list order */
2770 newsrv = NULL;
2771 while (curproxy->srv) {
2772 struct server *next;
2773
2774 next = curproxy->srv->next;
2775 curproxy->srv->next = newsrv;
2776 newsrv = curproxy->srv;
2777 if (!next)
2778 break;
2779 curproxy->srv = next;
2780 }
2781
Willy Tarreau20697042007-11-15 23:26:18 +01002782 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01002783 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002784
Willy Tarreaub625a082007-11-26 01:15:43 +01002785 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01002786 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01002787 fwrr_init_server_groups(curproxy);
2788 else
2789 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002790
2791 if (curproxy->options & PR_O_LOGASAP)
2792 curproxy->to_log &= ~LW_BYTES;
2793
Willy Tarreaubaaee002006-06-26 02:48:02 +02002794 /*
2795 * If this server supports a maxconn parameter, it needs a dedicated
2796 * tasks to fill the emptied slots when a connection leaves.
2797 */
2798 newsrv = curproxy->srv;
2799 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002800 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002801 /* Only 'minconn' was specified, or it was higher than or equal
2802 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2803 * this will avoid further useless expensive computations.
2804 */
2805 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002806 } else if (newsrv->maxconn && !newsrv->minconn) {
2807 /* minconn was not specified, so we set it to maxconn */
2808 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002809 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2810 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002811 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002812 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002813 }
2814
2815 if (newsrv->maxconn > 0) {
2816 struct task *t;
2817
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002818 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002819 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2820 return -1;
2821 }
2822
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002823 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002824 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002825 t->state = TASK_IDLE;
2826 t->process = process_srv_queue;
2827 t->context = newsrv;
2828 newsrv->queue_mgt = t;
2829
2830 /* never run it unless specifically woken up */
2831 tv_eternity(&t->expire);
2832 task_queue(t);
2833 }
2834 newsrv = newsrv->next;
2835 }
2836
Willy Tarreaue6b98942007-10-29 01:09:36 +01002837 /* adjust this proxy's listeners */
2838 listener = curproxy->listen;
2839 while (listener) {
2840 if (curproxy->options & PR_O_TCP_NOLING)
2841 listener->options |= LI_O_NOLINGER;
2842 listener->maxconn = curproxy->maxconn;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002843 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002844 listener->accept = event_accept;
2845 listener->private = curproxy;
2846
2847 listener = listener->next;
2848 }
2849
Willy Tarreaubaaee002006-06-26 02:48:02 +02002850 curproxy = curproxy->next;
2851 }
2852 if (cfgerr > 0) {
2853 Alert("Errors found in configuration file, aborting.\n");
2854 return -1;
2855 }
2856 else
2857 return 0;
2858}
2859
2860
2861
2862/*
2863 * Local variables:
2864 * c-indent-level: 8
2865 * c-basic-offset: 8
2866 * End:
2867 */