blob: ae05da0aa4db44721c90e5dea7b83ed9500fbd79 [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{
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010094 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010095 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010096 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010097 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
98 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
99 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
100 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
101 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
102 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
103 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
104 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100106 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
107 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100108#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100109 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
110#endif
111#ifdef TPROXY
112 { "transparent", PR_O_TRANSP, PR_CAP_FE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100113#endif
114
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116};
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 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100264int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265{
266
267 if (!strcmp(args[0], "global")) { /* new section */
268 /* no option, nothing special to do */
269 return 0;
270 }
271 else if (!strcmp(args[0], "daemon")) {
272 global.mode |= MODE_DAEMON;
273 }
274 else if (!strcmp(args[0], "debug")) {
275 global.mode |= MODE_DEBUG;
276 }
277 else if (!strcmp(args[0], "noepoll")) {
278 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
279 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200280 else if (!strcmp(args[0], "nosepoll")) {
281 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
282 }
283 else if (!strcmp(args[0], "nokqueue")) {
284 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286 else if (!strcmp(args[0], "nopoll")) {
287 cfg_polling_mechanism &= ~POLL_USE_POLL;
288 }
289 else if (!strcmp(args[0], "quiet")) {
290 global.mode |= MODE_QUIET;
291 }
292 else if (!strcmp(args[0], "stats")) {
Willy Tarreaufbee7132007-10-18 13:53:22 +0200293 memcpy(trash, "error near 'stats'", 19);
294 if (stats_parse_global((const char **)args + 1, trash, sizeof(trash)) < 0) {
295 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
296 return -1;
297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200299 else if (!strcmp(args[0], "tune.maxpollevents")) {
300 if (global.tune.maxpollevents != 0) {
301 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
302 return 0;
303 }
304 if (*(args[1]) == 0) {
305 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
306 return -1;
307 }
308 global.tune.maxpollevents = atol(args[1]);
309 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200310 else if (!strcmp(args[0], "uid")) {
311 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200312 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200313 return 0;
314 }
315 if (*(args[1]) == 0) {
316 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
317 return -1;
318 }
319 global.uid = atol(args[1]);
320 }
321 else if (!strcmp(args[0], "gid")) {
322 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200323 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324 return 0;
325 }
326 if (*(args[1]) == 0) {
327 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
328 return -1;
329 }
330 global.gid = atol(args[1]);
331 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200332 /* user/group name handling */
333 else if (!strcmp(args[0], "user")) {
334 struct passwd *ha_user;
335 if (global.uid != 0) {
336 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
337 return 0;
338 }
339 errno = 0;
340 ha_user = getpwnam(args[1]);
341 if (ha_user != NULL) {
342 global.uid = (int)ha_user->pw_uid;
343 }
344 else {
345 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
346 exit(1);
347 }
348 }
349 else if (!strcmp(args[0], "group")) {
350 struct group *ha_group;
351 if (global.gid != 0) {
352 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
353 return 0;
354 }
355 errno = 0;
356 ha_group = getgrnam(args[1]);
357 if (ha_group != NULL) {
358 global.gid = (int)ha_group->gr_gid;
359 }
360 else {
361 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
362 exit(1);
363 }
364 }
365 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200366 else if (!strcmp(args[0], "nbproc")) {
367 if (global.nbproc != 0) {
368 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
369 return 0;
370 }
371 if (*(args[1]) == 0) {
372 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
373 return -1;
374 }
375 global.nbproc = atol(args[1]);
376 }
377 else if (!strcmp(args[0], "maxconn")) {
378 if (global.maxconn != 0) {
379 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
380 return 0;
381 }
382 if (*(args[1]) == 0) {
383 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
384 return -1;
385 }
386 global.maxconn = atol(args[1]);
387#ifdef SYSTEM_MAXCONN
388 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
389 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
390 global.maxconn = DEFAULT_MAXCONN;
391 }
392#endif /* SYSTEM_MAXCONN */
393 }
394 else if (!strcmp(args[0], "ulimit-n")) {
395 if (global.rlimit_nofile != 0) {
396 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
397 return 0;
398 }
399 if (*(args[1]) == 0) {
400 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
401 return -1;
402 }
403 global.rlimit_nofile = atol(args[1]);
404 }
405 else if (!strcmp(args[0], "chroot")) {
406 if (global.chroot != NULL) {
407 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
408 return 0;
409 }
410 if (*(args[1]) == 0) {
411 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
412 return -1;
413 }
414 global.chroot = strdup(args[1]);
415 }
416 else if (!strcmp(args[0], "pidfile")) {
417 if (global.pidfile != NULL) {
418 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
419 return 0;
420 }
421 if (*(args[1]) == 0) {
422 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
423 return -1;
424 }
425 global.pidfile = strdup(args[1]);
426 }
427 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100428 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200429 int facility, level;
430
431 if (*(args[1]) == 0 || *(args[2]) == 0) {
432 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
433 return -1;
434 }
435
436 facility = get_log_facility(args[2]);
437 if (facility < 0) {
438 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
439 exit(1);
440 }
441
442 level = 7; /* max syslog level = debug */
443 if (*(args[3])) {
444 level = get_log_level(args[3]);
445 if (level < 0) {
446 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
447 exit(1);
448 }
449 }
450
Robert Tsai81ae1952007-12-05 10:47:29 +0100451 if (args[1][0] == '/') {
452 logsrv.u.addr.sa_family = AF_UNIX;
453 logsrv.u.un = *str2sun(args[1]);
454 } else {
455 logsrv.u.addr.sa_family = AF_INET;
456 logsrv.u.in = *str2sa(args[1]);
457 if (!logsrv.u.in.sin_port)
458 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460
461 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100462 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463 global.logfac1 = facility;
464 global.loglev1 = level;
465 }
466 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100467 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468 global.logfac2 = facility;
469 global.loglev2 = level;
470 }
471 else {
472 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
473 return -1;
474 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200475 }
476 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
477 if (global.spread_checks != 0) {
478 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
479 return 0;
480 }
481 if (*(args[1]) == 0) {
482 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
483 return -1;
484 }
485 global.spread_checks = atol(args[1]);
486 if (global.spread_checks < 0 || global.spread_checks > 50) {
487 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
488 return -1;
489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200490 }
491 else {
492 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
493 return -1;
494 }
495 return 0;
496}
497
498
499static void init_default_instance()
500{
501 memset(&defproxy, 0, sizeof(defproxy));
502 defproxy.mode = PR_MODE_TCP;
503 defproxy.state = PR_STNEW;
504 defproxy.maxconn = cfg_maxpconn;
505 defproxy.conn_retries = CONN_RETRIES;
506 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100507 tv_eternity(&defproxy.timeout.client);
508 tv_eternity(&defproxy.timeout.connect);
509 tv_eternity(&defproxy.timeout.server);
510 tv_eternity(&defproxy.timeout.appsession);
Willy Tarreau1fa31262007-12-03 00:36:16 +0100511 tv_eternity(&defproxy.timeout.queue);
512 tv_eternity(&defproxy.timeout.tarpit);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200513}
514
515/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100516 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
517 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100519int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520{
521 static struct proxy *curproxy = NULL;
522 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200523 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100524 int rc;
525 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200526
Willy Tarreau977b8e42006-12-29 14:19:17 +0100527 if (!strcmp(args[0], "listen"))
528 rc = PR_CAP_LISTEN;
529 else if (!strcmp(args[0], "frontend"))
530 rc = PR_CAP_FE | PR_CAP_RS;
531 else if (!strcmp(args[0], "backend"))
532 rc = PR_CAP_BE | PR_CAP_RS;
533 else if (!strcmp(args[0], "ruleset"))
534 rc = PR_CAP_RS;
535 else
536 rc = PR_CAP_NONE;
537
538 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200539 if (!*args[1]) {
540 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
541 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
542 file, linenum, args[0]);
543 return -1;
544 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200545
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100546 err = invalid_char(args[1]);
547 if (err) {
548 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
549 file, linenum, *err, args[0], args[1]);
550 return -1;
551 }
552
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200553 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
554 /*
555 * If there are two proxies with the same name only following
556 * combinations are allowed:
557 *
558 * listen backend frontend ruleset
559 * listen - - - -
560 * backend - - OK -
561 * frontend - OK - -
562 * ruleset - - - -
563 */
564
565 if (!strcmp(curproxy->id, args[1]) &&
566 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
567 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100568 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
569 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200570 }
571 }
572
Willy Tarreaubaaee002006-06-26 02:48:02 +0200573 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
574 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
575 return -1;
576 }
577
578 curproxy->next = proxy;
579 proxy = curproxy;
580 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200581 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200582 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100583 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200584 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585
Willy Tarreauee991362007-05-14 14:37:50 +0200586 /* Timeouts are defined as -1, so we cannot use the zeroed area
587 * as a default value.
588 */
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100589 tv_eternity(&curproxy->timeout.client);
590 tv_eternity(&curproxy->timeout.server);
591 tv_eternity(&curproxy->timeout.connect);
592 tv_eternity(&curproxy->timeout.appsession);
Willy Tarreau1fa31262007-12-03 00:36:16 +0100593 tv_eternity(&curproxy->timeout.queue);
594 tv_eternity(&curproxy->timeout.tarpit);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200595
596 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200597 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100598 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599
600 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100601 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 curproxy->listen = str2listener(args[2], curproxy->listen);
603 if (!curproxy->listen)
604 return -1;
605 global.maxsock++;
606 }
607
608 /* set default values */
609 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100611 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200612 curproxy->except_net = defproxy.except_net;
613 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200614
Willy Tarreau977b8e42006-12-29 14:19:17 +0100615 if (curproxy->cap & PR_CAP_FE) {
616 curproxy->maxconn = defproxy.maxconn;
617
618 /* initialize error relocations */
619 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
620 if (defproxy.errmsg[rc].str)
621 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
622 }
623
624 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626
Willy Tarreau977b8e42006-12-29 14:19:17 +0100627 if (curproxy->cap & PR_CAP_BE) {
628 curproxy->fullconn = defproxy.fullconn;
629 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630
Willy Tarreau977b8e42006-12-29 14:19:17 +0100631 if (defproxy.check_req)
632 curproxy->check_req = strdup(defproxy.check_req);
633 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634
Willy Tarreau977b8e42006-12-29 14:19:17 +0100635 if (defproxy.cookie_name)
636 curproxy->cookie_name = strdup(defproxy.cookie_name);
637 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100638
639 if (defproxy.url_param_name)
640 curproxy->url_param_name = strdup(defproxy.url_param_name);
641 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100642 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200643
Willy Tarreau977b8e42006-12-29 14:19:17 +0100644 if (curproxy->cap & PR_CAP_RS) {
645 if (defproxy.capture_name)
646 curproxy->capture_name = strdup(defproxy.capture_name);
647 curproxy->capture_namelen = defproxy.capture_namelen;
648 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200650
Willy Tarreau977b8e42006-12-29 14:19:17 +0100651 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100652 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100653 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100654 curproxy->uri_auth = defproxy.uri_auth;
655 curproxy->mon_net = defproxy.mon_net;
656 curproxy->mon_mask = defproxy.mon_mask;
657 if (defproxy.monitor_uri)
658 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
659 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100660 if (defproxy.defbe.name)
661 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100662 }
663
664 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100665 curproxy->timeout.connect = defproxy.timeout.connect;
666 curproxy->timeout.server = defproxy.timeout.server;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100667 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100668 curproxy->source_addr = defproxy.source_addr;
669 }
670
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671 curproxy->mode = defproxy.mode;
672 curproxy->logfac1 = defproxy.logfac1;
673 curproxy->logsrv1 = defproxy.logsrv1;
674 curproxy->loglev1 = defproxy.loglev1;
675 curproxy->logfac2 = defproxy.logfac2;
676 curproxy->logsrv2 = defproxy.logsrv2;
677 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200678 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100679 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
680 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200681
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 return 0;
683 }
684 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
685 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100686 /* FIXME-20070101: we should do this too at the end of the
687 * config parsing to free all default values.
688 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200689 if (defproxy.check_req) free(defproxy.check_req);
690 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100691 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200693 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100694 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100695
696 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
697 if (defproxy.errmsg[rc].len)
698 free(defproxy.errmsg[rc].str);
699 }
700
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 /* we cannot free uri_auth because it might already be used */
702 init_default_instance();
703 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100704 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200705 return 0;
706 }
707 else if (curproxy == NULL) {
708 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
709 return -1;
710 }
711
Willy Tarreau977b8e42006-12-29 14:19:17 +0100712
713 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714 if (!strcmp(args[0], "bind")) { /* new listen addresses */
715 if (curproxy == &defproxy) {
716 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
717 return -1;
718 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100719 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
720 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721
722 if (strchr(args[1], ':') == NULL) {
723 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
724 file, linenum, args[0]);
725 return -1;
726 }
727 curproxy->listen = str2listener(args[1], curproxy->listen);
728 if (!curproxy->listen)
729 return -1;
730 global.maxsock++;
731 return 0;
732 }
733 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
734 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
735 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
736 file, linenum, args[0]);
737 return -1;
738 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100739 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
740 return 0;
741
Willy Tarreaubaaee002006-06-26 02:48:02 +0200742 /* flush useless bits */
743 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
744 return 0;
745 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200746 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100747 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
748 return 0;
749
Willy Tarreau1c47f852006-07-09 08:22:27 +0200750 if (!*args[1]) {
751 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
752 file, linenum, args[0]);
753 return -1;
754 }
755
756 if (curproxy->monitor_uri != NULL)
757 free(curproxy->monitor_uri);
758
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100759 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200760 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100761 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200762 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
763
764 return 0;
765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200766 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
767 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
768 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
769 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
770 else {
771 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
772 return -1;
773 }
774 }
775 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
776 curproxy->state = PR_STSTOPPED;
777 }
778 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
779 curproxy->state = PR_STNEW;
780 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200781 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100782 err = invalid_char(args[1]);
783 if (err) {
784 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
785 file, linenum, *err, args[1]);
786 return -1;
787 }
788
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200789 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
790 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
791 file, linenum, args[1]);
792 return -1;
793 }
794 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200795 else if (!strcmp(args[0], "cookie")) { /* cookie name */
796 int cur_arg;
797 // if (curproxy == &defproxy) {
798 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
799 // return -1;
800 // }
801
Willy Tarreau977b8e42006-12-29 14:19:17 +0100802 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
803 return 0;
804
Willy Tarreaubaaee002006-06-26 02:48:02 +0200805 if (curproxy->cookie_name != NULL) {
806 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
807 // file, linenum);
808 // return 0;
809 free(curproxy->cookie_name);
810 }
811
812 if (*(args[1]) == 0) {
813 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
814 file, linenum, args[0]);
815 return -1;
816 }
817 curproxy->cookie_name = strdup(args[1]);
818 curproxy->cookie_len = strlen(curproxy->cookie_name);
819
820 cur_arg = 2;
821 while (*(args[cur_arg])) {
822 if (!strcmp(args[cur_arg], "rewrite")) {
823 curproxy->options |= PR_O_COOK_RW;
824 }
825 else if (!strcmp(args[cur_arg], "indirect")) {
826 curproxy->options |= PR_O_COOK_IND;
827 }
828 else if (!strcmp(args[cur_arg], "insert")) {
829 curproxy->options |= PR_O_COOK_INS;
830 }
831 else if (!strcmp(args[cur_arg], "nocache")) {
832 curproxy->options |= PR_O_COOK_NOC;
833 }
834 else if (!strcmp(args[cur_arg], "postonly")) {
835 curproxy->options |= PR_O_COOK_POST;
836 }
837 else if (!strcmp(args[cur_arg], "prefix")) {
838 curproxy->options |= PR_O_COOK_PFX;
839 }
840 else {
841 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
842 file, linenum, args[0]);
843 return -1;
844 }
845 cur_arg++;
846 }
847 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
848 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
849 file, linenum);
850 return -1;
851 }
852
853 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
854 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
855 file, linenum);
856 return -1;
857 }
858 }/* end else if (!strcmp(args[0], "cookie")) */
859 else if (!strcmp(args[0], "appsession")) { /* cookie name */
860 // if (curproxy == &defproxy) {
861 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
862 // return -1;
863 // }
864
Willy Tarreau977b8e42006-12-29 14:19:17 +0100865 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
866 return 0;
867
Willy Tarreaubaaee002006-06-26 02:48:02 +0200868 if (curproxy->appsession_name != NULL) {
869 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
870 // file, linenum);
871 // return 0;
872 free(curproxy->appsession_name);
873 }
874
875 if (*(args[5]) == 0) {
876 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
877 file, linenum, args[0]);
878 return -1;
879 }
880 have_appsession = 1;
881 curproxy->appsession_name = strdup(args[1]);
882 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
883 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100884 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
885 if (err) {
886 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
887 file, linenum, *err, args[0]);
888 return -1;
889 }
Willy Tarreauee991362007-05-14 14:37:50 +0200890 if (val > 0)
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100891 __tv_from_ms(&curproxy->timeout.appsession, val);
Willy Tarreauee991362007-05-14 14:37:50 +0200892 else
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100893 tv_eternity(&curproxy->timeout.appsession);
Willy Tarreauee991362007-05-14 14:37:50 +0200894
Willy Tarreau51041c72007-09-09 21:56:53 +0200895 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
896 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897 return -1;
898 }
899 } /* Url App Session */
900 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100901 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
902 return 0;
903
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
905 // if (curproxy == &defproxy) {
906 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
907 // return -1;
908 // }
909
910 if (curproxy->capture_name != NULL) {
911 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
912 // file, linenum, args[0]);
913 // return 0;
914 free(curproxy->capture_name);
915 }
916
917 if (*(args[4]) == 0) {
918 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
919 file, linenum, args[0]);
920 return -1;
921 }
922 curproxy->capture_name = strdup(args[2]);
923 curproxy->capture_namelen = strlen(curproxy->capture_name);
924 curproxy->capture_len = atol(args[4]);
925 if (curproxy->capture_len >= CAPTURE_LEN) {
926 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
927 file, linenum, CAPTURE_LEN - 1);
928 curproxy->capture_len = CAPTURE_LEN - 1;
929 }
930 curproxy->to_log |= LW_COOKIE;
931 }
932 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
933 struct cap_hdr *hdr;
934
935 if (curproxy == &defproxy) {
936 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
937 return -1;
938 }
939
940 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
941 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
942 file, linenum, args[0], args[1]);
943 return -1;
944 }
945
946 hdr = calloc(sizeof(struct cap_hdr), 1);
947 hdr->next = curproxy->req_cap;
948 hdr->name = strdup(args[3]);
949 hdr->namelen = strlen(args[3]);
950 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200951 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 hdr->index = curproxy->nb_req_cap++;
953 curproxy->req_cap = hdr;
954 curproxy->to_log |= LW_REQHDR;
955 }
956 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
957 struct cap_hdr *hdr;
958
959 if (curproxy == &defproxy) {
960 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
961 return -1;
962 }
963
964 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
965 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
966 file, linenum, args[0], args[1]);
967 return -1;
968 }
969 hdr = calloc(sizeof(struct cap_hdr), 1);
970 hdr->next = curproxy->rsp_cap;
971 hdr->name = strdup(args[3]);
972 hdr->namelen = strlen(args[3]);
973 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200974 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200975 hdr->index = curproxy->nb_rsp_cap++;
976 curproxy->rsp_cap = hdr;
977 curproxy->to_log |= LW_RSPHDR;
978 }
979 else {
980 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
981 file, linenum, args[0]);
982 return -1;
983 }
984 }
Willy Tarreaue219db72007-12-03 01:30:13 +0100985 else if (!strcmp(args[0], "contimeout") || !strcmp(args[0], "clitimeout") ||
986 !strcmp(args[0], "srvtimeout") || !strcmp(args[0], "timeout")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100987
Willy Tarreaue219db72007-12-03 01:30:13 +0100988 /* either we have {con|srv|cli}timeout <value> or we have the
989 * new form: timeout <type> <value>. The parser needs the word
990 * preceeding the value.
991 */
992 const char **start_arg = (const char **)args;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100993
Willy Tarreaue219db72007-12-03 01:30:13 +0100994 if (strcmp(args[0], "timeout") == 0)
995 start_arg++;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100996
Willy Tarreaue219db72007-12-03 01:30:13 +0100997 snprintf(trash, sizeof(trash), "error near '%s'", args[0]);
998 rc = proxy_parse_timeout(start_arg, curproxy, &defproxy, trash, sizeof(trash));
999 if (rc < 0) {
1000 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001001 return -1;
1002 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001003 if (rc > 0)
1004 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005 }
1006 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001007 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1008 return 0;
1009
Willy Tarreaubaaee002006-06-26 02:48:02 +02001010 if (*(args[1]) == 0) {
1011 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1012 file, linenum, args[0]);
1013 return -1;
1014 }
1015 curproxy->conn_retries = atol(args[1]);
1016 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001017 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1018 int pol = ACL_COND_NONE;
1019 struct acl_cond *cond;
1020
1021 if (!strcmp(args[1], "if"))
1022 pol = ACL_COND_IF;
1023 else if (!strcmp(args[1], "unless"))
1024 pol = ACL_COND_UNLESS;
1025
1026 if (pol == ACL_COND_NONE) {
1027 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1028 file, linenum, args[0]);
1029 return -1;
1030 }
1031
1032 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1033 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1034 file, linenum);
1035 return -1;
1036 }
1037 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1038 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001039 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1040 int pol = ACL_COND_NONE;
1041 struct acl_cond *cond;
1042 struct switching_rule *rule;
1043
1044 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1045 return 0;
1046
1047 if (*(args[1]) == 0) {
1048 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1049 return -1;
1050 }
1051
1052 if (!strcmp(args[2], "if"))
1053 pol = ACL_COND_IF;
1054 else if (!strcmp(args[2], "unless"))
1055 pol = ACL_COND_UNLESS;
1056
1057 if (pol == ACL_COND_NONE) {
1058 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1059 file, linenum, args[0]);
1060 return -1;
1061 }
1062
1063 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1064 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1065 file, linenum);
1066 return -1;
1067 }
1068
1069 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1070 rule->cond = cond;
1071 rule->be.name = strdup(args[1]);
1072 LIST_INIT(&rule->list);
1073 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1074 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001075 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001076 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1077 return 0;
1078
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1080 curproxy->uri_auth = NULL; /* we must detach from the default config */
1081
1082 if (*(args[1]) == 0) {
1083 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1084 return -1;
1085 } else if (!strcmp(args[1], "uri")) {
1086 if (*(args[2]) == 0) {
1087 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1088 return -1;
1089 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1090 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1091 return -1;
1092 }
1093 } else if (!strcmp(args[1], "realm")) {
1094 if (*(args[2]) == 0) {
1095 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1096 return -1;
1097 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1098 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1099 return -1;
1100 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001101 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001102 unsigned interval;
1103
1104 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1105 if (err) {
1106 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1107 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001108 return -1;
1109 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1110 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1111 return -1;
1112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001113 } else if (!strcmp(args[1], "auth")) {
1114 if (*(args[2]) == 0) {
1115 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1116 return -1;
1117 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1118 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1119 return -1;
1120 }
1121 } else if (!strcmp(args[1], "scope")) {
1122 if (*(args[2]) == 0) {
1123 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1124 return -1;
1125 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1126 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1127 return -1;
1128 }
1129 } else if (!strcmp(args[1], "enable")) {
1130 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1131 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1132 return -1;
1133 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001134 } else if (!strcmp(args[1], "hide-version")) {
1135 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1136 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1137 return -1;
1138 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001139 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001140 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 file, linenum, args[0]);
1142 return -1;
1143 }
1144 }
1145 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001146 int optnum;
1147
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001148 if (*(args[1]) == '\0') {
1149 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1150 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151 return -1;
1152 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001153
1154 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1155 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1156 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1157 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001158
1159 if (!inv)
1160 curproxy->options |= cfg_opts[optnum].val;
1161 else
1162 curproxy->options &= ~cfg_opts[optnum].val;
1163
Willy Tarreau13943ab2006-12-31 00:24:10 +01001164 return 0;
1165 }
1166 }
1167
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001168 if (inv) {
1169 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1170 file, linenum, args[1]);
1171 return -1;
1172 }
1173
Willy Tarreau13943ab2006-12-31 00:24:10 +01001174 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001175 /* generate a complete HTTP log */
1176 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1177 else if (!strcmp(args[1], "tcplog"))
1178 /* generate a detailed TCP log */
1179 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001180 else if (!strcmp(args[1], "tcpka")) {
1181 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001182 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1183 return 0;
1184
1185 if (curproxy->cap & PR_CAP_FE)
1186 curproxy->options |= PR_O_TCP_CLI_KA;
1187 if (curproxy->cap & PR_CAP_BE)
1188 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001189 }
1190 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001191 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1192 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 /* use HTTP request to check servers' health */
1194 if (curproxy->check_req != NULL) {
1195 free(curproxy->check_req);
1196 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001197 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001198 curproxy->options &= ~PR_O_SMTP_CHK;
1199 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001200 if (!*args[2]) { /* no argument */
1201 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1202 curproxy->check_len = strlen(DEF_CHECK_REQ);
1203 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001204 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 curproxy->check_req = (char *)malloc(reqlen);
1206 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1207 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1208 } else { /* more arguments : METHOD URI [HTTP_VER] */
1209 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1210 if (*args[4])
1211 reqlen += strlen(args[4]);
1212 else
1213 reqlen += strlen("HTTP/1.0");
1214
1215 curproxy->check_req = (char *)malloc(reqlen);
1216 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1217 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1218 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001219 }
1220 else if (!strcmp(args[1], "ssl-hello-chk")) {
1221 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001222 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1223 return 0;
1224
Willy Tarreauf3c69202006-07-09 16:42:34 +02001225 if (curproxy->check_req != NULL) {
1226 free(curproxy->check_req);
1227 }
1228 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001229 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001230 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001231 }
Willy Tarreau23677902007-05-08 23:50:35 +02001232 else if (!strcmp(args[1], "smtpchk")) {
1233 /* use SMTP request to check servers' health */
1234 if (curproxy->check_req != NULL) {
1235 free(curproxy->check_req);
1236 }
1237 curproxy->options &= ~PR_O_HTTP_CHK;
1238 curproxy->options &= ~PR_O_SSL3_CHK;
1239 curproxy->options |= PR_O_SMTP_CHK;
1240
1241 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1242 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1243 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1244 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1245 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1246 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1247 curproxy->check_req = (char *)malloc(reqlen);
1248 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1249 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1250 } else {
1251 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1252 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1253 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1254 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1255 }
1256 }
1257 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001258 else if (!strcmp(args[1], "forwardfor")) {
1259 /* insert x-forwarded-for field, but not for the
1260 * IP address listed as an except.
1261 */
1262 if (*(args[2])) {
1263 if (!strcmp(args[2], "except")) {
1264 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1265 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1266 file, linenum, args[0]);
1267 return -1;
1268 }
1269 /* flush useless bits */
1270 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1271 } else {
1272 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1273 file, linenum, args[0]);
1274 return -1;
1275 }
1276 }
1277 curproxy->options |= PR_O_FWDFOR;
1278 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001279 else {
1280 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1281 return -1;
1282 }
1283 return 0;
1284 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001285 else if (!strcmp(args[0], "default_backend")) {
1286 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1287 return 0;
1288
1289 if (*(args[1]) == 0) {
1290 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1291 return -1;
1292 }
1293 if (curproxy->defbe.name)
1294 free(curproxy->defbe.name);
1295 curproxy->defbe.name = strdup(args[1]);
1296 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001297 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001298 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1299 return 0;
1300
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001301 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1302 file, linenum, args[0]);
1303
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304 /* enable reconnections to dispatch */
1305 curproxy->options |= PR_O_REDISP;
1306 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001307 else if (!strcmp(args[0], "http-check")) {
1308 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1309 return 0;
1310
1311 if (strcmp(args[1], "disable-on-404") == 0) {
1312 /* enable a graceful server shutdown on an HTTP 404 response */
1313 curproxy->options |= PR_O_DISABLE404;
1314 }
1315 else {
1316 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1317 return -1;
1318 }
1319 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001320 else if (!strcmp(args[0], "monitor")) {
1321 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1322 return 0;
1323
1324 if (strcmp(args[1], "fail") == 0) {
1325 /* add a condition to fail monitor requests */
1326 int pol = ACL_COND_NONE;
1327 struct acl_cond *cond;
1328
1329 if (!strcmp(args[2], "if"))
1330 pol = ACL_COND_IF;
1331 else if (!strcmp(args[2], "unless"))
1332 pol = ACL_COND_UNLESS;
1333
1334 if (pol == ACL_COND_NONE) {
1335 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1336 file, linenum, args[0], args[1]);
1337 return -1;
1338 }
1339
1340 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1341 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1342 file, linenum, args[0], args[1]);
1343 return -1;
1344 }
1345 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1346 }
1347 else {
1348 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1349 return -1;
1350 }
1351 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001352#ifdef TPROXY
1353 else if (!strcmp(args[0], "transparent")) {
1354 /* enable transparent proxy connections */
1355 curproxy->options |= PR_O_TRANSP;
1356 }
1357#endif
1358 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001359 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1360 return 0;
1361
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 if (*(args[1]) == 0) {
1363 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1364 return -1;
1365 }
1366 curproxy->maxconn = atol(args[1]);
1367 }
Willy Tarreau86034312006-12-29 00:10:33 +01001368 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001369 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1370 return 0;
1371
Willy Tarreau86034312006-12-29 00:10:33 +01001372 if (*(args[1]) == 0) {
1373 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1374 return -1;
1375 }
1376 curproxy->fullconn = atol(args[1]);
1377 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1379 if (*(args[1]) == 0) {
1380 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1381 return -1;
1382 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001383 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1384 if (err) {
1385 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1386 file, linenum, *err);
1387 return -1;
1388 }
1389 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390 }
1391 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1392 if (curproxy == &defproxy) {
1393 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1394 return -1;
1395 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001396 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1397 return 0;
1398
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 if (strchr(args[1], ':') == NULL) {
1400 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1401 return -1;
1402 }
1403 curproxy->dispatch_addr = *str2sa(args[1]);
1404 }
1405 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001406 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1407 return 0;
1408
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001409 memcpy(trash, "error near 'balance'", 19);
1410 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1411 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1412 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001413 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 }
1415 else if (!strcmp(args[0], "server")) { /* server address */
1416 int cur_arg;
1417 char *rport;
1418 char *raddr;
1419 short realport;
1420 int do_check;
1421
1422 if (curproxy == &defproxy) {
1423 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1424 return -1;
1425 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001426 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1427 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001428
1429 if (!*args[2]) {
1430 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1431 file, linenum, args[0]);
1432 return -1;
1433 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001434
1435 err = invalid_char(args[1]);
1436 if (err) {
1437 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1438 file, linenum, *err, args[1]);
1439 return -1;
1440 }
1441
Willy Tarreaubaaee002006-06-26 02:48:02 +02001442 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1443 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1444 return -1;
1445 }
1446
1447 /* the servers are linked backwards first */
1448 newsrv->next = curproxy->srv;
1449 curproxy->srv = newsrv;
1450 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001451 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001452
1453 LIST_INIT(&newsrv->pendconns);
1454 do_check = 0;
1455 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001456 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 newsrv->id = strdup(args[1]);
1458
1459 /* several ways to check the port component :
1460 * - IP => port=+0, relative
1461 * - IP: => port=+0, relative
1462 * - IP:N => port=N, absolute
1463 * - IP:+N => port=+N, relative
1464 * - IP:-N => port=-N, relative
1465 */
1466 raddr = strdup(args[2]);
1467 rport = strchr(raddr, ':');
1468 if (rport) {
1469 *rport++ = 0;
1470 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001471 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472 newsrv->state |= SRV_MAPPORTS;
1473 } else {
1474 realport = 0;
1475 newsrv->state |= SRV_MAPPORTS;
1476 }
1477
1478 newsrv->addr = *str2sa(raddr);
1479 newsrv->addr.sin_port = htons(realport);
1480 free(raddr);
1481
1482 newsrv->curfd = -1; /* no health-check in progress */
1483 newsrv->inter = DEF_CHKINTR;
1484 newsrv->rise = DEF_RISETIME;
1485 newsrv->fall = DEF_FALLTIME;
1486 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001487 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001488 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001489 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001490
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491 cur_arg = 3;
1492 while (*args[cur_arg]) {
1493 if (!strcmp(args[cur_arg], "cookie")) {
1494 newsrv->cookie = strdup(args[cur_arg + 1]);
1495 newsrv->cklen = strlen(args[cur_arg + 1]);
1496 cur_arg += 2;
1497 }
1498 else if (!strcmp(args[cur_arg], "rise")) {
1499 newsrv->rise = atol(args[cur_arg + 1]);
1500 newsrv->health = newsrv->rise;
1501 cur_arg += 2;
1502 }
1503 else if (!strcmp(args[cur_arg], "fall")) {
1504 newsrv->fall = atol(args[cur_arg + 1]);
1505 cur_arg += 2;
1506 }
1507 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001508 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1509 if (err) {
1510 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1511 file, linenum, *err, newsrv->id);
1512 return -1;
1513 }
1514 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515 cur_arg += 2;
1516 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001517 else if (!strcmp(args[cur_arg], "addr")) {
1518 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001519 cur_arg += 2;
1520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001521 else if (!strcmp(args[cur_arg], "port")) {
1522 newsrv->check_port = atol(args[cur_arg + 1]);
1523 cur_arg += 2;
1524 }
1525 else if (!strcmp(args[cur_arg], "backup")) {
1526 newsrv->state |= SRV_BACKUP;
1527 cur_arg ++;
1528 }
1529 else if (!strcmp(args[cur_arg], "weight")) {
1530 int w;
1531 w = atol(args[cur_arg + 1]);
1532 if (w < 1 || w > 256) {
1533 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1534 file, linenum, newsrv->id, w);
1535 return -1;
1536 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001537 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001538 cur_arg += 2;
1539 }
1540 else if (!strcmp(args[cur_arg], "minconn")) {
1541 newsrv->minconn = atol(args[cur_arg + 1]);
1542 cur_arg += 2;
1543 }
1544 else if (!strcmp(args[cur_arg], "maxconn")) {
1545 newsrv->maxconn = atol(args[cur_arg + 1]);
1546 cur_arg += 2;
1547 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001548 else if (!strcmp(args[cur_arg], "maxqueue")) {
1549 newsrv->maxqueue = atol(args[cur_arg + 1]);
1550 cur_arg += 2;
1551 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001552 else if (!strcmp(args[cur_arg], "slowstart")) {
1553 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001554 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001555 if (err) {
1556 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1557 file, linenum, *err, newsrv->id);
1558 return -1;
1559 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001560 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001561 cur_arg += 2;
1562 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 else if (!strcmp(args[cur_arg], "check")) {
1564 global.maxsock++;
1565 do_check = 1;
1566 cur_arg += 1;
1567 }
1568 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1569 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001570#ifdef CONFIG_HAP_CTTPROXY
1571 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1572 file, linenum, "source", "usesrc");
1573#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001574 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1575 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001576#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577 return -1;
1578 }
1579 newsrv->state |= SRV_BIND_SRC;
1580 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1581 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001582 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001583#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001584 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001585 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1586 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001587 return -1;
1588 }
1589 if (!*args[cur_arg + 1]) {
1590 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1591 file, linenum, "usesrc");
1592 return -1;
1593 }
1594 if (!strcmp(args[cur_arg + 1], "client")) {
1595 newsrv->state |= SRV_TPROXY_CLI;
1596 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1597 newsrv->state |= SRV_TPROXY_CIP;
1598 } else {
1599 newsrv->state |= SRV_TPROXY_ADDR;
1600 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1601 }
1602 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1603 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001604#else /* no CTTPROXY support */
1605 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1606 file, linenum, "usesrc");
1607 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001608#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001610 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001611#ifdef CONFIG_HAP_CTTPROXY
1612 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1613 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1614 file, linenum, "usesrc", "source");
1615 return -1;
1616 }
1617#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001618 else {
Willy Tarreau9909fc12007-11-30 17:42:05 +01001619 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 +02001620 file, linenum, newsrv->id);
1621 return -1;
1622 }
1623 }
1624
1625 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001626 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1627 newsrv->check_port = newsrv->check_addr.sin_port;
1628
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1630 newsrv->check_port = realport; /* by default */
1631 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001632 /* not yet valid, because no port was set on
1633 * the server either. We'll check if we have
1634 * a known port on the first listener.
1635 */
1636 struct listener *l;
1637 l = curproxy->listen;
1638 if (l) {
1639 int port;
1640 port = (l->addr.ss_family == AF_INET6)
1641 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1642 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1643 newsrv->check_port = port;
1644 }
1645 }
1646 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001647 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1648 file, linenum, newsrv->id);
1649 return -1;
1650 }
1651 newsrv->state |= SRV_CHECKED;
1652 }
1653
1654 if (newsrv->state & SRV_BACKUP)
1655 curproxy->srv_bck++;
1656 else
1657 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001658
1659 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001660 }
1661 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001662 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001663 int facility;
1664
1665 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1666 curproxy->logfac1 = global.logfac1;
1667 curproxy->logsrv1 = global.logsrv1;
1668 curproxy->loglev1 = global.loglev1;
1669 curproxy->logfac2 = global.logfac2;
1670 curproxy->logsrv2 = global.logsrv2;
1671 curproxy->loglev2 = global.loglev2;
1672 }
1673 else if (*(args[1]) && *(args[2])) {
1674 int level;
1675
1676 facility = get_log_facility(args[2]);
1677 if (facility < 0) {
1678 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1679 exit(1);
1680 }
1681
1682 level = 7; /* max syslog level = debug */
1683 if (*(args[3])) {
1684 level = get_log_level(args[3]);
1685 if (level < 0) {
1686 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1687 exit(1);
1688 }
1689 }
1690
Robert Tsai81ae1952007-12-05 10:47:29 +01001691 if (args[1][0] == '/') {
1692 logsrv.u.addr.sa_family = AF_UNIX;
1693 logsrv.u.un = *str2sun(args[1]);
1694 } else {
1695 logsrv.u.addr.sa_family = AF_INET;
1696 logsrv.u.in = *str2sa(args[1]);
1697 if (!logsrv.u.in.sin_port) {
1698 logsrv.u.in.sin_port =
1699 htons(SYSLOG_PORT);
1700 }
1701 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001702
1703 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001704 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001705 curproxy->logfac1 = facility;
1706 curproxy->loglev1 = level;
1707 }
1708 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001709 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710 curproxy->logfac2 = facility;
1711 curproxy->loglev2 = level;
1712 }
1713 else {
1714 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1715 return -1;
1716 }
1717 }
1718 else {
1719 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1720 file, linenum);
1721 return -1;
1722 }
1723 }
1724 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001725 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1726 return 0;
1727
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001729#ifdef CONFIG_HAP_CTTPROXY
1730 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1731 file, linenum, "source", "usesrc");
1732#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001733 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1734 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001735#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 return -1;
1737 }
1738
1739 curproxy->source_addr = *str2sa(args[1]);
1740 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001741 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001742#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001743 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1744 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1745 file, linenum, "usesrc");
1746 return -1;
1747 }
1748 if (!*args[3]) {
1749 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1750 file, linenum, "usesrc");
1751 return -1;
1752 }
1753
1754 if (!strcmp(args[3], "client")) {
1755 curproxy->options |= PR_O_TPXY_CLI;
1756 } else if (!strcmp(args[3], "clientip")) {
1757 curproxy->options |= PR_O_TPXY_CIP;
1758 } else {
1759 curproxy->options |= PR_O_TPXY_ADDR;
1760 curproxy->tproxy_addr = *str2sa(args[3]);
1761 }
1762 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001763#else /* no CTTPROXY support */
1764 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1765 file, linenum, "usesrc");
1766 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001767#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001768 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001769 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001770#ifdef CONFIG_HAP_CTTPROXY
1771 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1772 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1773 file, linenum, "usesrc", "source");
1774 return -1;
1775 }
1776#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace 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 || *(args[2]) == 0) {
1787 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1788 file, linenum, args[0]);
1789 return -1;
1790 }
1791
1792 preg = calloc(1, sizeof(regex_t));
1793 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1794 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1795 return -1;
1796 }
1797
1798 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1799 if (err) {
1800 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1801 file, linenum, *err);
1802 return -1;
1803 }
1804 }
1805 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1806 regex_t *preg;
1807 if (curproxy == &defproxy) {
1808 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1809 return -1;
1810 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001811 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1812 return 0;
1813
Willy Tarreaubaaee002006-06-26 02:48:02 +02001814 if (*(args[1]) == 0) {
1815 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1816 return -1;
1817 }
1818
1819 preg = calloc(1, sizeof(regex_t));
1820 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1821 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1822 return -1;
1823 }
1824
1825 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1826 }
1827 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1828 regex_t *preg;
1829 if (curproxy == &defproxy) {
1830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1831 return -1;
1832 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001833 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1834 return 0;
1835
Willy Tarreaubaaee002006-06-26 02:48:02 +02001836 if (*(args[1]) == 0) {
1837 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1838 return -1;
1839 }
1840
1841 preg = calloc(1, sizeof(regex_t));
1842 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1843 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1844 return -1;
1845 }
1846
1847 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1848 }
1849 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1850 regex_t *preg;
1851 if (curproxy == &defproxy) {
1852 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1853 return -1;
1854 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001855 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1856 return 0;
1857
Willy Tarreaubaaee002006-06-26 02:48:02 +02001858 if (*(args[1]) == 0) {
1859 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1860 return -1;
1861 }
1862
1863 preg = calloc(1, sizeof(regex_t));
1864 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1865 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1866 return -1;
1867 }
1868
1869 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1870 }
1871 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1872 regex_t *preg;
1873 if (curproxy == &defproxy) {
1874 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1875 return -1;
1876 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001877 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1878 return 0;
1879
Willy Tarreaubaaee002006-06-26 02:48:02 +02001880 if (*(args[1]) == 0) {
1881 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1882 return -1;
1883 }
1884
1885 preg = calloc(1, sizeof(regex_t));
1886 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1887 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1888 return -1;
1889 }
1890
1891 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1892 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001893 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1894 regex_t *preg;
1895 if (curproxy == &defproxy) {
1896 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1897 return -1;
1898 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001899 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1900 return 0;
1901
Willy Tarreaub8750a82006-09-03 09:56:00 +02001902 if (*(args[1]) == 0) {
1903 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1904 return -1;
1905 }
1906
1907 preg = calloc(1, sizeof(regex_t));
1908 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1909 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1910 return -1;
1911 }
1912
1913 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1914 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001915 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1916 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001917 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001918 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1919 return -1;
1920 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001921 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1922 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001923
Willy Tarreau977b8e42006-12-29 14:19:17 +01001924 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001925 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1926 file, linenum, args[0]);
1927 return -1;
1928 }
1929
1930 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001931 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001932 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1933 }
1934
1935 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1936 }
1937 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1938 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001939 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001940 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1941 return -1;
1942 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001943 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1944 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001945
Willy Tarreau977b8e42006-12-29 14:19:17 +01001946 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001947 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1948 file, linenum, args[0]);
1949 return -1;
1950 }
1951
1952 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001953 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001954 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1955 }
1956
1957 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1958 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001959 else if (!strcmp(args[0], "reqirep")) { /* replace 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 || *(args[2]) == 0) {
1969 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1970 file, linenum, args[0]);
1971 return -1;
1972 }
1973
1974 preg = calloc(1, sizeof(regex_t));
1975 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1976 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1977 return -1;
1978 }
1979
1980 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1981 if (err) {
1982 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1983 file, linenum, *err);
1984 return -1;
1985 }
1986 }
1987 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1988 regex_t *preg;
1989 if (curproxy == &defproxy) {
1990 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1991 return -1;
1992 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001993 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1994 return 0;
1995
Willy Tarreaubaaee002006-06-26 02:48:02 +02001996 if (*(args[1]) == 0) {
1997 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1998 return -1;
1999 }
2000
2001 preg = calloc(1, sizeof(regex_t));
2002 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2003 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2004 return -1;
2005 }
2006
2007 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2008 }
2009 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2010 regex_t *preg;
2011 if (curproxy == &defproxy) {
2012 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2013 return -1;
2014 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002015 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2016 return 0;
2017
Willy Tarreaubaaee002006-06-26 02:48:02 +02002018 if (*(args[1]) == 0) {
2019 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2020 return -1;
2021 }
2022
2023 preg = calloc(1, sizeof(regex_t));
2024 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2025 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2026 return -1;
2027 }
2028
2029 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2030 }
2031 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2032 regex_t *preg;
2033 if (curproxy == &defproxy) {
2034 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2035 return -1;
2036 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002037 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2038 return 0;
2039
Willy Tarreaubaaee002006-06-26 02:48:02 +02002040 if (*(args[1]) == 0) {
2041 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2042 return -1;
2043 }
2044
2045 preg = calloc(1, sizeof(regex_t));
2046 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2047 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2048 return -1;
2049 }
2050
2051 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2052 }
2053 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2054 regex_t *preg;
2055 if (curproxy == &defproxy) {
2056 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2057 return -1;
2058 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002059 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2060 return 0;
2061
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062 if (*(args[1]) == 0) {
2063 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2064 return -1;
2065 }
2066
2067 preg = calloc(1, sizeof(regex_t));
2068 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2069 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2070 return -1;
2071 }
2072
2073 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2074 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002075 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2076 regex_t *preg;
2077 if (curproxy == &defproxy) {
2078 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2079 return -1;
2080 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002081 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2082 return 0;
2083
Willy Tarreaub8750a82006-09-03 09:56:00 +02002084 if (*(args[1]) == 0) {
2085 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2086 return -1;
2087 }
2088
2089 preg = calloc(1, sizeof(regex_t));
2090 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2091 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2092 return -1;
2093 }
2094
2095 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2096 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2098 if (curproxy == &defproxy) {
2099 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2100 return -1;
2101 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002102 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2103 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104
2105 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2106 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2107 return 0;
2108 }
2109
2110 if (*(args[1]) == 0) {
2111 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2112 return -1;
2113 }
2114
2115 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2116 }
2117 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2118 regex_t *preg;
2119
2120 if (*(args[1]) == 0 || *(args[2]) == 0) {
2121 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2122 file, linenum, args[0]);
2123 return -1;
2124 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002125 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2126 return 0;
2127
Willy Tarreaubaaee002006-06-26 02:48:02 +02002128 preg = calloc(1, sizeof(regex_t));
2129 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2130 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2131 return -1;
2132 }
2133
2134 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2135 if (err) {
2136 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2137 file, linenum, *err);
2138 return -1;
2139 }
2140 }
2141 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2142 regex_t *preg;
2143 if (curproxy == &defproxy) {
2144 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2145 return -1;
2146 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002147 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2148 return 0;
2149
Willy Tarreaubaaee002006-06-26 02:48:02 +02002150 if (*(args[1]) == 0) {
2151 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2152 return -1;
2153 }
2154
2155 preg = calloc(1, sizeof(regex_t));
2156 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2157 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2158 return -1;
2159 }
2160
2161 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2162 if (err) {
2163 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2164 file, linenum, *err);
2165 return -1;
2166 }
2167 }
2168 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2169 regex_t *preg;
2170 if (curproxy == &defproxy) {
2171 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2172 return -1;
2173 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002174 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2175 return 0;
2176
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 if (*(args[1]) == 0) {
2178 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2179 return -1;
2180 }
2181
2182 preg = calloc(1, sizeof(regex_t));
2183 if (regcomp(preg, args[1], REG_EXTENDED) != 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_DENY, 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], "rspirep")) { /* replace 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;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203
2204 if (*(args[1]) == 0 || *(args[2]) == 0) {
2205 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2206 file, linenum, args[0]);
2207 return -1;
2208 }
2209
2210 preg = calloc(1, sizeof(regex_t));
2211 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2212 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2213 return -1;
2214 }
2215
2216 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2217 if (err) {
2218 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2219 file, linenum, *err);
2220 return -1;
2221 }
2222 }
2223 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2224 regex_t *preg;
2225 if (curproxy == &defproxy) {
2226 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2227 return -1;
2228 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002229 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2230 return 0;
2231
Willy Tarreaubaaee002006-06-26 02:48:02 +02002232 if (*(args[1]) == 0) {
2233 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2234 return -1;
2235 }
2236
2237 preg = calloc(1, sizeof(regex_t));
2238 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2239 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2240 return -1;
2241 }
2242
2243 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2244 if (err) {
2245 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2246 file, linenum, *err);
2247 return -1;
2248 }
2249 }
2250 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2251 regex_t *preg;
2252 if (curproxy == &defproxy) {
2253 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2254 return -1;
2255 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002256 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2257 return 0;
2258
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 if (*(args[1]) == 0) {
2260 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2261 return -1;
2262 }
2263
2264 preg = calloc(1, sizeof(regex_t));
2265 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2266 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2267 return -1;
2268 }
2269
2270 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2271 if (err) {
2272 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2273 file, linenum, *err);
2274 return -1;
2275 }
2276 }
2277 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2278 if (curproxy == &defproxy) {
2279 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2280 return -1;
2281 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002282 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2283 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284
2285 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2286 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2287 return 0;
2288 }
2289
2290 if (*(args[1]) == 0) {
2291 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2292 return -1;
2293 }
2294
2295 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2296 }
2297 else if (!strcmp(args[0], "errorloc") ||
2298 !strcmp(args[0], "errorloc302") ||
2299 !strcmp(args[0], "errorloc303")) { /* error location */
2300 int errnum, errlen;
2301 char *err;
2302
Willy Tarreau977b8e42006-12-29 14:19:17 +01002303 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2304 return 0;
2305
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002307 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002308 return -1;
2309 }
2310
2311 errnum = atol(args[1]);
2312 if (!strcmp(args[0], "errorloc303")) {
2313 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2314 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2315 } else {
2316 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2317 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2318 }
2319
Willy Tarreau0f772532006-12-23 20:51:41 +01002320 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2321 if (http_err_codes[rc] == errnum) {
2322 if (curproxy->errmsg[rc].str)
2323 free(curproxy->errmsg[rc].str);
2324 curproxy->errmsg[rc].str = err;
2325 curproxy->errmsg[rc].len = errlen;
2326 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002327 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002329
2330 if (rc >= HTTP_ERR_SIZE) {
2331 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2332 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333 free(err);
2334 }
2335 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002336 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2337 int errnum, errlen, fd;
2338 char *err;
2339 struct stat stat;
2340
2341 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2342 return 0;
2343
2344 if (*(args[2]) == 0) {
2345 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2346 return -1;
2347 }
2348
2349 fd = open(args[2], O_RDONLY);
2350 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2351 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2352 file, linenum, args[2], args[1]);
2353 if (fd >= 0)
2354 close(fd);
2355 return -1;
2356 }
2357
2358 if (stat.st_size <= BUFSIZE) {
2359 errlen = stat.st_size;
2360 } else {
2361 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2362 file, linenum, args[2], BUFSIZE);
2363 errlen = BUFSIZE;
2364 }
2365
2366 err = malloc(errlen); /* malloc() must succeed during parsing */
2367 errnum = read(fd, err, errlen);
2368 if (errnum != errlen) {
2369 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2370 file, linenum, args[2], args[1]);
2371 close(fd);
2372 free(err);
2373 return -1;
2374 }
2375 close(fd);
2376
2377 errnum = atol(args[1]);
2378 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2379 if (http_err_codes[rc] == errnum) {
2380 if (curproxy->errmsg[rc].str)
2381 free(curproxy->errmsg[rc].str);
2382 curproxy->errmsg[rc].str = err;
2383 curproxy->errmsg[rc].len = errlen;
2384 break;
2385 }
2386 }
2387
2388 if (rc >= HTTP_ERR_SIZE) {
2389 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2390 file, linenum, errnum);
2391 free(err);
2392 }
2393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002394 else {
2395 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2396 return -1;
2397 }
2398 return 0;
2399}
2400
2401
2402/*
2403 * This function reads and parses the configuration file given in the argument.
2404 * returns 0 if OK, -1 if error.
2405 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002406int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002407{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002408 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002409 FILE *f;
2410 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002412 int confsect = CFG_NONE;
2413
2414 struct proxy *curproxy = NULL;
2415 struct server *newsrv = NULL;
2416
2417 if ((f=fopen(file,"r")) == NULL)
2418 return -1;
2419
2420 init_default_instance();
2421
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002422 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002423 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002424 char *end;
2425 char *args[MAX_LINE_ARGS + 1];
2426 char *line = thisline;
2427
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 linenum++;
2429
2430 end = line + strlen(line);
2431
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002432 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2433 /* Check if we reached the limit and the last char is not \n.
2434 * Watch out for the last line without the terminating '\n'!
2435 */
2436 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2437 file, linenum, sizeof(thisline)-1);
2438 return -1;
2439 }
2440
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002442 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 line++;
2444
2445 arg = 0;
2446 args[arg] = line;
2447
2448 while (*line && arg < MAX_LINE_ARGS) {
2449 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2450 * C equivalent value. Other combinations left unchanged (eg: \1).
2451 */
2452 if (*line == '\\') {
2453 int skip = 0;
2454 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2455 *line = line[1];
2456 skip = 1;
2457 }
2458 else if (line[1] == 'r') {
2459 *line = '\r';
2460 skip = 1;
2461 }
2462 else if (line[1] == 'n') {
2463 *line = '\n';
2464 skip = 1;
2465 }
2466 else if (line[1] == 't') {
2467 *line = '\t';
2468 skip = 1;
2469 }
2470 else if (line[1] == 'x') {
2471 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2472 unsigned char hex1, hex2;
2473 hex1 = toupper(line[2]) - '0';
2474 hex2 = toupper(line[3]) - '0';
2475 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2476 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2477 *line = (hex1<<4) + hex2;
2478 skip = 3;
2479 }
2480 else {
2481 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2482 return -1;
2483 }
2484 }
2485 if (skip) {
2486 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2487 end -= skip;
2488 }
2489 line++;
2490 }
2491 else if (*line == '#' || *line == '\n' || *line == '\r') {
2492 /* end of string, end of loop */
2493 *line = 0;
2494 break;
2495 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002496 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002498 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002499 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500 line++;
2501 args[++arg] = line;
2502 }
2503 else {
2504 line++;
2505 }
2506 }
2507
2508 /* empty line */
2509 if (!**args)
2510 continue;
2511
Willy Tarreau540abe42007-05-02 20:50:16 +02002512 /* zero out remaining args and ensure that at least one entry
2513 * is zeroed out.
2514 */
2515 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 args[arg] = line;
2517 }
2518
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002519 if (!strcmp(args[0], "no")) {
2520 inv = 1;
2521 for (arg=0; *args[arg+1]; arg++)
2522 args[arg] = args[arg+1]; // shift args after inversion
2523 }
2524
2525 if (inv && strcmp(args[0], "option")) {
2526 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
2527 return -1;
2528 }
2529
Willy Tarreau977b8e42006-12-29 14:19:17 +01002530 if (!strcmp(args[0], "listen") ||
2531 !strcmp(args[0], "frontend") ||
2532 !strcmp(args[0], "backend") ||
2533 !strcmp(args[0], "ruleset") ||
2534 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535 confsect = CFG_LISTEN;
2536 else if (!strcmp(args[0], "global")) /* global config */
2537 confsect = CFG_GLOBAL;
2538 /* else it's a section keyword */
2539
2540 switch (confsect) {
2541 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002542 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 return -1;
2544 break;
2545 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002546 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 return -1;
2548 break;
2549 default:
2550 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2551 return -1;
2552 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 }
2554 fclose(f);
2555
2556 /*
2557 * Now, check for the integrity of all that we have collected.
2558 */
2559
2560 /* will be needed further to delay some tasks */
2561 tv_now(&now);
2562
2563 if ((curproxy = proxy) == NULL) {
2564 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2565 file);
2566 return -1;
2567 }
2568
2569 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002570 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002571 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002572
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 if (curproxy->state == PR_STSTOPPED) {
2574 curproxy = curproxy->next;
2575 continue;
2576 }
2577
Willy Tarreau977b8e42006-12-29 14:19:17 +01002578 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2579 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 +01002580 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581 cfgerr++;
2582 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002583 else if (curproxy->cap & PR_CAP_BE &&
2584 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002585 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002586 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002587 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2588 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 +01002589 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 cfgerr++;
2591 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002592
Willy Tarreau31682232007-11-29 15:38:04 +01002593 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002595 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002596 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 cfgerr++;
2598 }
2599#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2600 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002601 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002602 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603 cfgerr++;
2604 }
2605#endif
2606 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002607 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002608 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609 }
2610 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002611
2612 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002613 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002614 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002615 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002618 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002619 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002620 }
2621 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002622 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002623 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002625 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002626 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002627 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002628 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002629 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002630 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2631 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002632
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002633 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002634 file, proxy_type_str(curproxy), curproxy->id);
2635 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002637
2638 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2639 if ((newsrv = curproxy->srv) != NULL) {
2640 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2641 file, proxy_type_str(curproxy), curproxy->id);
2642 }
2643 }
2644
2645 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2647 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2648 file, curproxy->id);
2649 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002650 }
2651 }
2652
Willy Tarreau82936582007-11-30 15:20:09 +01002653 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2654 curproxy->options &= ~PR_O_DISABLE404;
2655 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2656 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2657 }
2658
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002659 /* if a default backend was specified, let's find it */
2660 if (curproxy->defbe.name) {
2661 struct proxy *target;
2662
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002663 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2664 if (!target) {
2665 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2666 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002667 cfgerr++;
2668 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002669 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2670 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002671 } else {
2672 free(curproxy->defbe.name);
2673 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002674 }
2675 }
2676
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002677 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002678 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2679 /* map jump target for ACT_SETBE in req_rep chain */
2680 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002681 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002682 struct proxy *target;
2683
Willy Tarreaua496b602006-12-17 23:15:24 +01002684 if (exp->action != ACT_SETBE)
2685 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002686
2687 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2688 if (!target) {
2689 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2690 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002691 cfgerr++;
2692 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002693 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2694 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002695 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002696 } else {
2697 free((void *)exp->replace);
2698 exp->replace = (const char *)target;
2699 }
2700 }
2701 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002702
2703 /* find the target proxy for 'use_backend' rules */
2704 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002705 struct proxy *target;
2706
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002707 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002708
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002709 if (!target) {
2710 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2711 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002712 cfgerr++;
2713 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002714 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2715 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002716 cfgerr++;
2717 } else {
2718 free((void *)rule->be.name);
2719 rule->be.backend = target;
2720 }
2721 }
2722
Willy Tarreau2738a142006-07-08 17:28:09 +02002723 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002724 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->timeout.client)) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02002725 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002726 (!tv_isset(&curproxy->timeout.connect) || !tv_isset(&curproxy->timeout.server))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002727 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002728 " | While not properly invalid, you will certainly encounter various problems\n"
2729 " | with such a configuration. To fix this, please ensure that all following\n"
2730 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002731 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002732 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002733
Willy Tarreau1fa31262007-12-03 00:36:16 +01002734 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
2735 * We must still support older configurations, so let's find out whether those
2736 * parameters have been set or must be copied from contimeouts.
2737 */
2738 if (curproxy != &defproxy) {
2739 if ((curproxy->cap & PR_CAP_FE) &&
2740 (!tv_isset(&curproxy->timeout.tarpit) ||
2741 __tv_iseq(&curproxy->timeout.tarpit, &defproxy.timeout.tarpit))) {
2742 /* tarpit timeout not set. We search in the following order:
2743 * default.tarpit, curr.connect, default.connect.
2744 */
2745 if (tv_isset(&defproxy.timeout.tarpit))
2746 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002747 else if (tv_isset(&curproxy->timeout.connect))
2748 curproxy->timeout.tarpit = curproxy->timeout.connect;
2749 else if (tv_isset(&defproxy.timeout.connect))
2750 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002751 }
2752 if ((curproxy->cap & PR_CAP_BE) &&
2753 (!tv_isset(&curproxy->timeout.queue) ||
2754 __tv_iseq(&curproxy->timeout.queue, &defproxy.timeout.queue))) {
2755 /* queue timeout not set. We search in the following order:
2756 * default.queue, curr.connect, default.connect.
2757 */
2758 if (tv_isset(&defproxy.timeout.queue))
2759 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002760 else if (tv_isset(&curproxy->timeout.connect))
2761 curproxy->timeout.queue = curproxy->timeout.connect;
2762 else if (tv_isset(&defproxy.timeout.connect))
2763 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002764 }
2765 }
2766
Willy Tarreauf3c69202006-07-09 16:42:34 +02002767 if (curproxy->options & PR_O_SSL3_CHK) {
2768 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2769 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2770 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2771 }
2772
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002773 /* The small pools required for the capture lists */
2774 if (curproxy->nb_req_cap)
2775 curproxy->req_cap_pool = create_pool("ptrcap",
2776 curproxy->nb_req_cap * sizeof(char *),
2777 MEM_F_SHARED);
2778 if (curproxy->nb_rsp_cap)
2779 curproxy->rsp_cap_pool = create_pool("ptrcap",
2780 curproxy->nb_rsp_cap * sizeof(char *),
2781 MEM_F_SHARED);
2782
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002783 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2784 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2785 MEM_F_SHARED);
2786
Willy Tarreau86034312006-12-29 00:10:33 +01002787 /* for backwards compatibility with "listen" instances, if
2788 * fullconn is not set but maxconn is set, then maxconn
2789 * is used.
2790 */
2791 if (!curproxy->fullconn)
2792 curproxy->fullconn = curproxy->maxconn;
2793
Willy Tarreaubaaee002006-06-26 02:48:02 +02002794 /* first, we will invert the servers list order */
2795 newsrv = NULL;
2796 while (curproxy->srv) {
2797 struct server *next;
2798
2799 next = curproxy->srv->next;
2800 curproxy->srv->next = newsrv;
2801 newsrv = curproxy->srv;
2802 if (!next)
2803 break;
2804 curproxy->srv = next;
2805 }
2806
Willy Tarreau20697042007-11-15 23:26:18 +01002807 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01002808 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002809
Willy Tarreaub625a082007-11-26 01:15:43 +01002810 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01002811 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01002812 fwrr_init_server_groups(curproxy);
2813 else
2814 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815
2816 if (curproxy->options & PR_O_LOGASAP)
2817 curproxy->to_log &= ~LW_BYTES;
2818
Willy Tarreaubaaee002006-06-26 02:48:02 +02002819 /*
2820 * If this server supports a maxconn parameter, it needs a dedicated
2821 * tasks to fill the emptied slots when a connection leaves.
2822 */
2823 newsrv = curproxy->srv;
2824 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002825 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002826 /* Only 'minconn' was specified, or it was higher than or equal
2827 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2828 * this will avoid further useless expensive computations.
2829 */
2830 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002831 } else if (newsrv->maxconn && !newsrv->minconn) {
2832 /* minconn was not specified, so we set it to maxconn */
2833 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002834 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2835 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002836 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002837 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002838 }
2839
2840 if (newsrv->maxconn > 0) {
2841 struct task *t;
2842
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002843 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002844 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2845 return -1;
2846 }
2847
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002848 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002849 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002850 t->state = TASK_IDLE;
2851 t->process = process_srv_queue;
2852 t->context = newsrv;
2853 newsrv->queue_mgt = t;
2854
2855 /* never run it unless specifically woken up */
2856 tv_eternity(&t->expire);
2857 task_queue(t);
2858 }
2859 newsrv = newsrv->next;
2860 }
2861
Willy Tarreaue6b98942007-10-29 01:09:36 +01002862 /* adjust this proxy's listeners */
2863 listener = curproxy->listen;
2864 while (listener) {
2865 if (curproxy->options & PR_O_TCP_NOLING)
2866 listener->options |= LI_O_NOLINGER;
2867 listener->maxconn = curproxy->maxconn;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002868 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002869 listener->accept = event_accept;
2870 listener->private = curproxy;
2871
2872 listener = listener->next;
2873 }
2874
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875 curproxy = curproxy->next;
2876 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002877
Willy Tarreaubaaee002006-06-26 02:48:02 +02002878 if (cfgerr > 0) {
2879 Alert("Errors found in configuration file, aborting.\n");
2880 return -1;
2881 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002882
2883 /*
2884 * Recount currently required checks.
2885 */
2886
2887 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
2888 int optnum;
2889
2890 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2891 if (!(curproxy->options & cfg_opts[optnum].val))
2892 continue;
2893
2894 global.last_checks |= cfg_opts[optnum].checks;
2895 }
2896 }
2897
2898 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899}
2900
2901
2902
2903/*
2904 * Local variables:
2905 * c-indent-level: 8
2906 * c-basic-offset: 8
2907 * End:
2908 */