blob: 9473b75ea792b63d1fc05090c1b241b73b4ec5a5 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau0b4ed902007-03-26 00:18:40 +02004 * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
27#include <common/config.h>
28#include <common/memory.h>
29#include <common/standard.h>
30#include <common/time.h>
31#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020032
33#include <types/capture.h>
34#include <types/global.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010035#include <types/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <types/polling.h>
37#include <types/proxy.h>
38#include <types/queue.h>
39
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010045#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020046#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010047#include <proto/protocols.h>
48#include <proto/proto_tcp.h>
49#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010050#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/server.h>
52#include <proto/task.h>
53
54
Willy Tarreauf3c69202006-07-09 16:42:34 +020055/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
56 * ssl-hello-chk option to ensure that the remote server speaks SSL.
57 *
58 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
59 */
60const char sslv3_client_hello_pkt[] = {
61 "\x16" /* ContentType : 0x16 = Hanshake */
62 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
63 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
64 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
65 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
66 "\x03\x00" /* Hello Version : 0x0300 = v3 */
67 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
68 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
69 "\x00" /* Session ID length : empty (no session ID) */
70 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
71 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
72 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
73 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
74 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
75 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
76 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
77 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
78 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
79 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
80 "\x00\x38" "\x00\x39" "\x00\x3A"
81 "\x01" /* Compression Length : 0x01 = 1 byte for types */
82 "\x00" /* Compression Type : 0x00 = NULL compression */
83};
84
Willy Tarreau13943ab2006-12-31 00:24:10 +010085/* some of the most common options which are also the easiest to handle */
86static const struct {
87 const char *name;
88 unsigned int val;
89 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010090 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010091} cfg_opts[] =
92{
93#ifdef TPROXY
94 { "transparent", PR_O_TRANSP, PR_CAP_FE },
95#endif
Willy Tarreau4fee4e92007-01-06 21:09:17 +010096 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
97 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010098 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
Alexandre Cassen87ea5482007-10-11 20:48:58 +020099 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Alexandre Cassen5eb1a902007-11-29 15:43:32 +0100100 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100101 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100102 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100103 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
104 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
105 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
106 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
107 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
108 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
109 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
110 { "forceclose", PR_O_FORCE_CLO | PR_O_HTTP_CLOSE, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100111#ifdef CONFIG_HAP_TCPSPLICE
112 { "tcpsplice", PR_O_TCPSPLICE , PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
113#endif
114
Willy Tarreau13943ab2006-12-31 00:24:10 +0100115 { NULL, 0, 0 }
116};
117
Willy Tarreaubaaee002006-06-26 02:48:02 +0200118
119static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
120int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
121int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
122
123/*
124 * converts <str> to a list of listeners which are dynamically allocated.
125 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
126 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
127 * - <port> is a numerical port from 1 to 65535 ;
128 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
129 * This can be repeated as many times as necessary, separated by a coma.
130 * The <tail> argument is a pointer to a current list which should be appended
131 * to the tail of the new list. The pointer to the new list is returned.
132 */
133static struct listener *str2listener(char *str, struct listener *tail)
134{
135 struct listener *l;
136 char *c, *next, *range, *dupstr;
137 int port, end;
138
139 next = dupstr = strdup(str);
140
141 while (next && *next) {
142 struct sockaddr_storage ss;
143
144 str = next;
145 /* 1) look for the end of the first address */
146 if ((next = strrchr(str, ',')) != NULL) {
147 *next++ = 0;
148 }
149
150 /* 2) look for the addr/port delimiter, it's the last colon. */
151 if ((range = strrchr(str, ':')) == NULL) {
152 Alert("Missing port number: '%s'\n", str);
153 goto fail;
154 }
155
156 *range++ = 0;
157
158 if (strrchr(str, ':') != NULL) {
159 /* IPv6 address contains ':' */
160 memset(&ss, 0, sizeof(ss));
161 ss.ss_family = AF_INET6;
162
163 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
164 Alert("Invalid server address: '%s'\n", str);
165 goto fail;
166 }
167 }
168 else {
169 memset(&ss, 0, sizeof(ss));
170 ss.ss_family = AF_INET;
171
172 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
173 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
174 }
175 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
176 struct hostent *he;
177
178 if ((he = gethostbyname(str)) == NULL) {
179 Alert("Invalid server name: '%s'\n", str);
180 goto fail;
181 }
182 else
183 ((struct sockaddr_in *)&ss)->sin_addr =
184 *(struct in_addr *) *(he->h_addr_list);
185 }
186 }
187
188 /* 3) look for the port-end delimiter */
189 if ((c = strchr(range, '-')) != NULL) {
190 *c++ = 0;
191 end = atol(c);
192 }
193 else {
194 end = atol(range);
195 }
196
197 port = atol(range);
198
199 if (port < 1 || port > 65535) {
200 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
201 goto fail;
202 }
203
204 if (end < 1 || end > 65535) {
205 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
206 goto fail;
207 }
208
209 for (; port <= end; port++) {
210 l = (struct listener *)calloc(1, sizeof(struct listener));
211 l->next = tail;
212 tail = l;
213
214 l->fd = -1;
215 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100216 l->state = LI_INIT;
217
218 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100220 tcpv6_add_listener(l);
221 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100223 tcpv4_add_listener(l);
224 }
225 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 } /* end for(port) */
227 } /* end while(next) */
228 free(dupstr);
229 return tail;
230 fail:
231 free(dupstr);
232 return NULL;
233}
234
Willy Tarreau977b8e42006-12-29 14:19:17 +0100235/*
236 * Sends a warning if proxy <proxy> does not have at least one of the
237 * capabilities in <cap>. An optionnal <hint> may be added at the end
238 * of the warning to help the user. Returns 1 if a warning was emitted
239 * or 0 if the condition is valid.
240 */
241int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
242{
243 char *msg;
244
245 switch (cap) {
246 case PR_CAP_BE: msg = "no backend"; break;
247 case PR_CAP_FE: msg = "no frontend"; break;
248 case PR_CAP_RS: msg = "no ruleset"; break;
249 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
250 default: msg = "not enough"; break;
251 }
252
253 if (!(proxy->cap & cap)) {
254 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100255 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100256 return 1;
257 }
258 return 0;
259}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200260
261/*
262 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
263 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200264int cfg_parse_global(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265{
266
267 if (!strcmp(args[0], "global")) { /* new section */
268 /* no option, nothing special to do */
269 return 0;
270 }
271 else if (!strcmp(args[0], "daemon")) {
272 global.mode |= MODE_DAEMON;
273 }
274 else if (!strcmp(args[0], "debug")) {
275 global.mode |= MODE_DEBUG;
276 }
277 else if (!strcmp(args[0], "noepoll")) {
278 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
279 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200280 else if (!strcmp(args[0], "nosepoll")) {
281 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
282 }
283 else if (!strcmp(args[0], "nokqueue")) {
284 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286 else if (!strcmp(args[0], "nopoll")) {
287 cfg_polling_mechanism &= ~POLL_USE_POLL;
288 }
289 else if (!strcmp(args[0], "quiet")) {
290 global.mode |= MODE_QUIET;
291 }
292 else if (!strcmp(args[0], "stats")) {
Willy Tarreaufbee7132007-10-18 13:53:22 +0200293 memcpy(trash, "error near 'stats'", 19);
294 if (stats_parse_global((const char **)args + 1, trash, sizeof(trash)) < 0) {
295 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
296 return -1;
297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200299 else if (!strcmp(args[0], "tune.maxpollevents")) {
300 if (global.tune.maxpollevents != 0) {
301 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
302 return 0;
303 }
304 if (*(args[1]) == 0) {
305 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
306 return -1;
307 }
308 global.tune.maxpollevents = atol(args[1]);
309 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200310 else if (!strcmp(args[0], "uid")) {
311 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200312 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200313 return 0;
314 }
315 if (*(args[1]) == 0) {
316 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
317 return -1;
318 }
319 global.uid = atol(args[1]);
320 }
321 else if (!strcmp(args[0], "gid")) {
322 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200323 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324 return 0;
325 }
326 if (*(args[1]) == 0) {
327 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
328 return -1;
329 }
330 global.gid = atol(args[1]);
331 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200332 /* user/group name handling */
333 else if (!strcmp(args[0], "user")) {
334 struct passwd *ha_user;
335 if (global.uid != 0) {
336 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
337 return 0;
338 }
339 errno = 0;
340 ha_user = getpwnam(args[1]);
341 if (ha_user != NULL) {
342 global.uid = (int)ha_user->pw_uid;
343 }
344 else {
345 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
346 exit(1);
347 }
348 }
349 else if (!strcmp(args[0], "group")) {
350 struct group *ha_group;
351 if (global.gid != 0) {
352 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
353 return 0;
354 }
355 errno = 0;
356 ha_group = getgrnam(args[1]);
357 if (ha_group != NULL) {
358 global.gid = (int)ha_group->gr_gid;
359 }
360 else {
361 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
362 exit(1);
363 }
364 }
365 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200366 else if (!strcmp(args[0], "nbproc")) {
367 if (global.nbproc != 0) {
368 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
369 return 0;
370 }
371 if (*(args[1]) == 0) {
372 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
373 return -1;
374 }
375 global.nbproc = atol(args[1]);
376 }
377 else if (!strcmp(args[0], "maxconn")) {
378 if (global.maxconn != 0) {
379 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
380 return 0;
381 }
382 if (*(args[1]) == 0) {
383 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
384 return -1;
385 }
386 global.maxconn = atol(args[1]);
387#ifdef SYSTEM_MAXCONN
388 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
389 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
390 global.maxconn = DEFAULT_MAXCONN;
391 }
392#endif /* SYSTEM_MAXCONN */
393 }
394 else if (!strcmp(args[0], "ulimit-n")) {
395 if (global.rlimit_nofile != 0) {
396 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
397 return 0;
398 }
399 if (*(args[1]) == 0) {
400 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
401 return -1;
402 }
403 global.rlimit_nofile = atol(args[1]);
404 }
405 else if (!strcmp(args[0], "chroot")) {
406 if (global.chroot != NULL) {
407 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
408 return 0;
409 }
410 if (*(args[1]) == 0) {
411 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
412 return -1;
413 }
414 global.chroot = strdup(args[1]);
415 }
416 else if (!strcmp(args[0], "pidfile")) {
417 if (global.pidfile != NULL) {
418 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
419 return 0;
420 }
421 if (*(args[1]) == 0) {
422 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
423 return -1;
424 }
425 global.pidfile = strdup(args[1]);
426 }
427 else if (!strcmp(args[0], "log")) { /* syslog server address */
428 struct sockaddr_in *sa;
429 int facility, level;
430
431 if (*(args[1]) == 0 || *(args[2]) == 0) {
432 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
433 return -1;
434 }
435
436 facility = get_log_facility(args[2]);
437 if (facility < 0) {
438 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
439 exit(1);
440 }
441
442 level = 7; /* max syslog level = debug */
443 if (*(args[3])) {
444 level = get_log_level(args[3]);
445 if (level < 0) {
446 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
447 exit(1);
448 }
449 }
450
451 sa = str2sa(args[1]);
452 if (!sa->sin_port)
453 sa->sin_port = htons(SYSLOG_PORT);
454
455 if (global.logfac1 == -1) {
456 global.logsrv1 = *sa;
457 global.logfac1 = facility;
458 global.loglev1 = level;
459 }
460 else if (global.logfac2 == -1) {
461 global.logsrv2 = *sa;
462 global.logfac2 = facility;
463 global.loglev2 = level;
464 }
465 else {
466 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
467 return -1;
468 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200469 }
470 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
471 if (global.spread_checks != 0) {
472 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
473 return 0;
474 }
475 if (*(args[1]) == 0) {
476 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
477 return -1;
478 }
479 global.spread_checks = atol(args[1]);
480 if (global.spread_checks < 0 || global.spread_checks > 50) {
481 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
482 return -1;
483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200484 }
485 else {
486 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
487 return -1;
488 }
489 return 0;
490}
491
492
493static void init_default_instance()
494{
495 memset(&defproxy, 0, sizeof(defproxy));
496 defproxy.mode = PR_MODE_TCP;
497 defproxy.state = PR_STNEW;
498 defproxy.maxconn = cfg_maxpconn;
499 defproxy.conn_retries = CONN_RETRIES;
500 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100501 tv_eternity(&defproxy.timeout.client);
502 tv_eternity(&defproxy.timeout.connect);
503 tv_eternity(&defproxy.timeout.server);
504 tv_eternity(&defproxy.timeout.appsession);
Willy Tarreau1fa31262007-12-03 00:36:16 +0100505 tv_eternity(&defproxy.timeout.queue);
506 tv_eternity(&defproxy.timeout.tarpit);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200507}
508
509/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100510 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
511 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200512 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200513int cfg_parse_listen(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200514{
515 static struct proxy *curproxy = NULL;
516 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200517 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100518 int rc;
519 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520
Willy Tarreau977b8e42006-12-29 14:19:17 +0100521 if (!strcmp(args[0], "listen"))
522 rc = PR_CAP_LISTEN;
523 else if (!strcmp(args[0], "frontend"))
524 rc = PR_CAP_FE | PR_CAP_RS;
525 else if (!strcmp(args[0], "backend"))
526 rc = PR_CAP_BE | PR_CAP_RS;
527 else if (!strcmp(args[0], "ruleset"))
528 rc = PR_CAP_RS;
529 else
530 rc = PR_CAP_NONE;
531
532 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200533 if (!*args[1]) {
534 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
535 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
536 file, linenum, args[0]);
537 return -1;
538 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200539
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100540 err = invalid_char(args[1]);
541 if (err) {
542 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
543 file, linenum, *err, args[0], args[1]);
544 return -1;
545 }
546
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200547 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
548 /*
549 * If there are two proxies with the same name only following
550 * combinations are allowed:
551 *
552 * listen backend frontend ruleset
553 * listen - - - -
554 * backend - - OK -
555 * frontend - OK - -
556 * ruleset - - - -
557 */
558
559 if (!strcmp(curproxy->id, args[1]) &&
560 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
561 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100562 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
563 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200564 }
565 }
566
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
568 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
569 return -1;
570 }
571
572 curproxy->next = proxy;
573 proxy = curproxy;
574 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200575 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200576 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100577 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200578 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579
Willy Tarreauee991362007-05-14 14:37:50 +0200580 /* Timeouts are defined as -1, so we cannot use the zeroed area
581 * as a default value.
582 */
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100583 tv_eternity(&curproxy->timeout.client);
584 tv_eternity(&curproxy->timeout.server);
585 tv_eternity(&curproxy->timeout.connect);
586 tv_eternity(&curproxy->timeout.appsession);
Willy Tarreau1fa31262007-12-03 00:36:16 +0100587 tv_eternity(&curproxy->timeout.queue);
588 tv_eternity(&curproxy->timeout.tarpit);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200589
590 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200591 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100592 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200593
594 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100595 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200596 curproxy->listen = str2listener(args[2], curproxy->listen);
597 if (!curproxy->listen)
598 return -1;
599 global.maxsock++;
600 }
601
602 /* set default values */
603 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100605 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200606 curproxy->except_net = defproxy.except_net;
607 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608
Willy Tarreau977b8e42006-12-29 14:19:17 +0100609 if (curproxy->cap & PR_CAP_FE) {
610 curproxy->maxconn = defproxy.maxconn;
611
612 /* initialize error relocations */
613 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
614 if (defproxy.errmsg[rc].str)
615 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
616 }
617
618 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
619 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200620
Willy Tarreau977b8e42006-12-29 14:19:17 +0100621 if (curproxy->cap & PR_CAP_BE) {
622 curproxy->fullconn = defproxy.fullconn;
623 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200624
Willy Tarreau977b8e42006-12-29 14:19:17 +0100625 if (defproxy.check_req)
626 curproxy->check_req = strdup(defproxy.check_req);
627 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628
Willy Tarreau977b8e42006-12-29 14:19:17 +0100629 if (defproxy.cookie_name)
630 curproxy->cookie_name = strdup(defproxy.cookie_name);
631 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100632
633 if (defproxy.url_param_name)
634 curproxy->url_param_name = strdup(defproxy.url_param_name);
635 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100636 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200637
Willy Tarreau977b8e42006-12-29 14:19:17 +0100638 if (curproxy->cap & PR_CAP_RS) {
639 if (defproxy.capture_name)
640 curproxy->capture_name = strdup(defproxy.capture_name);
641 curproxy->capture_namelen = defproxy.capture_namelen;
642 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100643 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644
Willy Tarreau977b8e42006-12-29 14:19:17 +0100645 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100646 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100647 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100648 curproxy->uri_auth = defproxy.uri_auth;
649 curproxy->mon_net = defproxy.mon_net;
650 curproxy->mon_mask = defproxy.mon_mask;
651 if (defproxy.monitor_uri)
652 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
653 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100654 if (defproxy.defbe.name)
655 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100656 }
657
658 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100659 curproxy->timeout.connect = defproxy.timeout.connect;
660 curproxy->timeout.server = defproxy.timeout.server;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100661 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100662 curproxy->source_addr = defproxy.source_addr;
663 }
664
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 curproxy->mode = defproxy.mode;
666 curproxy->logfac1 = defproxy.logfac1;
667 curproxy->logsrv1 = defproxy.logsrv1;
668 curproxy->loglev1 = defproxy.loglev1;
669 curproxy->logfac2 = defproxy.logfac2;
670 curproxy->logsrv2 = defproxy.logsrv2;
671 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200672 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100673 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
674 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200675
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676 return 0;
677 }
678 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
679 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100680 /* FIXME-20070101: we should do this too at the end of the
681 * config parsing to free all default values.
682 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200683 if (defproxy.check_req) free(defproxy.check_req);
684 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100685 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200686 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200687 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100688 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100689
690 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
691 if (defproxy.errmsg[rc].len)
692 free(defproxy.errmsg[rc].str);
693 }
694
Willy Tarreaubaaee002006-06-26 02:48:02 +0200695 /* we cannot free uri_auth because it might already be used */
696 init_default_instance();
697 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100698 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200699 return 0;
700 }
701 else if (curproxy == NULL) {
702 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
703 return -1;
704 }
705
Willy Tarreau977b8e42006-12-29 14:19:17 +0100706
707 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200708 if (!strcmp(args[0], "bind")) { /* new listen addresses */
709 if (curproxy == &defproxy) {
710 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
711 return -1;
712 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100713 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
714 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200715
716 if (strchr(args[1], ':') == NULL) {
717 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
718 file, linenum, args[0]);
719 return -1;
720 }
721 curproxy->listen = str2listener(args[1], curproxy->listen);
722 if (!curproxy->listen)
723 return -1;
724 global.maxsock++;
725 return 0;
726 }
727 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
728 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
729 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
730 file, linenum, args[0]);
731 return -1;
732 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100733 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
734 return 0;
735
Willy Tarreaubaaee002006-06-26 02:48:02 +0200736 /* flush useless bits */
737 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
738 return 0;
739 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200740 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100741 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
742 return 0;
743
Willy Tarreau1c47f852006-07-09 08:22:27 +0200744 if (!*args[1]) {
745 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
746 file, linenum, args[0]);
747 return -1;
748 }
749
750 if (curproxy->monitor_uri != NULL)
751 free(curproxy->monitor_uri);
752
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100753 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200754 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100755 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200756 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
757
758 return 0;
759 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200760 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
761 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
762 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
763 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
764 else {
765 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
766 return -1;
767 }
768 }
769 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
770 curproxy->state = PR_STSTOPPED;
771 }
772 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
773 curproxy->state = PR_STNEW;
774 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200775 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100776 err = invalid_char(args[1]);
777 if (err) {
778 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
779 file, linenum, *err, args[1]);
780 return -1;
781 }
782
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200783 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
784 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
785 file, linenum, args[1]);
786 return -1;
787 }
788 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789 else if (!strcmp(args[0], "cookie")) { /* cookie name */
790 int cur_arg;
791 // if (curproxy == &defproxy) {
792 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
793 // return -1;
794 // }
795
Willy Tarreau977b8e42006-12-29 14:19:17 +0100796 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
797 return 0;
798
Willy Tarreaubaaee002006-06-26 02:48:02 +0200799 if (curproxy->cookie_name != NULL) {
800 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
801 // file, linenum);
802 // return 0;
803 free(curproxy->cookie_name);
804 }
805
806 if (*(args[1]) == 0) {
807 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
808 file, linenum, args[0]);
809 return -1;
810 }
811 curproxy->cookie_name = strdup(args[1]);
812 curproxy->cookie_len = strlen(curproxy->cookie_name);
813
814 cur_arg = 2;
815 while (*(args[cur_arg])) {
816 if (!strcmp(args[cur_arg], "rewrite")) {
817 curproxy->options |= PR_O_COOK_RW;
818 }
819 else if (!strcmp(args[cur_arg], "indirect")) {
820 curproxy->options |= PR_O_COOK_IND;
821 }
822 else if (!strcmp(args[cur_arg], "insert")) {
823 curproxy->options |= PR_O_COOK_INS;
824 }
825 else if (!strcmp(args[cur_arg], "nocache")) {
826 curproxy->options |= PR_O_COOK_NOC;
827 }
828 else if (!strcmp(args[cur_arg], "postonly")) {
829 curproxy->options |= PR_O_COOK_POST;
830 }
831 else if (!strcmp(args[cur_arg], "prefix")) {
832 curproxy->options |= PR_O_COOK_PFX;
833 }
834 else {
835 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
836 file, linenum, args[0]);
837 return -1;
838 }
839 cur_arg++;
840 }
841 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
842 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
843 file, linenum);
844 return -1;
845 }
846
847 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
848 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
849 file, linenum);
850 return -1;
851 }
852 }/* end else if (!strcmp(args[0], "cookie")) */
853 else if (!strcmp(args[0], "appsession")) { /* cookie name */
854 // if (curproxy == &defproxy) {
855 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
856 // return -1;
857 // }
858
Willy Tarreau977b8e42006-12-29 14:19:17 +0100859 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
860 return 0;
861
Willy Tarreaubaaee002006-06-26 02:48:02 +0200862 if (curproxy->appsession_name != NULL) {
863 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
864 // file, linenum);
865 // return 0;
866 free(curproxy->appsession_name);
867 }
868
869 if (*(args[5]) == 0) {
870 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
871 file, linenum, args[0]);
872 return -1;
873 }
874 have_appsession = 1;
875 curproxy->appsession_name = strdup(args[1]);
876 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
877 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100878 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
879 if (err) {
880 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
881 file, linenum, *err, args[0]);
882 return -1;
883 }
Willy Tarreauee991362007-05-14 14:37:50 +0200884 if (val > 0)
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100885 __tv_from_ms(&curproxy->timeout.appsession, val);
Willy Tarreauee991362007-05-14 14:37:50 +0200886 else
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100887 tv_eternity(&curproxy->timeout.appsession);
Willy Tarreauee991362007-05-14 14:37:50 +0200888
Willy Tarreau51041c72007-09-09 21:56:53 +0200889 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
890 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891 return -1;
892 }
893 } /* Url App Session */
894 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100895 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
896 return 0;
897
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
899 // if (curproxy == &defproxy) {
900 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
901 // return -1;
902 // }
903
904 if (curproxy->capture_name != NULL) {
905 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
906 // file, linenum, args[0]);
907 // return 0;
908 free(curproxy->capture_name);
909 }
910
911 if (*(args[4]) == 0) {
912 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
913 file, linenum, args[0]);
914 return -1;
915 }
916 curproxy->capture_name = strdup(args[2]);
917 curproxy->capture_namelen = strlen(curproxy->capture_name);
918 curproxy->capture_len = atol(args[4]);
919 if (curproxy->capture_len >= CAPTURE_LEN) {
920 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
921 file, linenum, CAPTURE_LEN - 1);
922 curproxy->capture_len = CAPTURE_LEN - 1;
923 }
924 curproxy->to_log |= LW_COOKIE;
925 }
926 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
927 struct cap_hdr *hdr;
928
929 if (curproxy == &defproxy) {
930 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
931 return -1;
932 }
933
934 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
935 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
936 file, linenum, args[0], args[1]);
937 return -1;
938 }
939
940 hdr = calloc(sizeof(struct cap_hdr), 1);
941 hdr->next = curproxy->req_cap;
942 hdr->name = strdup(args[3]);
943 hdr->namelen = strlen(args[3]);
944 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200945 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 hdr->index = curproxy->nb_req_cap++;
947 curproxy->req_cap = hdr;
948 curproxy->to_log |= LW_REQHDR;
949 }
950 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
951 struct cap_hdr *hdr;
952
953 if (curproxy == &defproxy) {
954 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
955 return -1;
956 }
957
958 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
959 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
960 file, linenum, args[0], args[1]);
961 return -1;
962 }
963 hdr = calloc(sizeof(struct cap_hdr), 1);
964 hdr->next = curproxy->rsp_cap;
965 hdr->name = strdup(args[3]);
966 hdr->namelen = strlen(args[3]);
967 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200968 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200969 hdr->index = curproxy->nb_rsp_cap++;
970 curproxy->rsp_cap = hdr;
971 curproxy->to_log |= LW_RSPHDR;
972 }
973 else {
974 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
975 file, linenum, args[0]);
976 return -1;
977 }
978 }
Willy Tarreaue219db72007-12-03 01:30:13 +0100979 else if (!strcmp(args[0], "contimeout") || !strcmp(args[0], "clitimeout") ||
980 !strcmp(args[0], "srvtimeout") || !strcmp(args[0], "timeout")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100981
Willy Tarreaue219db72007-12-03 01:30:13 +0100982 /* either we have {con|srv|cli}timeout <value> or we have the
983 * new form: timeout <type> <value>. The parser needs the word
984 * preceeding the value.
985 */
986 const char **start_arg = (const char **)args;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100987
Willy Tarreaue219db72007-12-03 01:30:13 +0100988 if (strcmp(args[0], "timeout") == 0)
989 start_arg++;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100990
Willy Tarreaue219db72007-12-03 01:30:13 +0100991 snprintf(trash, sizeof(trash), "error near '%s'", args[0]);
992 rc = proxy_parse_timeout(start_arg, curproxy, &defproxy, trash, sizeof(trash));
993 if (rc < 0) {
994 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100995 return -1;
996 }
Willy Tarreaue219db72007-12-03 01:30:13 +0100997 if (rc > 0)
998 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 }
1000 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001001 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1002 return 0;
1003
Willy Tarreaubaaee002006-06-26 02:48:02 +02001004 if (*(args[1]) == 0) {
1005 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1006 file, linenum, args[0]);
1007 return -1;
1008 }
1009 curproxy->conn_retries = atol(args[1]);
1010 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001011 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1012 int pol = ACL_COND_NONE;
1013 struct acl_cond *cond;
1014
1015 if (!strcmp(args[1], "if"))
1016 pol = ACL_COND_IF;
1017 else if (!strcmp(args[1], "unless"))
1018 pol = ACL_COND_UNLESS;
1019
1020 if (pol == ACL_COND_NONE) {
1021 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1022 file, linenum, args[0]);
1023 return -1;
1024 }
1025
1026 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1027 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1028 file, linenum);
1029 return -1;
1030 }
1031 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1032 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001033 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1034 int pol = ACL_COND_NONE;
1035 struct acl_cond *cond;
1036 struct switching_rule *rule;
1037
1038 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1039 return 0;
1040
1041 if (*(args[1]) == 0) {
1042 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1043 return -1;
1044 }
1045
1046 if (!strcmp(args[2], "if"))
1047 pol = ACL_COND_IF;
1048 else if (!strcmp(args[2], "unless"))
1049 pol = ACL_COND_UNLESS;
1050
1051 if (pol == ACL_COND_NONE) {
1052 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1053 file, linenum, args[0]);
1054 return -1;
1055 }
1056
1057 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1058 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1059 file, linenum);
1060 return -1;
1061 }
1062
1063 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1064 rule->cond = cond;
1065 rule->be.name = strdup(args[1]);
1066 LIST_INIT(&rule->list);
1067 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1068 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001069 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001070 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1071 return 0;
1072
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1074 curproxy->uri_auth = NULL; /* we must detach from the default config */
1075
1076 if (*(args[1]) == 0) {
1077 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1078 return -1;
1079 } else if (!strcmp(args[1], "uri")) {
1080 if (*(args[2]) == 0) {
1081 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1082 return -1;
1083 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1084 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1085 return -1;
1086 }
1087 } else if (!strcmp(args[1], "realm")) {
1088 if (*(args[2]) == 0) {
1089 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1090 return -1;
1091 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1092 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1093 return -1;
1094 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001095 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001096 unsigned interval;
1097
1098 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1099 if (err) {
1100 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1101 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001102 return -1;
1103 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1104 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1105 return -1;
1106 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 } else if (!strcmp(args[1], "auth")) {
1108 if (*(args[2]) == 0) {
1109 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1110 return -1;
1111 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1112 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1113 return -1;
1114 }
1115 } else if (!strcmp(args[1], "scope")) {
1116 if (*(args[2]) == 0) {
1117 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1118 return -1;
1119 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1120 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1121 return -1;
1122 }
1123 } else if (!strcmp(args[1], "enable")) {
1124 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1125 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1126 return -1;
1127 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001128 } else if (!strcmp(args[1], "hide-version")) {
1129 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1130 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1131 return -1;
1132 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001133 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001134 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 file, linenum, args[0]);
1136 return -1;
1137 }
1138 }
1139 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001140 int optnum;
1141
Willy Tarreaubaaee002006-06-26 02:48:02 +02001142 if (*(args[1]) == 0) {
1143 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
1144 return -1;
1145 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001146
1147 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1148 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1149 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1150 return 0;
1151 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001152 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001153 return 0;
1154 }
1155 }
1156
1157 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158 /* generate a complete HTTP log */
1159 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1160 else if (!strcmp(args[1], "tcplog"))
1161 /* generate a detailed TCP log */
1162 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 else if (!strcmp(args[1], "tcpka")) {
1164 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001165 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1166 return 0;
1167
1168 if (curproxy->cap & PR_CAP_FE)
1169 curproxy->options |= PR_O_TCP_CLI_KA;
1170 if (curproxy->cap & PR_CAP_BE)
1171 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001172 }
1173 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001174 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1175 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001176 /* use HTTP request to check servers' health */
1177 if (curproxy->check_req != NULL) {
1178 free(curproxy->check_req);
1179 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001180 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001181 curproxy->options &= ~PR_O_SMTP_CHK;
1182 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001183 if (!*args[2]) { /* no argument */
1184 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1185 curproxy->check_len = strlen(DEF_CHECK_REQ);
1186 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001187 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001188 curproxy->check_req = (char *)malloc(reqlen);
1189 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1190 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1191 } else { /* more arguments : METHOD URI [HTTP_VER] */
1192 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1193 if (*args[4])
1194 reqlen += strlen(args[4]);
1195 else
1196 reqlen += strlen("HTTP/1.0");
1197
1198 curproxy->check_req = (char *)malloc(reqlen);
1199 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1200 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1201 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001202 }
1203 else if (!strcmp(args[1], "ssl-hello-chk")) {
1204 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001205 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1206 return 0;
1207
Willy Tarreauf3c69202006-07-09 16:42:34 +02001208 if (curproxy->check_req != NULL) {
1209 free(curproxy->check_req);
1210 }
1211 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001212 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001213 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001214 }
Willy Tarreau23677902007-05-08 23:50:35 +02001215 else if (!strcmp(args[1], "smtpchk")) {
1216 /* use SMTP request to check servers' health */
1217 if (curproxy->check_req != NULL) {
1218 free(curproxy->check_req);
1219 }
1220 curproxy->options &= ~PR_O_HTTP_CHK;
1221 curproxy->options &= ~PR_O_SSL3_CHK;
1222 curproxy->options |= PR_O_SMTP_CHK;
1223
1224 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1225 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1226 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1227 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1228 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1229 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1230 curproxy->check_req = (char *)malloc(reqlen);
1231 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1232 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1233 } else {
1234 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1235 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1236 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1237 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1238 }
1239 }
1240 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001241 else if (!strcmp(args[1], "forwardfor")) {
1242 /* insert x-forwarded-for field, but not for the
1243 * IP address listed as an except.
1244 */
1245 if (*(args[2])) {
1246 if (!strcmp(args[2], "except")) {
1247 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1248 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1249 file, linenum, args[0]);
1250 return -1;
1251 }
1252 /* flush useless bits */
1253 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1254 } else {
1255 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1256 file, linenum, args[0]);
1257 return -1;
1258 }
1259 }
1260 curproxy->options |= PR_O_FWDFOR;
1261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001262 else {
1263 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1264 return -1;
1265 }
1266 return 0;
1267 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001268 else if (!strcmp(args[0], "default_backend")) {
1269 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1270 return 0;
1271
1272 if (*(args[1]) == 0) {
1273 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1274 return -1;
1275 }
1276 if (curproxy->defbe.name)
1277 free(curproxy->defbe.name);
1278 curproxy->defbe.name = strdup(args[1]);
1279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001280 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001281 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1282 return 0;
1283
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284 /* enable reconnections to dispatch */
1285 curproxy->options |= PR_O_REDISP;
1286 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001287 else if (!strcmp(args[0], "http-check")) {
1288 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1289 return 0;
1290
1291 if (strcmp(args[1], "disable-on-404") == 0) {
1292 /* enable a graceful server shutdown on an HTTP 404 response */
1293 curproxy->options |= PR_O_DISABLE404;
1294 }
1295 else {
1296 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1297 return -1;
1298 }
1299 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001300 else if (!strcmp(args[0], "monitor")) {
1301 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1302 return 0;
1303
1304 if (strcmp(args[1], "fail") == 0) {
1305 /* add a condition to fail monitor requests */
1306 int pol = ACL_COND_NONE;
1307 struct acl_cond *cond;
1308
1309 if (!strcmp(args[2], "if"))
1310 pol = ACL_COND_IF;
1311 else if (!strcmp(args[2], "unless"))
1312 pol = ACL_COND_UNLESS;
1313
1314 if (pol == ACL_COND_NONE) {
1315 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1316 file, linenum, args[0], args[1]);
1317 return -1;
1318 }
1319
1320 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1321 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1322 file, linenum, args[0], args[1]);
1323 return -1;
1324 }
1325 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1326 }
1327 else {
1328 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1329 return -1;
1330 }
1331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001332#ifdef TPROXY
1333 else if (!strcmp(args[0], "transparent")) {
1334 /* enable transparent proxy connections */
1335 curproxy->options |= PR_O_TRANSP;
1336 }
1337#endif
1338 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001339 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1340 return 0;
1341
Willy Tarreaubaaee002006-06-26 02:48:02 +02001342 if (*(args[1]) == 0) {
1343 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1344 return -1;
1345 }
1346 curproxy->maxconn = atol(args[1]);
1347 }
Willy Tarreau86034312006-12-29 00:10:33 +01001348 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001349 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1350 return 0;
1351
Willy Tarreau86034312006-12-29 00:10:33 +01001352 if (*(args[1]) == 0) {
1353 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1354 return -1;
1355 }
1356 curproxy->fullconn = atol(args[1]);
1357 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1359 if (*(args[1]) == 0) {
1360 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1361 return -1;
1362 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001363 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1364 if (err) {
1365 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1366 file, linenum, *err);
1367 return -1;
1368 }
1369 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 }
1371 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1372 if (curproxy == &defproxy) {
1373 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1374 return -1;
1375 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001376 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1377 return 0;
1378
Willy Tarreaubaaee002006-06-26 02:48:02 +02001379 if (strchr(args[1], ':') == NULL) {
1380 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1381 return -1;
1382 }
1383 curproxy->dispatch_addr = *str2sa(args[1]);
1384 }
1385 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001386 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1387 return 0;
1388
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001389 memcpy(trash, "error near 'balance'", 19);
1390 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1391 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1392 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 }
1395 else if (!strcmp(args[0], "server")) { /* server address */
1396 int cur_arg;
1397 char *rport;
1398 char *raddr;
1399 short realport;
1400 int do_check;
1401
1402 if (curproxy == &defproxy) {
1403 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1404 return -1;
1405 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001406 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1407 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001408
1409 if (!*args[2]) {
1410 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1411 file, linenum, args[0]);
1412 return -1;
1413 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001414
1415 err = invalid_char(args[1]);
1416 if (err) {
1417 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1418 file, linenum, *err, args[1]);
1419 return -1;
1420 }
1421
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1423 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1424 return -1;
1425 }
1426
1427 /* the servers are linked backwards first */
1428 newsrv->next = curproxy->srv;
1429 curproxy->srv = newsrv;
1430 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001431 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001432
1433 LIST_INIT(&newsrv->pendconns);
1434 do_check = 0;
1435 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001436 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001437 newsrv->id = strdup(args[1]);
1438
1439 /* several ways to check the port component :
1440 * - IP => port=+0, relative
1441 * - IP: => port=+0, relative
1442 * - IP:N => port=N, absolute
1443 * - IP:+N => port=+N, relative
1444 * - IP:-N => port=-N, relative
1445 */
1446 raddr = strdup(args[2]);
1447 rport = strchr(raddr, ':');
1448 if (rport) {
1449 *rport++ = 0;
1450 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001451 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001452 newsrv->state |= SRV_MAPPORTS;
1453 } else {
1454 realport = 0;
1455 newsrv->state |= SRV_MAPPORTS;
1456 }
1457
1458 newsrv->addr = *str2sa(raddr);
1459 newsrv->addr.sin_port = htons(realport);
1460 free(raddr);
1461
1462 newsrv->curfd = -1; /* no health-check in progress */
1463 newsrv->inter = DEF_CHKINTR;
1464 newsrv->rise = DEF_RISETIME;
1465 newsrv->fall = DEF_FALLTIME;
1466 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001467 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001468 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001469 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001470
Willy Tarreaubaaee002006-06-26 02:48:02 +02001471 cur_arg = 3;
1472 while (*args[cur_arg]) {
1473 if (!strcmp(args[cur_arg], "cookie")) {
1474 newsrv->cookie = strdup(args[cur_arg + 1]);
1475 newsrv->cklen = strlen(args[cur_arg + 1]);
1476 cur_arg += 2;
1477 }
1478 else if (!strcmp(args[cur_arg], "rise")) {
1479 newsrv->rise = atol(args[cur_arg + 1]);
1480 newsrv->health = newsrv->rise;
1481 cur_arg += 2;
1482 }
1483 else if (!strcmp(args[cur_arg], "fall")) {
1484 newsrv->fall = atol(args[cur_arg + 1]);
1485 cur_arg += 2;
1486 }
1487 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001488 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1489 if (err) {
1490 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1491 file, linenum, *err, newsrv->id);
1492 return -1;
1493 }
1494 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001495 cur_arg += 2;
1496 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001497 else if (!strcmp(args[cur_arg], "addr")) {
1498 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001499 cur_arg += 2;
1500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001501 else if (!strcmp(args[cur_arg], "port")) {
1502 newsrv->check_port = atol(args[cur_arg + 1]);
1503 cur_arg += 2;
1504 }
1505 else if (!strcmp(args[cur_arg], "backup")) {
1506 newsrv->state |= SRV_BACKUP;
1507 cur_arg ++;
1508 }
1509 else if (!strcmp(args[cur_arg], "weight")) {
1510 int w;
1511 w = atol(args[cur_arg + 1]);
1512 if (w < 1 || w > 256) {
1513 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1514 file, linenum, newsrv->id, w);
1515 return -1;
1516 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001517 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001518 cur_arg += 2;
1519 }
1520 else if (!strcmp(args[cur_arg], "minconn")) {
1521 newsrv->minconn = atol(args[cur_arg + 1]);
1522 cur_arg += 2;
1523 }
1524 else if (!strcmp(args[cur_arg], "maxconn")) {
1525 newsrv->maxconn = atol(args[cur_arg + 1]);
1526 cur_arg += 2;
1527 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001528 else if (!strcmp(args[cur_arg], "maxqueue")) {
1529 newsrv->maxqueue = atol(args[cur_arg + 1]);
1530 cur_arg += 2;
1531 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001532 else if (!strcmp(args[cur_arg], "slowstart")) {
1533 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001534 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001535 if (err) {
1536 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1537 file, linenum, *err, newsrv->id);
1538 return -1;
1539 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001540 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001541 cur_arg += 2;
1542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001543 else if (!strcmp(args[cur_arg], "check")) {
1544 global.maxsock++;
1545 do_check = 1;
1546 cur_arg += 1;
1547 }
1548 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1549 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001550#ifdef CONFIG_HAP_CTTPROXY
1551 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1552 file, linenum, "source", "usesrc");
1553#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1555 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001556#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557 return -1;
1558 }
1559 newsrv->state |= SRV_BIND_SRC;
1560 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1561 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001562 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001563#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001564 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001565 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1566 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001567 return -1;
1568 }
1569 if (!*args[cur_arg + 1]) {
1570 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1571 file, linenum, "usesrc");
1572 return -1;
1573 }
1574 if (!strcmp(args[cur_arg + 1], "client")) {
1575 newsrv->state |= SRV_TPROXY_CLI;
1576 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1577 newsrv->state |= SRV_TPROXY_CIP;
1578 } else {
1579 newsrv->state |= SRV_TPROXY_ADDR;
1580 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1581 }
1582 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1583 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001584#else /* no CTTPROXY support */
1585 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1586 file, linenum, "usesrc");
1587 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001588#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001591#ifdef CONFIG_HAP_CTTPROXY
1592 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1593 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1594 file, linenum, "usesrc", "source");
1595 return -1;
1596 }
1597#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 else {
Willy Tarreau9909fc12007-11-30 17:42:05 +01001599 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 +02001600 file, linenum, newsrv->id);
1601 return -1;
1602 }
1603 }
1604
1605 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001606 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1607 newsrv->check_port = newsrv->check_addr.sin_port;
1608
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1610 newsrv->check_port = realport; /* by default */
1611 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001612 /* not yet valid, because no port was set on
1613 * the server either. We'll check if we have
1614 * a known port on the first listener.
1615 */
1616 struct listener *l;
1617 l = curproxy->listen;
1618 if (l) {
1619 int port;
1620 port = (l->addr.ss_family == AF_INET6)
1621 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1622 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1623 newsrv->check_port = port;
1624 }
1625 }
1626 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001627 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1628 file, linenum, newsrv->id);
1629 return -1;
1630 }
1631 newsrv->state |= SRV_CHECKED;
1632 }
1633
1634 if (newsrv->state & SRV_BACKUP)
1635 curproxy->srv_bck++;
1636 else
1637 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001638
1639 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640 }
1641 else if (!strcmp(args[0], "log")) { /* syslog server address */
1642 struct sockaddr_in *sa;
1643 int facility;
1644
1645 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1646 curproxy->logfac1 = global.logfac1;
1647 curproxy->logsrv1 = global.logsrv1;
1648 curproxy->loglev1 = global.loglev1;
1649 curproxy->logfac2 = global.logfac2;
1650 curproxy->logsrv2 = global.logsrv2;
1651 curproxy->loglev2 = global.loglev2;
1652 }
1653 else if (*(args[1]) && *(args[2])) {
1654 int level;
1655
1656 facility = get_log_facility(args[2]);
1657 if (facility < 0) {
1658 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1659 exit(1);
1660 }
1661
1662 level = 7; /* max syslog level = debug */
1663 if (*(args[3])) {
1664 level = get_log_level(args[3]);
1665 if (level < 0) {
1666 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1667 exit(1);
1668 }
1669 }
1670
1671 sa = str2sa(args[1]);
1672 if (!sa->sin_port)
1673 sa->sin_port = htons(SYSLOG_PORT);
1674
1675 if (curproxy->logfac1 == -1) {
1676 curproxy->logsrv1 = *sa;
1677 curproxy->logfac1 = facility;
1678 curproxy->loglev1 = level;
1679 }
1680 else if (curproxy->logfac2 == -1) {
1681 curproxy->logsrv2 = *sa;
1682 curproxy->logfac2 = facility;
1683 curproxy->loglev2 = level;
1684 }
1685 else {
1686 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1687 return -1;
1688 }
1689 }
1690 else {
1691 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1692 file, linenum);
1693 return -1;
1694 }
1695 }
1696 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001697 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1698 return 0;
1699
Willy Tarreaubaaee002006-06-26 02:48:02 +02001700 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001701#ifdef CONFIG_HAP_CTTPROXY
1702 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1703 file, linenum, "source", "usesrc");
1704#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001705 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1706 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001707#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 return -1;
1709 }
1710
1711 curproxy->source_addr = *str2sa(args[1]);
1712 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001713 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001714#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001715 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1716 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1717 file, linenum, "usesrc");
1718 return -1;
1719 }
1720 if (!*args[3]) {
1721 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1722 file, linenum, "usesrc");
1723 return -1;
1724 }
1725
1726 if (!strcmp(args[3], "client")) {
1727 curproxy->options |= PR_O_TPXY_CLI;
1728 } else if (!strcmp(args[3], "clientip")) {
1729 curproxy->options |= PR_O_TPXY_CIP;
1730 } else {
1731 curproxy->options |= PR_O_TPXY_ADDR;
1732 curproxy->tproxy_addr = *str2sa(args[3]);
1733 }
1734 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001735#else /* no CTTPROXY support */
1736 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1737 file, linenum, "usesrc");
1738 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001739#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001740 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001741 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001742#ifdef CONFIG_HAP_CTTPROXY
1743 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1744 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1745 file, linenum, "usesrc", "source");
1746 return -1;
1747 }
1748#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001749 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1750 regex_t *preg;
1751 if (curproxy == &defproxy) {
1752 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1753 return -1;
1754 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001755 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1756 return 0;
1757
Willy Tarreaubaaee002006-06-26 02:48:02 +02001758 if (*(args[1]) == 0 || *(args[2]) == 0) {
1759 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1760 file, linenum, args[0]);
1761 return -1;
1762 }
1763
1764 preg = calloc(1, sizeof(regex_t));
1765 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1766 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1767 return -1;
1768 }
1769
1770 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1771 if (err) {
1772 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1773 file, linenum, *err);
1774 return -1;
1775 }
1776 }
1777 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1778 regex_t *preg;
1779 if (curproxy == &defproxy) {
1780 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1781 return -1;
1782 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001783 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1784 return 0;
1785
Willy Tarreaubaaee002006-06-26 02:48:02 +02001786 if (*(args[1]) == 0) {
1787 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1788 return -1;
1789 }
1790
1791 preg = calloc(1, sizeof(regex_t));
1792 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1793 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1794 return -1;
1795 }
1796
1797 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1798 }
1799 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1800 regex_t *preg;
1801 if (curproxy == &defproxy) {
1802 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1803 return -1;
1804 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001805 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1806 return 0;
1807
Willy Tarreaubaaee002006-06-26 02:48:02 +02001808 if (*(args[1]) == 0) {
1809 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1810 return -1;
1811 }
1812
1813 preg = calloc(1, sizeof(regex_t));
1814 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1815 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1816 return -1;
1817 }
1818
1819 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1820 }
1821 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1822 regex_t *preg;
1823 if (curproxy == &defproxy) {
1824 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1825 return -1;
1826 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001827 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1828 return 0;
1829
Willy Tarreaubaaee002006-06-26 02:48:02 +02001830 if (*(args[1]) == 0) {
1831 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1832 return -1;
1833 }
1834
1835 preg = calloc(1, sizeof(regex_t));
1836 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1837 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1838 return -1;
1839 }
1840
1841 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1842 }
1843 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1844 regex_t *preg;
1845 if (curproxy == &defproxy) {
1846 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1847 return -1;
1848 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001849 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1850 return 0;
1851
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852 if (*(args[1]) == 0) {
1853 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1854 return -1;
1855 }
1856
1857 preg = calloc(1, sizeof(regex_t));
1858 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1859 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1860 return -1;
1861 }
1862
1863 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1864 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001865 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1866 regex_t *preg;
1867 if (curproxy == &defproxy) {
1868 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1869 return -1;
1870 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001871 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1872 return 0;
1873
Willy Tarreaub8750a82006-09-03 09:56:00 +02001874 if (*(args[1]) == 0) {
1875 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1876 return -1;
1877 }
1878
1879 preg = calloc(1, sizeof(regex_t));
1880 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1881 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1882 return -1;
1883 }
1884
1885 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1886 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001887 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1888 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001889 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001890 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1891 return -1;
1892 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001893 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1894 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001895
Willy Tarreau977b8e42006-12-29 14:19:17 +01001896 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001897 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1898 file, linenum, args[0]);
1899 return -1;
1900 }
1901
1902 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001903 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001904 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1905 }
1906
1907 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1908 }
1909 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1910 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001911 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001912 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1913 return -1;
1914 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001915 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1916 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001917
Willy Tarreau977b8e42006-12-29 14:19:17 +01001918 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001919 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1920 file, linenum, args[0]);
1921 return -1;
1922 }
1923
1924 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001925 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001926 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1927 }
1928
1929 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1930 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1932 regex_t *preg;
1933 if (curproxy == &defproxy) {
1934 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1935 return -1;
1936 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001937 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1938 return 0;
1939
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 if (*(args[1]) == 0 || *(args[2]) == 0) {
1941 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1942 file, linenum, args[0]);
1943 return -1;
1944 }
1945
1946 preg = calloc(1, sizeof(regex_t));
1947 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1948 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1949 return -1;
1950 }
1951
1952 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1953 if (err) {
1954 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1955 file, linenum, *err);
1956 return -1;
1957 }
1958 }
1959 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1960 regex_t *preg;
1961 if (curproxy == &defproxy) {
1962 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1963 return -1;
1964 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001965 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1966 return 0;
1967
Willy Tarreaubaaee002006-06-26 02:48:02 +02001968 if (*(args[1]) == 0) {
1969 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1970 return -1;
1971 }
1972
1973 preg = calloc(1, sizeof(regex_t));
1974 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1975 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1976 return -1;
1977 }
1978
1979 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1980 }
1981 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1982 regex_t *preg;
1983 if (curproxy == &defproxy) {
1984 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1985 return -1;
1986 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001987 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1988 return 0;
1989
Willy Tarreaubaaee002006-06-26 02:48:02 +02001990 if (*(args[1]) == 0) {
1991 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1992 return -1;
1993 }
1994
1995 preg = calloc(1, sizeof(regex_t));
1996 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1997 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1998 return -1;
1999 }
2000
2001 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2002 }
2003 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2004 regex_t *preg;
2005 if (curproxy == &defproxy) {
2006 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2007 return -1;
2008 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002009 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2010 return 0;
2011
Willy Tarreaubaaee002006-06-26 02:48:02 +02002012 if (*(args[1]) == 0) {
2013 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2014 return -1;
2015 }
2016
2017 preg = calloc(1, sizeof(regex_t));
2018 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2019 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2020 return -1;
2021 }
2022
2023 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2024 }
2025 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2026 regex_t *preg;
2027 if (curproxy == &defproxy) {
2028 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2029 return -1;
2030 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002031 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2032 return 0;
2033
Willy Tarreaubaaee002006-06-26 02:48:02 +02002034 if (*(args[1]) == 0) {
2035 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2036 return -1;
2037 }
2038
2039 preg = calloc(1, sizeof(regex_t));
2040 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2041 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2042 return -1;
2043 }
2044
2045 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2046 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002047 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2048 regex_t *preg;
2049 if (curproxy == &defproxy) {
2050 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2051 return -1;
2052 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002053 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2054 return 0;
2055
Willy Tarreaub8750a82006-09-03 09:56:00 +02002056 if (*(args[1]) == 0) {
2057 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2058 return -1;
2059 }
2060
2061 preg = calloc(1, sizeof(regex_t));
2062 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2063 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2064 return -1;
2065 }
2066
2067 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2068 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002069 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2070 if (curproxy == &defproxy) {
2071 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2072 return -1;
2073 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002074 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2075 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002076
2077 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2078 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2079 return 0;
2080 }
2081
2082 if (*(args[1]) == 0) {
2083 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2084 return -1;
2085 }
2086
2087 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2088 }
2089 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2090 regex_t *preg;
2091
2092 if (*(args[1]) == 0 || *(args[2]) == 0) {
2093 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2094 file, linenum, args[0]);
2095 return -1;
2096 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002097 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2098 return 0;
2099
Willy Tarreaubaaee002006-06-26 02:48:02 +02002100 preg = calloc(1, sizeof(regex_t));
2101 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2102 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2103 return -1;
2104 }
2105
2106 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2107 if (err) {
2108 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2109 file, linenum, *err);
2110 return -1;
2111 }
2112 }
2113 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2114 regex_t *preg;
2115 if (curproxy == &defproxy) {
2116 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2117 return -1;
2118 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002119 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2120 return 0;
2121
Willy Tarreaubaaee002006-06-26 02:48:02 +02002122 if (*(args[1]) == 0) {
2123 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2124 return -1;
2125 }
2126
2127 preg = calloc(1, sizeof(regex_t));
2128 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2129 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2130 return -1;
2131 }
2132
2133 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2134 if (err) {
2135 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2136 file, linenum, *err);
2137 return -1;
2138 }
2139 }
2140 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2141 regex_t *preg;
2142 if (curproxy == &defproxy) {
2143 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2144 return -1;
2145 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002146 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2147 return 0;
2148
Willy Tarreaubaaee002006-06-26 02:48:02 +02002149 if (*(args[1]) == 0) {
2150 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2151 return -1;
2152 }
2153
2154 preg = calloc(1, sizeof(regex_t));
2155 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2156 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2157 return -1;
2158 }
2159
2160 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2161 if (err) {
2162 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2163 file, linenum, *err);
2164 return -1;
2165 }
2166 }
2167 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2168 regex_t *preg;
2169 if (curproxy == &defproxy) {
2170 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2171 return -1;
2172 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002173 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2174 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002175
2176 if (*(args[1]) == 0 || *(args[2]) == 0) {
2177 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2178 file, linenum, args[0]);
2179 return -1;
2180 }
2181
2182 preg = calloc(1, sizeof(regex_t));
2183 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2184 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2185 return -1;
2186 }
2187
2188 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2189 if (err) {
2190 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2191 file, linenum, *err);
2192 return -1;
2193 }
2194 }
2195 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2196 regex_t *preg;
2197 if (curproxy == &defproxy) {
2198 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2199 return -1;
2200 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002201 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2202 return 0;
2203
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 if (*(args[1]) == 0) {
2205 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2206 return -1;
2207 }
2208
2209 preg = calloc(1, sizeof(regex_t));
2210 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2211 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2212 return -1;
2213 }
2214
2215 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2216 if (err) {
2217 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2218 file, linenum, *err);
2219 return -1;
2220 }
2221 }
2222 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2223 regex_t *preg;
2224 if (curproxy == &defproxy) {
2225 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2226 return -1;
2227 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002228 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2229 return 0;
2230
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 if (*(args[1]) == 0) {
2232 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2233 return -1;
2234 }
2235
2236 preg = calloc(1, sizeof(regex_t));
2237 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2238 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2239 return -1;
2240 }
2241
2242 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2243 if (err) {
2244 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2245 file, linenum, *err);
2246 return -1;
2247 }
2248 }
2249 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2250 if (curproxy == &defproxy) {
2251 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2252 return -1;
2253 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002254 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2255 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256
2257 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2258 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2259 return 0;
2260 }
2261
2262 if (*(args[1]) == 0) {
2263 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2264 return -1;
2265 }
2266
2267 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2268 }
2269 else if (!strcmp(args[0], "errorloc") ||
2270 !strcmp(args[0], "errorloc302") ||
2271 !strcmp(args[0], "errorloc303")) { /* error location */
2272 int errnum, errlen;
2273 char *err;
2274
Willy Tarreau977b8e42006-12-29 14:19:17 +01002275 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2276 return 0;
2277
Willy Tarreaubaaee002006-06-26 02:48:02 +02002278 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002279 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002280 return -1;
2281 }
2282
2283 errnum = atol(args[1]);
2284 if (!strcmp(args[0], "errorloc303")) {
2285 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2286 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2287 } else {
2288 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2289 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2290 }
2291
Willy Tarreau0f772532006-12-23 20:51:41 +01002292 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2293 if (http_err_codes[rc] == errnum) {
2294 if (curproxy->errmsg[rc].str)
2295 free(curproxy->errmsg[rc].str);
2296 curproxy->errmsg[rc].str = err;
2297 curproxy->errmsg[rc].len = errlen;
2298 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002301
2302 if (rc >= HTTP_ERR_SIZE) {
2303 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2304 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002305 free(err);
2306 }
2307 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002308 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2309 int errnum, errlen, fd;
2310 char *err;
2311 struct stat stat;
2312
2313 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2314 return 0;
2315
2316 if (*(args[2]) == 0) {
2317 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2318 return -1;
2319 }
2320
2321 fd = open(args[2], O_RDONLY);
2322 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2323 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2324 file, linenum, args[2], args[1]);
2325 if (fd >= 0)
2326 close(fd);
2327 return -1;
2328 }
2329
2330 if (stat.st_size <= BUFSIZE) {
2331 errlen = stat.st_size;
2332 } else {
2333 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2334 file, linenum, args[2], BUFSIZE);
2335 errlen = BUFSIZE;
2336 }
2337
2338 err = malloc(errlen); /* malloc() must succeed during parsing */
2339 errnum = read(fd, err, errlen);
2340 if (errnum != errlen) {
2341 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2342 file, linenum, args[2], args[1]);
2343 close(fd);
2344 free(err);
2345 return -1;
2346 }
2347 close(fd);
2348
2349 errnum = atol(args[1]);
2350 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2351 if (http_err_codes[rc] == errnum) {
2352 if (curproxy->errmsg[rc].str)
2353 free(curproxy->errmsg[rc].str);
2354 curproxy->errmsg[rc].str = err;
2355 curproxy->errmsg[rc].len = errlen;
2356 break;
2357 }
2358 }
2359
2360 if (rc >= HTTP_ERR_SIZE) {
2361 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2362 file, linenum, errnum);
2363 free(err);
2364 }
2365 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 else {
2367 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2368 return -1;
2369 }
2370 return 0;
2371}
2372
2373
2374/*
2375 * This function reads and parses the configuration file given in the argument.
2376 * returns 0 if OK, -1 if error.
2377 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002378int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002380 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 FILE *f;
2382 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002383 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 int confsect = CFG_NONE;
2385
2386 struct proxy *curproxy = NULL;
2387 struct server *newsrv = NULL;
2388
2389 if ((f=fopen(file,"r")) == NULL)
2390 return -1;
2391
2392 init_default_instance();
2393
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002394 while (fgets(thisline, sizeof(thisline), f) != NULL) {
2395 int arg;
2396 char *end;
2397 char *args[MAX_LINE_ARGS + 1];
2398 char *line = thisline;
2399
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 linenum++;
2401
2402 end = line + strlen(line);
2403
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002404 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2405 /* Check if we reached the limit and the last char is not \n.
2406 * Watch out for the last line without the terminating '\n'!
2407 */
2408 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2409 file, linenum, sizeof(thisline)-1);
2410 return -1;
2411 }
2412
Willy Tarreaubaaee002006-06-26 02:48:02 +02002413 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002414 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 line++;
2416
2417 arg = 0;
2418 args[arg] = line;
2419
2420 while (*line && arg < MAX_LINE_ARGS) {
2421 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2422 * C equivalent value. Other combinations left unchanged (eg: \1).
2423 */
2424 if (*line == '\\') {
2425 int skip = 0;
2426 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2427 *line = line[1];
2428 skip = 1;
2429 }
2430 else if (line[1] == 'r') {
2431 *line = '\r';
2432 skip = 1;
2433 }
2434 else if (line[1] == 'n') {
2435 *line = '\n';
2436 skip = 1;
2437 }
2438 else if (line[1] == 't') {
2439 *line = '\t';
2440 skip = 1;
2441 }
2442 else if (line[1] == 'x') {
2443 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2444 unsigned char hex1, hex2;
2445 hex1 = toupper(line[2]) - '0';
2446 hex2 = toupper(line[3]) - '0';
2447 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2448 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2449 *line = (hex1<<4) + hex2;
2450 skip = 3;
2451 }
2452 else {
2453 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2454 return -1;
2455 }
2456 }
2457 if (skip) {
2458 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2459 end -= skip;
2460 }
2461 line++;
2462 }
2463 else if (*line == '#' || *line == '\n' || *line == '\r') {
2464 /* end of string, end of loop */
2465 *line = 0;
2466 break;
2467 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002468 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002469 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002470 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002471 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 line++;
2473 args[++arg] = line;
2474 }
2475 else {
2476 line++;
2477 }
2478 }
2479
2480 /* empty line */
2481 if (!**args)
2482 continue;
2483
Willy Tarreau540abe42007-05-02 20:50:16 +02002484 /* zero out remaining args and ensure that at least one entry
2485 * is zeroed out.
2486 */
2487 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002488 args[arg] = line;
2489 }
2490
Willy Tarreau977b8e42006-12-29 14:19:17 +01002491 if (!strcmp(args[0], "listen") ||
2492 !strcmp(args[0], "frontend") ||
2493 !strcmp(args[0], "backend") ||
2494 !strcmp(args[0], "ruleset") ||
2495 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 confsect = CFG_LISTEN;
2497 else if (!strcmp(args[0], "global")) /* global config */
2498 confsect = CFG_GLOBAL;
2499 /* else it's a section keyword */
2500
2501 switch (confsect) {
2502 case CFG_LISTEN:
2503 if (cfg_parse_listen(file, linenum, args) < 0)
2504 return -1;
2505 break;
2506 case CFG_GLOBAL:
2507 if (cfg_parse_global(file, linenum, args) < 0)
2508 return -1;
2509 break;
2510 default:
2511 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2512 return -1;
2513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 }
2515 fclose(f);
2516
2517 /*
2518 * Now, check for the integrity of all that we have collected.
2519 */
2520
2521 /* will be needed further to delay some tasks */
2522 tv_now(&now);
2523
2524 if ((curproxy = proxy) == NULL) {
2525 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2526 file);
2527 return -1;
2528 }
2529
2530 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002531 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002532 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002533
Willy Tarreaubaaee002006-06-26 02:48:02 +02002534 if (curproxy->state == PR_STSTOPPED) {
2535 curproxy = curproxy->next;
2536 continue;
2537 }
2538
Willy Tarreau977b8e42006-12-29 14:19:17 +01002539 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2540 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 +01002541 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 cfgerr++;
2543 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002544 else if (curproxy->cap & PR_CAP_BE &&
2545 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002546 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002547 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002548 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2549 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 +01002550 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 cfgerr++;
2552 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002553
Willy Tarreau31682232007-11-29 15:38:04 +01002554 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002556 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002557 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558 cfgerr++;
2559 }
2560#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2561 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002562 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002563 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 cfgerr++;
2565 }
2566#endif
2567 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002568 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002569 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 }
2571 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002572
2573 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002575 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002576 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002579 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002580 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581 }
2582 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002583 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002584 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002586 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002587 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002588 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002589 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002590 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002591 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2592 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002593
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002594 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002595 file, proxy_type_str(curproxy), curproxy->id);
2596 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002598
2599 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2600 if ((newsrv = curproxy->srv) != NULL) {
2601 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2602 file, proxy_type_str(curproxy), curproxy->id);
2603 }
2604 }
2605
2606 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2608 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2609 file, curproxy->id);
2610 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002611 }
2612 }
2613
Willy Tarreau82936582007-11-30 15:20:09 +01002614 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2615 curproxy->options &= ~PR_O_DISABLE404;
2616 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2617 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2618 }
2619
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002620 /* if a default backend was specified, let's find it */
2621 if (curproxy->defbe.name) {
2622 struct proxy *target;
2623
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002624 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2625 if (!target) {
2626 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2627 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002628 cfgerr++;
2629 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002630 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2631 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002632 } else {
2633 free(curproxy->defbe.name);
2634 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002635 }
2636 }
2637
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002638 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002639 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2640 /* map jump target for ACT_SETBE in req_rep chain */
2641 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002642 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002643 struct proxy *target;
2644
Willy Tarreaua496b602006-12-17 23:15:24 +01002645 if (exp->action != ACT_SETBE)
2646 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002647
2648 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2649 if (!target) {
2650 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2651 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002652 cfgerr++;
2653 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002654 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2655 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002656 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002657 } else {
2658 free((void *)exp->replace);
2659 exp->replace = (const char *)target;
2660 }
2661 }
2662 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002663
2664 /* find the target proxy for 'use_backend' rules */
2665 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002666 struct proxy *target;
2667
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002668 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002669
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002670 if (!target) {
2671 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2672 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002673 cfgerr++;
2674 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002675 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2676 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002677 cfgerr++;
2678 } else {
2679 free((void *)rule->be.name);
2680 rule->be.backend = target;
2681 }
2682 }
2683
Willy Tarreau2738a142006-07-08 17:28:09 +02002684 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002685 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->timeout.client)) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02002686 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002687 (!tv_isset(&curproxy->timeout.connect) || !tv_isset(&curproxy->timeout.server))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002688 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002689 " | While not properly invalid, you will certainly encounter various problems\n"
2690 " | with such a configuration. To fix this, please ensure that all following\n"
2691 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002692 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002693 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002694
Willy Tarreau1fa31262007-12-03 00:36:16 +01002695 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
2696 * We must still support older configurations, so let's find out whether those
2697 * parameters have been set or must be copied from contimeouts.
2698 */
2699 if (curproxy != &defproxy) {
2700 if ((curproxy->cap & PR_CAP_FE) &&
2701 (!tv_isset(&curproxy->timeout.tarpit) ||
2702 __tv_iseq(&curproxy->timeout.tarpit, &defproxy.timeout.tarpit))) {
2703 /* tarpit timeout not set. We search in the following order:
2704 * default.tarpit, curr.connect, default.connect.
2705 */
2706 if (tv_isset(&defproxy.timeout.tarpit))
2707 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002708 else if (tv_isset(&curproxy->timeout.connect))
2709 curproxy->timeout.tarpit = curproxy->timeout.connect;
2710 else if (tv_isset(&defproxy.timeout.connect))
2711 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002712 }
2713 if ((curproxy->cap & PR_CAP_BE) &&
2714 (!tv_isset(&curproxy->timeout.queue) ||
2715 __tv_iseq(&curproxy->timeout.queue, &defproxy.timeout.queue))) {
2716 /* queue timeout not set. We search in the following order:
2717 * default.queue, curr.connect, default.connect.
2718 */
2719 if (tv_isset(&defproxy.timeout.queue))
2720 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002721 else if (tv_isset(&curproxy->timeout.connect))
2722 curproxy->timeout.queue = curproxy->timeout.connect;
2723 else if (tv_isset(&defproxy.timeout.connect))
2724 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002725 }
2726 }
2727
Willy Tarreauf3c69202006-07-09 16:42:34 +02002728 if (curproxy->options & PR_O_SSL3_CHK) {
2729 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2730 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2731 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2732 }
2733
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002734 /* The small pools required for the capture lists */
2735 if (curproxy->nb_req_cap)
2736 curproxy->req_cap_pool = create_pool("ptrcap",
2737 curproxy->nb_req_cap * sizeof(char *),
2738 MEM_F_SHARED);
2739 if (curproxy->nb_rsp_cap)
2740 curproxy->rsp_cap_pool = create_pool("ptrcap",
2741 curproxy->nb_rsp_cap * sizeof(char *),
2742 MEM_F_SHARED);
2743
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002744 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2745 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2746 MEM_F_SHARED);
2747
Willy Tarreau86034312006-12-29 00:10:33 +01002748 /* for backwards compatibility with "listen" instances, if
2749 * fullconn is not set but maxconn is set, then maxconn
2750 * is used.
2751 */
2752 if (!curproxy->fullconn)
2753 curproxy->fullconn = curproxy->maxconn;
2754
Willy Tarreaubaaee002006-06-26 02:48:02 +02002755 /* first, we will invert the servers list order */
2756 newsrv = NULL;
2757 while (curproxy->srv) {
2758 struct server *next;
2759
2760 next = curproxy->srv->next;
2761 curproxy->srv->next = newsrv;
2762 newsrv = curproxy->srv;
2763 if (!next)
2764 break;
2765 curproxy->srv = next;
2766 }
2767
Willy Tarreau20697042007-11-15 23:26:18 +01002768 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01002769 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770
Willy Tarreaub625a082007-11-26 01:15:43 +01002771 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01002772 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01002773 fwrr_init_server_groups(curproxy);
2774 else
2775 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002776
2777 if (curproxy->options & PR_O_LOGASAP)
2778 curproxy->to_log &= ~LW_BYTES;
2779
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780 /*
2781 * If this server supports a maxconn parameter, it needs a dedicated
2782 * tasks to fill the emptied slots when a connection leaves.
2783 */
2784 newsrv = curproxy->srv;
2785 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002786 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002787 /* Only 'minconn' was specified, or it was higher than or equal
2788 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2789 * this will avoid further useless expensive computations.
2790 */
2791 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002792 } else if (newsrv->maxconn && !newsrv->minconn) {
2793 /* minconn was not specified, so we set it to maxconn */
2794 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002795 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2796 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002797 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002798 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799 }
2800
2801 if (newsrv->maxconn > 0) {
2802 struct task *t;
2803
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002804 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002805 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2806 return -1;
2807 }
2808
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002809 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002810 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002811 t->state = TASK_IDLE;
2812 t->process = process_srv_queue;
2813 t->context = newsrv;
2814 newsrv->queue_mgt = t;
2815
2816 /* never run it unless specifically woken up */
2817 tv_eternity(&t->expire);
2818 task_queue(t);
2819 }
2820 newsrv = newsrv->next;
2821 }
2822
Willy Tarreaue6b98942007-10-29 01:09:36 +01002823 /* adjust this proxy's listeners */
2824 listener = curproxy->listen;
2825 while (listener) {
2826 if (curproxy->options & PR_O_TCP_NOLING)
2827 listener->options |= LI_O_NOLINGER;
2828 listener->maxconn = curproxy->maxconn;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002829 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002830 listener->accept = event_accept;
2831 listener->private = curproxy;
2832
2833 listener = listener->next;
2834 }
2835
Willy Tarreaubaaee002006-06-26 02:48:02 +02002836 curproxy = curproxy->next;
2837 }
2838 if (cfgerr > 0) {
2839 Alert("Errors found in configuration file, aborting.\n");
2840 return -1;
2841 }
2842 else
2843 return 0;
2844}
2845
2846
2847
2848/*
2849 * Local variables:
2850 * c-indent-level: 8
2851 * c-basic-offset: 8
2852 * End:
2853 */