blob: d41edf7d86fd5f732fd9d779f69a89afebdf211f [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau7c669d72008-06-20 15:04:11 +02004 * Copyright 2000-2008 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>
35#include <types/polling.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036
Willy Tarreaueb0c6142007-05-07 00:53:22 +020037#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010039#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020041#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010044#include <proto/protocols.h>
45#include <proto/proto_tcp.h>
46#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010047#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010049#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <proto/task.h>
51
52
Willy Tarreauf3c69202006-07-09 16:42:34 +020053/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
54 * ssl-hello-chk option to ensure that the remote server speaks SSL.
55 *
56 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
57 */
58const char sslv3_client_hello_pkt[] = {
59 "\x16" /* ContentType : 0x16 = Hanshake */
60 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
61 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
62 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
63 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
64 "\x03\x00" /* Hello Version : 0x0300 = v3 */
65 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
66 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
67 "\x00" /* Session ID length : empty (no session ID) */
68 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
69 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
70 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
71 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
72 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
73 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
74 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
75 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
76 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
77 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
78 "\x00\x38" "\x00\x39" "\x00\x3A"
79 "\x01" /* Compression Length : 0x01 = 1 byte for types */
80 "\x00" /* Compression Type : 0x00 = NULL compression */
81};
82
Willy Tarreau13943ab2006-12-31 00:24:10 +010083/* some of the most common options which are also the easiest to handle */
84static const struct {
85 const char *name;
86 unsigned int val;
87 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010088 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010089} cfg_opts[] =
90{
Willy Tarreau4fee4e92007-01-06 21:09:17 +010091 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010092 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010094 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010095 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
96 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
97 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
98 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
99 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
100 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
101 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
102 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100103 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100104 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
105 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100106#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100107 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
108#endif
109#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100110 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100111#endif
112
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100113 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114};
115
Willy Tarreaubaaee002006-06-26 02:48:02 +0200116
Willy Tarreau6daf3432008-01-22 16:44:08 +0100117static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200118static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
119int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
120int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
121
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200122/* List head of all known configuration keywords */
123static struct cfg_kw_list cfg_keywords = {
124 .list = LIST_HEAD_INIT(cfg_keywords.list)
125};
126
Willy Tarreaubaaee002006-06-26 02:48:02 +0200127/*
128 * converts <str> to a list of listeners which are dynamically allocated.
129 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
130 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
131 * - <port> is a numerical port from 1 to 65535 ;
132 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
133 * This can be repeated as many times as necessary, separated by a coma.
134 * The <tail> argument is a pointer to a current list which should be appended
135 * to the tail of the new list. The pointer to the new list is returned.
136 */
137static struct listener *str2listener(char *str, struct listener *tail)
138{
139 struct listener *l;
140 char *c, *next, *range, *dupstr;
141 int port, end;
142
143 next = dupstr = strdup(str);
144
145 while (next && *next) {
146 struct sockaddr_storage ss;
147
148 str = next;
149 /* 1) look for the end of the first address */
150 if ((next = strrchr(str, ',')) != NULL) {
151 *next++ = 0;
152 }
153
154 /* 2) look for the addr/port delimiter, it's the last colon. */
155 if ((range = strrchr(str, ':')) == NULL) {
156 Alert("Missing port number: '%s'\n", str);
157 goto fail;
158 }
159
160 *range++ = 0;
161
162 if (strrchr(str, ':') != NULL) {
163 /* IPv6 address contains ':' */
164 memset(&ss, 0, sizeof(ss));
165 ss.ss_family = AF_INET6;
166
167 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
168 Alert("Invalid server address: '%s'\n", str);
169 goto fail;
170 }
171 }
172 else {
173 memset(&ss, 0, sizeof(ss));
174 ss.ss_family = AF_INET;
175
176 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
177 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
178 }
179 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
180 struct hostent *he;
181
182 if ((he = gethostbyname(str)) == NULL) {
183 Alert("Invalid server name: '%s'\n", str);
184 goto fail;
185 }
186 else
187 ((struct sockaddr_in *)&ss)->sin_addr =
188 *(struct in_addr *) *(he->h_addr_list);
189 }
190 }
191
192 /* 3) look for the port-end delimiter */
193 if ((c = strchr(range, '-')) != NULL) {
194 *c++ = 0;
195 end = atol(c);
196 }
197 else {
198 end = atol(range);
199 }
200
201 port = atol(range);
202
203 if (port < 1 || port > 65535) {
204 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
205 goto fail;
206 }
207
208 if (end < 1 || end > 65535) {
209 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
210 goto fail;
211 }
212
213 for (; port <= end; port++) {
214 l = (struct listener *)calloc(1, sizeof(struct listener));
215 l->next = tail;
216 tail = l;
217
218 l->fd = -1;
219 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100220 l->state = LI_INIT;
221
222 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100224 tcpv6_add_listener(l);
225 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100227 tcpv4_add_listener(l);
228 }
229 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 } /* end for(port) */
231 } /* end while(next) */
232 free(dupstr);
233 return tail;
234 fail:
235 free(dupstr);
236 return NULL;
237}
238
Willy Tarreau977b8e42006-12-29 14:19:17 +0100239/*
240 * Sends a warning if proxy <proxy> does not have at least one of the
241 * capabilities in <cap>. An optionnal <hint> may be added at the end
242 * of the warning to help the user. Returns 1 if a warning was emitted
243 * or 0 if the condition is valid.
244 */
245int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
246{
247 char *msg;
248
249 switch (cap) {
250 case PR_CAP_BE: msg = "no backend"; break;
251 case PR_CAP_FE: msg = "no frontend"; break;
252 case PR_CAP_RS: msg = "no ruleset"; break;
253 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
254 default: msg = "not enough"; break;
255 }
256
257 if (!(proxy->cap & cap)) {
258 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100259 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100260 return 1;
261 }
262 return 0;
263}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264
265/*
266 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
267 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100268int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200269{
270
271 if (!strcmp(args[0], "global")) { /* new section */
272 /* no option, nothing special to do */
273 return 0;
274 }
275 else if (!strcmp(args[0], "daemon")) {
276 global.mode |= MODE_DAEMON;
277 }
278 else if (!strcmp(args[0], "debug")) {
279 global.mode |= MODE_DEBUG;
280 }
281 else if (!strcmp(args[0], "noepoll")) {
282 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
283 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200284 else if (!strcmp(args[0], "nosepoll")) {
285 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
286 }
287 else if (!strcmp(args[0], "nokqueue")) {
288 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 else if (!strcmp(args[0], "nopoll")) {
291 cfg_polling_mechanism &= ~POLL_USE_POLL;
292 }
293 else if (!strcmp(args[0], "quiet")) {
294 global.mode |= MODE_QUIET;
295 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200296 else if (!strcmp(args[0], "tune.maxpollevents")) {
297 if (global.tune.maxpollevents != 0) {
298 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
299 return 0;
300 }
301 if (*(args[1]) == 0) {
302 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
303 return -1;
304 }
305 global.tune.maxpollevents = atol(args[1]);
306 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100307 else if (!strcmp(args[0], "tune.maxaccept")) {
308 if (global.tune.maxaccept != 0) {
309 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
310 return 0;
311 }
312 if (*(args[1]) == 0) {
313 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
314 return -1;
315 }
316 global.tune.maxaccept = atol(args[1]);
317 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318 else if (!strcmp(args[0], "uid")) {
319 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200320 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321 return 0;
322 }
323 if (*(args[1]) == 0) {
324 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
325 return -1;
326 }
327 global.uid = atol(args[1]);
328 }
329 else if (!strcmp(args[0], "gid")) {
330 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200331 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200332 return 0;
333 }
334 if (*(args[1]) == 0) {
335 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
336 return -1;
337 }
338 global.gid = atol(args[1]);
339 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200340 /* user/group name handling */
341 else if (!strcmp(args[0], "user")) {
342 struct passwd *ha_user;
343 if (global.uid != 0) {
344 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
345 return 0;
346 }
347 errno = 0;
348 ha_user = getpwnam(args[1]);
349 if (ha_user != NULL) {
350 global.uid = (int)ha_user->pw_uid;
351 }
352 else {
353 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
354 exit(1);
355 }
356 }
357 else if (!strcmp(args[0], "group")) {
358 struct group *ha_group;
359 if (global.gid != 0) {
360 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
361 return 0;
362 }
363 errno = 0;
364 ha_group = getgrnam(args[1]);
365 if (ha_group != NULL) {
366 global.gid = (int)ha_group->gr_gid;
367 }
368 else {
369 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
370 exit(1);
371 }
372 }
373 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200374 else if (!strcmp(args[0], "nbproc")) {
375 if (global.nbproc != 0) {
376 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
377 return 0;
378 }
379 if (*(args[1]) == 0) {
380 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
381 return -1;
382 }
383 global.nbproc = atol(args[1]);
384 }
385 else if (!strcmp(args[0], "maxconn")) {
386 if (global.maxconn != 0) {
387 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
388 return 0;
389 }
390 if (*(args[1]) == 0) {
391 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
392 return -1;
393 }
394 global.maxconn = atol(args[1]);
395#ifdef SYSTEM_MAXCONN
396 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
397 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);
398 global.maxconn = DEFAULT_MAXCONN;
399 }
400#endif /* SYSTEM_MAXCONN */
401 }
402 else if (!strcmp(args[0], "ulimit-n")) {
403 if (global.rlimit_nofile != 0) {
404 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
405 return 0;
406 }
407 if (*(args[1]) == 0) {
408 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
409 return -1;
410 }
411 global.rlimit_nofile = atol(args[1]);
412 }
413 else if (!strcmp(args[0], "chroot")) {
414 if (global.chroot != NULL) {
415 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
416 return 0;
417 }
418 if (*(args[1]) == 0) {
419 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
420 return -1;
421 }
422 global.chroot = strdup(args[1]);
423 }
424 else if (!strcmp(args[0], "pidfile")) {
425 if (global.pidfile != NULL) {
426 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
427 return 0;
428 }
429 if (*(args[1]) == 0) {
430 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
431 return -1;
432 }
433 global.pidfile = strdup(args[1]);
434 }
435 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100436 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200437 int facility, level;
438
439 if (*(args[1]) == 0 || *(args[2]) == 0) {
440 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
441 return -1;
442 }
443
444 facility = get_log_facility(args[2]);
445 if (facility < 0) {
446 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
447 exit(1);
448 }
449
450 level = 7; /* max syslog level = debug */
451 if (*(args[3])) {
452 level = get_log_level(args[3]);
453 if (level < 0) {
454 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
455 exit(1);
456 }
457 }
458
Robert Tsai81ae1952007-12-05 10:47:29 +0100459 if (args[1][0] == '/') {
460 logsrv.u.addr.sa_family = AF_UNIX;
461 logsrv.u.un = *str2sun(args[1]);
462 } else {
463 logsrv.u.addr.sa_family = AF_INET;
464 logsrv.u.in = *str2sa(args[1]);
465 if (!logsrv.u.in.sin_port)
466 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468
469 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100470 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200471 global.logfac1 = facility;
472 global.loglev1 = level;
473 }
474 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100475 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476 global.logfac2 = facility;
477 global.loglev2 = level;
478 }
479 else {
480 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
481 return -1;
482 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200483 }
484 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
485 if (global.spread_checks != 0) {
486 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
487 return 0;
488 }
489 if (*(args[1]) == 0) {
490 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
491 return -1;
492 }
493 global.spread_checks = atol(args[1]);
494 if (global.spread_checks < 0 || global.spread_checks > 50) {
495 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
496 return -1;
497 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200498 }
499 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200500 struct cfg_kw_list *kwl;
501 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200502 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200503
504 list_for_each_entry(kwl, &cfg_keywords.list, list) {
505 for (index = 0; kwl->kw[index].kw != NULL; index++) {
506 if (kwl->kw[index].section != CFG_GLOBAL)
507 continue;
508 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
509 /* prepare error message just in case */
510 snprintf(trash, sizeof(trash),
511 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200512 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
513 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200514 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
515 return -1;
516 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200517 else if (rc > 0) {
518 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
519 return 0;
520 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200521 return 0;
522 }
523 }
524 }
525
Willy Tarreaubaaee002006-06-26 02:48:02 +0200526 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
527 return -1;
528 }
529 return 0;
530}
531
532
533static void init_default_instance()
534{
535 memset(&defproxy, 0, sizeof(defproxy));
536 defproxy.mode = PR_MODE_TCP;
537 defproxy.state = PR_STNEW;
538 defproxy.maxconn = cfg_maxpconn;
539 defproxy.conn_retries = CONN_RETRIES;
540 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200541
542 LIST_INIT(&defproxy.pendconns);
543 LIST_INIT(&defproxy.acl);
544 LIST_INIT(&defproxy.block_cond);
545 LIST_INIT(&defproxy.mon_fail_cond);
546 LIST_INIT(&defproxy.switching_rules);
547
Willy Tarreau3a70f942008-02-15 11:15:34 +0100548 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200549}
550
551/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100552 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
553 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200554 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100555int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200556{
557 static struct proxy *curproxy = NULL;
558 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200559 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100560 int rc;
561 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200562
Willy Tarreau977b8e42006-12-29 14:19:17 +0100563 if (!strcmp(args[0], "listen"))
564 rc = PR_CAP_LISTEN;
565 else if (!strcmp(args[0], "frontend"))
566 rc = PR_CAP_FE | PR_CAP_RS;
567 else if (!strcmp(args[0], "backend"))
568 rc = PR_CAP_BE | PR_CAP_RS;
569 else if (!strcmp(args[0], "ruleset"))
570 rc = PR_CAP_RS;
571 else
572 rc = PR_CAP_NONE;
573
574 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575 if (!*args[1]) {
576 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
577 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
578 file, linenum, args[0]);
579 return -1;
580 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200581
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100582 err = invalid_char(args[1]);
583 if (err) {
584 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
585 file, linenum, *err, args[0], args[1]);
586 return -1;
587 }
588
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200589 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
590 /*
591 * If there are two proxies with the same name only following
592 * combinations are allowed:
593 *
594 * listen backend frontend ruleset
595 * listen - - - -
596 * backend - - OK -
597 * frontend - OK - -
598 * ruleset - - - -
599 */
600
601 if (!strcmp(curproxy->id, args[1]) &&
602 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
603 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100604 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
605 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200606 }
607 }
608
Willy Tarreaubaaee002006-06-26 02:48:02 +0200609 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
610 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
611 return -1;
612 }
613
614 curproxy->next = proxy;
615 proxy = curproxy;
616 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200617 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200618 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200619 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100620 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200621 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200622 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623
Willy Tarreauee991362007-05-14 14:37:50 +0200624 /* Timeouts are defined as -1, so we cannot use the zeroed area
625 * as a default value.
626 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100627 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200628
629 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100631 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632
633 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100634 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 curproxy->listen = str2listener(args[2], curproxy->listen);
636 if (!curproxy->listen)
637 return -1;
638 global.maxsock++;
639 }
640
641 /* set default values */
642 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200643 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100644 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200645 curproxy->except_net = defproxy.except_net;
646 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200648 if (defproxy.fwdfor_hdr_len) {
649 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
650 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
651 }
652
Willy Tarreau977b8e42006-12-29 14:19:17 +0100653 if (curproxy->cap & PR_CAP_FE) {
654 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100655 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100656
657 /* initialize error relocations */
658 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
659 if (defproxy.errmsg[rc].str)
660 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
661 }
662
663 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665
Willy Tarreau977b8e42006-12-29 14:19:17 +0100666 if (curproxy->cap & PR_CAP_BE) {
667 curproxy->fullconn = defproxy.fullconn;
668 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669
Willy Tarreau977b8e42006-12-29 14:19:17 +0100670 if (defproxy.check_req)
671 curproxy->check_req = strdup(defproxy.check_req);
672 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200673
Willy Tarreau977b8e42006-12-29 14:19:17 +0100674 if (defproxy.cookie_name)
675 curproxy->cookie_name = strdup(defproxy.cookie_name);
676 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100677
678 if (defproxy.url_param_name)
679 curproxy->url_param_name = strdup(defproxy.url_param_name);
680 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100681 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682
Willy Tarreau977b8e42006-12-29 14:19:17 +0100683 if (curproxy->cap & PR_CAP_RS) {
684 if (defproxy.capture_name)
685 curproxy->capture_name = strdup(defproxy.capture_name);
686 curproxy->capture_namelen = defproxy.capture_namelen;
687 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100688 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200689
Willy Tarreau977b8e42006-12-29 14:19:17 +0100690 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100691 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100692 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100693 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100694 curproxy->uri_auth = defproxy.uri_auth;
695 curproxy->mon_net = defproxy.mon_net;
696 curproxy->mon_mask = defproxy.mon_mask;
697 if (defproxy.monitor_uri)
698 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
699 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100700 if (defproxy.defbe.name)
701 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100702 }
703
704 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100705 curproxy->timeout.connect = defproxy.timeout.connect;
706 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100707 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100708 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100709 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100710 curproxy->source_addr = defproxy.source_addr;
711 }
712
Willy Tarreaubaaee002006-06-26 02:48:02 +0200713 curproxy->mode = defproxy.mode;
714 curproxy->logfac1 = defproxy.logfac1;
715 curproxy->logsrv1 = defproxy.logsrv1;
716 curproxy->loglev1 = defproxy.loglev1;
717 curproxy->logfac2 = defproxy.logfac2;
718 curproxy->logsrv2 = defproxy.logsrv2;
719 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200720 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100721 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
722 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200723
Willy Tarreaubaaee002006-06-26 02:48:02 +0200724 return 0;
725 }
726 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
727 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100728 /* FIXME-20070101: we should do this too at the end of the
729 * config parsing to free all default values.
730 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200731 free(defproxy.check_req);
732 free(defproxy.cookie_name);
733 free(defproxy.url_param_name);
734 free(defproxy.capture_name);
735 free(defproxy.monitor_uri);
736 free(defproxy.defbe.name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200737 free(defproxy.fwdfor_hdr_name);
738 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100739
Willy Tarreaua534fea2008-08-03 12:19:50 +0200740 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
741 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100742
Willy Tarreaubaaee002006-06-26 02:48:02 +0200743 /* we cannot free uri_auth because it might already be used */
744 init_default_instance();
745 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100746 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 return 0;
748 }
749 else if (curproxy == NULL) {
750 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
751 return -1;
752 }
753
Willy Tarreau977b8e42006-12-29 14:19:17 +0100754
755 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200756 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100757 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200758 if (curproxy == &defproxy) {
759 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
760 return -1;
761 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100762 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
763 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200764
765 if (strchr(args[1], ':') == NULL) {
766 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
767 file, linenum, args[0]);
768 return -1;
769 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100770
771 last_listen = curproxy->listen;
772 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200773 if (!curproxy->listen)
774 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100775 if (*args[2]) {
776#ifdef CONFIG_HAP_LINUX_TPROXY
777 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
778 struct listener *l;
779
780 for (l = curproxy->listen; l != last_listen; l = l->next)
781 l->options |= LI_O_FOREIGN;
782 }
783 else {
784 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
785 file, linenum, args[0]);
786 return -1;
787 }
788#else
789 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
790 file, linenum, args[0]);
791 return -1;
792#endif
793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200794 global.maxsock++;
795 return 0;
796 }
797 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
798 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
799 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
800 file, linenum, args[0]);
801 return -1;
802 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100803 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
804 return 0;
805
Willy Tarreaubaaee002006-06-26 02:48:02 +0200806 /* flush useless bits */
807 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
808 return 0;
809 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200810 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100811 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
812 return 0;
813
Willy Tarreau1c47f852006-07-09 08:22:27 +0200814 if (!*args[1]) {
815 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
816 file, linenum, args[0]);
817 return -1;
818 }
819
Willy Tarreaua534fea2008-08-03 12:19:50 +0200820 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100821 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200822 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100823 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200824 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
825
826 return 0;
827 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200828 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
829 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
830 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
831 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
832 else {
833 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
834 return -1;
835 }
836 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100837 else if (!strcmp(args[0], "id")) {
838 struct proxy *target;
839
840 if (curproxy == &defproxy) {
841 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
842 file, linenum, args[0]);
843 return -1;
844 }
845
846 if (!*args[1]) {
847 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
848 file, linenum, args[0]);
849 return -1;
850 }
851
852 curproxy->uuid = atol(args[1]);
853
854 if (curproxy->uuid < 1001) {
855 Alert("parsing [%s:%d]: custom id has to be > 1000",
856 file, linenum);
857 return -1;
858 }
859
860 for (target = proxy; target; target = target->next)
861 if (curproxy != target && curproxy->uuid == target->uuid) {
862 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
863 file, linenum, curproxy->id, target->id);
864 return -1;
865 }
866 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
868 curproxy->state = PR_STSTOPPED;
869 }
870 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
871 curproxy->state = PR_STNEW;
872 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200873 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200874 if (curproxy == &defproxy) {
875 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
876 return -1;
877 }
878
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100879 err = invalid_char(args[1]);
880 if (err) {
881 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
882 file, linenum, *err, args[1]);
883 return -1;
884 }
885
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200886 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
887 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
888 file, linenum, args[1]);
889 return -1;
890 }
891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 else if (!strcmp(args[0], "cookie")) { /* cookie name */
893 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200894
Willy Tarreau977b8e42006-12-29 14:19:17 +0100895 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
896 return 0;
897
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898 if (*(args[1]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
900 file, linenum, args[0]);
901 return -1;
902 }
Willy Tarreaua534fea2008-08-03 12:19:50 +0200903
904 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905 curproxy->cookie_name = strdup(args[1]);
906 curproxy->cookie_len = strlen(curproxy->cookie_name);
907
908 cur_arg = 2;
909 while (*(args[cur_arg])) {
910 if (!strcmp(args[cur_arg], "rewrite")) {
911 curproxy->options |= PR_O_COOK_RW;
912 }
913 else if (!strcmp(args[cur_arg], "indirect")) {
914 curproxy->options |= PR_O_COOK_IND;
915 }
916 else if (!strcmp(args[cur_arg], "insert")) {
917 curproxy->options |= PR_O_COOK_INS;
918 }
919 else if (!strcmp(args[cur_arg], "nocache")) {
920 curproxy->options |= PR_O_COOK_NOC;
921 }
922 else if (!strcmp(args[cur_arg], "postonly")) {
923 curproxy->options |= PR_O_COOK_POST;
924 }
925 else if (!strcmp(args[cur_arg], "prefix")) {
926 curproxy->options |= PR_O_COOK_PFX;
927 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200928 else if (!strcmp(args[cur_arg], "domain")) {
929 if (!*args[cur_arg + 1]) {
930 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
931 file, linenum, args[cur_arg]);
932 return -1;
933 }
934
935 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
936 /* rfc2109, 4.3.2 Rejecting Cookies */
937 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
938 " dots or does not start with a dot.\n",
939 file, linenum, args[cur_arg + 1]);
940 return -1;
941 }
942
943 err = invalid_domainchar(args[cur_arg + 1]);
944 if (err) {
945 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
946 file, linenum, *err, args[cur_arg + 1]);
947 return -1;
948 }
949
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +0200950 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200951 cur_arg++;
952 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200954 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 file, linenum, args[0]);
956 return -1;
957 }
958 cur_arg++;
959 }
960 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
961 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
962 file, linenum);
963 return -1;
964 }
965
966 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
967 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
968 file, linenum);
969 return -1;
970 }
971 }/* end else if (!strcmp(args[0], "cookie")) */
972 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973
Willy Tarreau977b8e42006-12-29 14:19:17 +0100974 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
975 return 0;
976
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977 if (*(args[5]) == 0) {
978 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
979 file, linenum, args[0]);
980 return -1;
981 }
982 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +0200983 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200984 curproxy->appsession_name = strdup(args[1]);
985 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
986 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100987 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
988 if (err) {
989 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
990 file, linenum, *err, args[0]);
991 return -1;
992 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200993 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +0200994
Willy Tarreau51041c72007-09-09 21:56:53 +0200995 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
996 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 return -1;
998 }
999 } /* Url App Session */
1000 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001001 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1002 return 0;
1003
Willy Tarreaubaaee002006-06-26 02:48:02 +02001004 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005 if (*(args[4]) == 0) {
1006 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1007 file, linenum, args[0]);
1008 return -1;
1009 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001010 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001011 curproxy->capture_name = strdup(args[2]);
1012 curproxy->capture_namelen = strlen(curproxy->capture_name);
1013 curproxy->capture_len = atol(args[4]);
1014 if (curproxy->capture_len >= CAPTURE_LEN) {
1015 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1016 file, linenum, CAPTURE_LEN - 1);
1017 curproxy->capture_len = CAPTURE_LEN - 1;
1018 }
1019 curproxy->to_log |= LW_COOKIE;
1020 }
1021 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1022 struct cap_hdr *hdr;
1023
1024 if (curproxy == &defproxy) {
1025 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1026 return -1;
1027 }
1028
1029 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1030 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1031 file, linenum, args[0], args[1]);
1032 return -1;
1033 }
1034
1035 hdr = calloc(sizeof(struct cap_hdr), 1);
1036 hdr->next = curproxy->req_cap;
1037 hdr->name = strdup(args[3]);
1038 hdr->namelen = strlen(args[3]);
1039 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001040 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001041 hdr->index = curproxy->nb_req_cap++;
1042 curproxy->req_cap = hdr;
1043 curproxy->to_log |= LW_REQHDR;
1044 }
1045 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1046 struct cap_hdr *hdr;
1047
1048 if (curproxy == &defproxy) {
1049 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1050 return -1;
1051 }
1052
1053 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1054 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1055 file, linenum, args[0], args[1]);
1056 return -1;
1057 }
1058 hdr = calloc(sizeof(struct cap_hdr), 1);
1059 hdr->next = curproxy->rsp_cap;
1060 hdr->name = strdup(args[3]);
1061 hdr->namelen = strlen(args[3]);
1062 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001063 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001064 hdr->index = curproxy->nb_rsp_cap++;
1065 curproxy->rsp_cap = hdr;
1066 curproxy->to_log |= LW_RSPHDR;
1067 }
1068 else {
1069 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1070 file, linenum, args[0]);
1071 return -1;
1072 }
1073 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001075 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1076 return 0;
1077
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078 if (*(args[1]) == 0) {
1079 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1080 file, linenum, args[0]);
1081 return -1;
1082 }
1083 curproxy->conn_retries = atol(args[1]);
1084 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001085 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1086 int pol = ACL_COND_NONE;
1087 struct acl_cond *cond;
1088
Willy Tarreaub099aca2008-10-12 17:26:37 +02001089 if (curproxy == &defproxy) {
1090 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1091 return -1;
1092 }
1093
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001094 if (!strcmp(args[1], "if"))
1095 pol = ACL_COND_IF;
1096 else if (!strcmp(args[1], "unless"))
1097 pol = ACL_COND_UNLESS;
1098
1099 if (pol == ACL_COND_NONE) {
1100 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1101 file, linenum, args[0]);
1102 return -1;
1103 }
1104
1105 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1106 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1107 file, linenum);
1108 return -1;
1109 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001110 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001111 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1112 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001113 else if (!strcmp(args[0], "redirect")) {
1114 int pol = ACL_COND_NONE;
1115 struct acl_cond *cond;
1116 struct redirect_rule *rule;
1117 int cur_arg;
1118 int type = REDIRECT_TYPE_NONE;
1119 int code = 302;
1120 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001121 char *cookie = NULL;
1122 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001123 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001124
1125 cur_arg = 1;
1126 while (*(args[cur_arg])) {
1127 if (!strcmp(args[cur_arg], "location")) {
1128 if (!*args[cur_arg + 1]) {
1129 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1130 file, linenum, args[0], args[cur_arg]);
1131 return -1;
1132 }
1133
1134 type = REDIRECT_TYPE_LOCATION;
1135 cur_arg++;
1136 destination = args[cur_arg];
1137 }
1138 else if (!strcmp(args[cur_arg], "prefix")) {
1139 if (!*args[cur_arg + 1]) {
1140 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1141 file, linenum, args[0], args[cur_arg]);
1142 return -1;
1143 }
1144
1145 type = REDIRECT_TYPE_PREFIX;
1146 cur_arg++;
1147 destination = args[cur_arg];
1148 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001149 else if (!strcmp(args[cur_arg], "set-cookie")) {
1150 if (!*args[cur_arg + 1]) {
1151 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1152 file, linenum, args[0], args[cur_arg]);
1153 return -1;
1154 }
1155
1156 cur_arg++;
1157 cookie = args[cur_arg];
1158 cookie_set = 1;
1159 }
1160 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1161 if (!*args[cur_arg + 1]) {
1162 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1163 file, linenum, args[0], args[cur_arg]);
1164 return -1;
1165 }
1166
1167 cur_arg++;
1168 cookie = args[cur_arg];
1169 cookie_set = 0;
1170 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001171 else if (!strcmp(args[cur_arg],"code")) {
1172 if (!*args[cur_arg + 1]) {
1173 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1174 file, linenum, args[0]);
1175 return -1;
1176 }
1177 cur_arg++;
1178 code = atol(args[cur_arg]);
1179 if (code < 301 || code > 303) {
1180 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1181 file, linenum, args[0], code);
1182 return -1;
1183 }
1184 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001185 else if (!strcmp(args[cur_arg],"drop-query")) {
1186 flags |= REDIRECT_FLAG_DROP_QS;
1187 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001188 else if (!strcmp(args[cur_arg], "if")) {
1189 pol = ACL_COND_IF;
1190 cur_arg++;
1191 break;
1192 }
1193 else if (!strcmp(args[cur_arg], "unless")) {
1194 pol = ACL_COND_UNLESS;
1195 cur_arg++;
1196 break;
1197 }
1198 else {
1199 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1200 file, linenum, args[0], args[cur_arg]);
1201 return -1;
1202 }
1203 cur_arg++;
1204 }
1205
1206 if (type == REDIRECT_TYPE_NONE) {
1207 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1208 file, linenum, args[0]);
1209 return -1;
1210 }
1211
1212 if (pol == ACL_COND_NONE) {
1213 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1214 file, linenum, args[0]);
1215 return -1;
1216 }
1217
1218 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1219 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1220 file, linenum, args[0]);
1221 return -1;
1222 }
1223
Willy Tarreaua9802632008-07-25 19:13:19 +02001224 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001225 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1226 rule->cond = cond;
1227 rule->rdr_str = strdup(destination);
1228 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001229 if (cookie) {
1230 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1231 * a clear consists in appending "; Max-Age=0" at the end.
1232 */
1233 rule->cookie_len = strlen(cookie);
1234 if (cookie_set)
1235 rule->cookie_str = strdup(cookie);
1236 else {
1237 rule->cookie_str = malloc(rule->cookie_len + 12);
1238 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1239 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1240 rule->cookie_len += 11;
1241 }
1242 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001243 rule->type = type;
1244 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001245 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001246 LIST_INIT(&rule->list);
1247 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1248 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001249 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1250 int pol = ACL_COND_NONE;
1251 struct acl_cond *cond;
1252 struct switching_rule *rule;
1253
Willy Tarreaub099aca2008-10-12 17:26:37 +02001254 if (curproxy == &defproxy) {
1255 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1256 return -1;
1257 }
1258
Willy Tarreau55ea7572007-06-17 19:56:27 +02001259 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1260 return 0;
1261
1262 if (*(args[1]) == 0) {
1263 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1264 return -1;
1265 }
1266
1267 if (!strcmp(args[2], "if"))
1268 pol = ACL_COND_IF;
1269 else if (!strcmp(args[2], "unless"))
1270 pol = ACL_COND_UNLESS;
1271
1272 if (pol == ACL_COND_NONE) {
1273 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1274 file, linenum, args[0]);
1275 return -1;
1276 }
1277
1278 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001279 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001280 file, linenum);
1281 return -1;
1282 }
1283
Willy Tarreaua9802632008-07-25 19:13:19 +02001284 cond->line = linenum;
1285 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001286 struct acl *acl;
1287 const char *name;
1288
1289 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1290 name = acl ? acl->name : "(unknown)";
1291 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1292 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001293 }
1294
Willy Tarreau55ea7572007-06-17 19:56:27 +02001295 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1296 rule->cond = cond;
1297 rule->be.name = strdup(args[1]);
1298 LIST_INIT(&rule->list);
1299 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001301 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001302 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1303 return 0;
1304
Willy Tarreaubaaee002006-06-26 02:48:02 +02001305 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1306 curproxy->uri_auth = NULL; /* we must detach from the default config */
1307
1308 if (*(args[1]) == 0) {
1309 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1310 return -1;
1311 } else if (!strcmp(args[1], "uri")) {
1312 if (*(args[2]) == 0) {
1313 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1314 return -1;
1315 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1316 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1317 return -1;
1318 }
1319 } else if (!strcmp(args[1], "realm")) {
1320 if (*(args[2]) == 0) {
1321 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1322 return -1;
1323 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1324 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1325 return -1;
1326 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001327 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001328 unsigned interval;
1329
1330 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1331 if (err) {
1332 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1333 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001334 return -1;
1335 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1336 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1337 return -1;
1338 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001339 } else if (!strcmp(args[1], "auth")) {
1340 if (*(args[2]) == 0) {
1341 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1342 return -1;
1343 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1344 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1345 return -1;
1346 }
1347 } else if (!strcmp(args[1], "scope")) {
1348 if (*(args[2]) == 0) {
1349 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1350 return -1;
1351 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1352 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1353 return -1;
1354 }
1355 } else if (!strcmp(args[1], "enable")) {
1356 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1357 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1358 return -1;
1359 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001360 } else if (!strcmp(args[1], "hide-version")) {
1361 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1362 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1363 return -1;
1364 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001366 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 file, linenum, args[0]);
1368 return -1;
1369 }
1370 }
1371 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001372 int optnum;
1373
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001374 if (*(args[1]) == '\0') {
1375 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1376 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001377 return -1;
1378 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001379
1380 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1381 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1382 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1383 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001384
1385 if (!inv)
1386 curproxy->options |= cfg_opts[optnum].val;
1387 else
1388 curproxy->options &= ~cfg_opts[optnum].val;
1389
Willy Tarreau13943ab2006-12-31 00:24:10 +01001390 return 0;
1391 }
1392 }
1393
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001394 if (inv) {
1395 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1396 file, linenum, args[1]);
1397 return -1;
1398 }
1399
Willy Tarreau13943ab2006-12-31 00:24:10 +01001400 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 /* generate a complete HTTP log */
1402 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1403 else if (!strcmp(args[1], "tcplog"))
1404 /* generate a detailed TCP log */
1405 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001406 else if (!strcmp(args[1], "tcpka")) {
1407 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001408 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1409 return 0;
1410
1411 if (curproxy->cap & PR_CAP_FE)
1412 curproxy->options |= PR_O_TCP_CLI_KA;
1413 if (curproxy->cap & PR_CAP_BE)
1414 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 }
1416 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001417 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1418 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001420 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001421 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001422 curproxy->options &= ~PR_O_SMTP_CHK;
1423 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001424 if (!*args[2]) { /* no argument */
1425 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1426 curproxy->check_len = strlen(DEF_CHECK_REQ);
1427 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001428 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429 curproxy->check_req = (char *)malloc(reqlen);
1430 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1431 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1432 } else { /* more arguments : METHOD URI [HTTP_VER] */
1433 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1434 if (*args[4])
1435 reqlen += strlen(args[4]);
1436 else
1437 reqlen += strlen("HTTP/1.0");
1438
1439 curproxy->check_req = (char *)malloc(reqlen);
1440 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1441 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1442 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001443 }
1444 else if (!strcmp(args[1], "ssl-hello-chk")) {
1445 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001446 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1447 return 0;
1448
Willy Tarreaua534fea2008-08-03 12:19:50 +02001449 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001450 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001451 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001452 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453 }
Willy Tarreau23677902007-05-08 23:50:35 +02001454 else if (!strcmp(args[1], "smtpchk")) {
1455 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001456 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001457 curproxy->options &= ~PR_O_HTTP_CHK;
1458 curproxy->options &= ~PR_O_SSL3_CHK;
1459 curproxy->options |= PR_O_SMTP_CHK;
1460
1461 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1462 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1463 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1464 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1465 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1466 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1467 curproxy->check_req = (char *)malloc(reqlen);
1468 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1469 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1470 } else {
1471 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1472 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1473 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1474 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1475 }
1476 }
1477 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001478 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001479 int cur_arg;
1480
1481 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1482 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001483 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001484
1485 curproxy->options |= PR_O_FWDFOR;
1486
1487 free(curproxy->fwdfor_hdr_name);
1488 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1489 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1490
1491 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1492 cur_arg = 2;
1493 while (*(args[cur_arg])) {
1494 if (!strcmp(args[cur_arg], "except")) {
1495 /* suboption except - needs additional argument for it */
1496 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1497 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1498 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001499 return -1;
1500 }
1501 /* flush useless bits */
1502 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001503 cur_arg += 2;
1504 } else if (!strcmp(args[cur_arg], "header")) {
1505 /* suboption header - needs additional argument for it */
1506 if (*(args[cur_arg+1]) == 0) {
1507 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1508 file, linenum, args[0], args[1], args[cur_arg]);
1509 return -1;
1510 }
1511 free(curproxy->fwdfor_hdr_name);
1512 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1513 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1514 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001515 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001516 /* unknown suboption - catchall */
1517 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1518 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001519 return -1;
1520 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001521 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523 else {
1524 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1525 return -1;
1526 }
1527 return 0;
1528 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001529 else if (!strcmp(args[0], "default_backend")) {
1530 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1531 return 0;
1532
1533 if (*(args[1]) == 0) {
1534 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1535 return -1;
1536 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001537 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001538 curproxy->defbe.name = strdup(args[1]);
1539 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001541 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1542 return 0;
1543
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001544 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1545 file, linenum, args[0]);
1546
Willy Tarreaubaaee002006-06-26 02:48:02 +02001547 /* enable reconnections to dispatch */
1548 curproxy->options |= PR_O_REDISP;
1549 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001550 else if (!strcmp(args[0], "http-check")) {
1551 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1552 return 0;
1553
1554 if (strcmp(args[1], "disable-on-404") == 0) {
1555 /* enable a graceful server shutdown on an HTTP 404 response */
1556 curproxy->options |= PR_O_DISABLE404;
1557 }
1558 else {
1559 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1560 return -1;
1561 }
1562 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001563 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001564 if (curproxy == &defproxy) {
1565 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1566 return -1;
1567 }
1568
Willy Tarreaub80c2302007-11-30 20:51:32 +01001569 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1570 return 0;
1571
1572 if (strcmp(args[1], "fail") == 0) {
1573 /* add a condition to fail monitor requests */
1574 int pol = ACL_COND_NONE;
1575 struct acl_cond *cond;
1576
1577 if (!strcmp(args[2], "if"))
1578 pol = ACL_COND_IF;
1579 else if (!strcmp(args[2], "unless"))
1580 pol = ACL_COND_UNLESS;
1581
1582 if (pol == ACL_COND_NONE) {
1583 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1584 file, linenum, args[0], args[1]);
1585 return -1;
1586 }
1587
1588 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1589 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1590 file, linenum, args[0], args[1]);
1591 return -1;
1592 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001593 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001594 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1595 }
1596 else {
1597 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1598 return -1;
1599 }
1600 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601#ifdef TPROXY
1602 else if (!strcmp(args[0], "transparent")) {
1603 /* enable transparent proxy connections */
1604 curproxy->options |= PR_O_TRANSP;
1605 }
1606#endif
1607 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001608 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1609 return 0;
1610
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611 if (*(args[1]) == 0) {
1612 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1613 return -1;
1614 }
1615 curproxy->maxconn = atol(args[1]);
1616 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001617 else if (!strcmp(args[0], "backlog")) { /* backlog */
1618 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1619 return 0;
1620
1621 if (*(args[1]) == 0) {
1622 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1623 return -1;
1624 }
1625 curproxy->backlog = atol(args[1]);
1626 }
Willy Tarreau86034312006-12-29 00:10:33 +01001627 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001628 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1629 return 0;
1630
Willy Tarreau86034312006-12-29 00:10:33 +01001631 if (*(args[1]) == 0) {
1632 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1633 return -1;
1634 }
1635 curproxy->fullconn = atol(args[1]);
1636 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001637 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1638 if (*(args[1]) == 0) {
1639 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1640 return -1;
1641 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001642 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1643 if (err) {
1644 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1645 file, linenum, *err);
1646 return -1;
1647 }
1648 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 }
1650 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1651 if (curproxy == &defproxy) {
1652 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1653 return -1;
1654 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001655 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1656 return 0;
1657
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 if (strchr(args[1], ':') == NULL) {
1659 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1660 return -1;
1661 }
1662 curproxy->dispatch_addr = *str2sa(args[1]);
1663 }
1664 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001665 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1666 return 0;
1667
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02001668 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001669 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1670 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1671 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001672 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 }
1674 else if (!strcmp(args[0], "server")) { /* server address */
1675 int cur_arg;
1676 char *rport;
1677 char *raddr;
1678 short realport;
1679 int do_check;
1680
1681 if (curproxy == &defproxy) {
1682 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1683 return -1;
1684 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001685 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1686 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001687
1688 if (!*args[2]) {
1689 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1690 file, linenum, args[0]);
1691 return -1;
1692 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001693
1694 err = invalid_char(args[1]);
1695 if (err) {
1696 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1697 file, linenum, *err, args[1]);
1698 return -1;
1699 }
1700
Willy Tarreaubaaee002006-06-26 02:48:02 +02001701 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1702 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1703 return -1;
1704 }
1705
1706 /* the servers are linked backwards first */
1707 newsrv->next = curproxy->srv;
1708 curproxy->srv = newsrv;
1709 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001710 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001711
1712 LIST_INIT(&newsrv->pendconns);
1713 do_check = 0;
1714 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001715 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001716 newsrv->id = strdup(args[1]);
1717
1718 /* several ways to check the port component :
1719 * - IP => port=+0, relative
1720 * - IP: => port=+0, relative
1721 * - IP:N => port=N, absolute
1722 * - IP:+N => port=+N, relative
1723 * - IP:-N => port=-N, relative
1724 */
1725 raddr = strdup(args[2]);
1726 rport = strchr(raddr, ':');
1727 if (rport) {
1728 *rport++ = 0;
1729 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001730 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001731 newsrv->state |= SRV_MAPPORTS;
1732 } else {
1733 realport = 0;
1734 newsrv->state |= SRV_MAPPORTS;
1735 }
1736
1737 newsrv->addr = *str2sa(raddr);
1738 newsrv->addr.sin_port = htons(realport);
1739 free(raddr);
1740
1741 newsrv->curfd = -1; /* no health-check in progress */
1742 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001743 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1744 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001745 newsrv->rise = DEF_RISETIME;
1746 newsrv->fall = DEF_FALLTIME;
1747 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001748 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001749 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001750 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001751
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752 cur_arg = 3;
1753 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001754 if (!strcmp(args[cur_arg], "id")) {
1755 struct server *target;
1756
1757 if (!*args[cur_arg + 1]) {
1758 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1759 file, linenum, args[cur_arg]);
1760 return -1;
1761 }
1762
1763 newsrv->puid = atol(args[cur_arg + 1]);
1764
1765 if (newsrv->puid< 1001) {
1766 Alert("parsing [%s:%d]: custom id has to be > 1000",
1767 file, linenum);
1768 return -1;
1769 }
1770
1771 for (target = proxy->srv; target; target = target->next)
1772 if (newsrv != target && newsrv->puid == target->puid) {
1773 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1774 file, linenum, newsrv->id, target->id);
1775 return -1;
1776 }
1777 cur_arg += 2;
1778 }
1779 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 newsrv->cookie = strdup(args[cur_arg + 1]);
1781 newsrv->cklen = strlen(args[cur_arg + 1]);
1782 cur_arg += 2;
1783 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001784 else if (!strcmp(args[cur_arg], "redir")) {
1785 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1786 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1787 cur_arg += 2;
1788 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001789 else if (!strcmp(args[cur_arg], "rise")) {
1790 newsrv->rise = atol(args[cur_arg + 1]);
1791 newsrv->health = newsrv->rise;
1792 cur_arg += 2;
1793 }
1794 else if (!strcmp(args[cur_arg], "fall")) {
1795 newsrv->fall = atol(args[cur_arg + 1]);
1796 cur_arg += 2;
1797 }
1798 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001799 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1800 if (err) {
1801 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1802 file, linenum, *err, newsrv->id);
1803 return -1;
1804 }
1805 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001806 cur_arg += 2;
1807 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001808 else if (!strcmp(args[cur_arg], "fastinter")) {
1809 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1810 if (err) {
1811 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1812 file, linenum, *err, newsrv->id);
1813 return -1;
1814 }
1815 newsrv->fastinter = val;
1816 cur_arg += 2;
1817 }
1818 else if (!strcmp(args[cur_arg], "downinter")) {
1819 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1820 if (err) {
1821 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1822 file, linenum, *err, newsrv->id);
1823 return -1;
1824 }
1825 newsrv->downinter = val;
1826 cur_arg += 2;
1827 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001828 else if (!strcmp(args[cur_arg], "addr")) {
1829 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001830 cur_arg += 2;
1831 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001832 else if (!strcmp(args[cur_arg], "port")) {
1833 newsrv->check_port = atol(args[cur_arg + 1]);
1834 cur_arg += 2;
1835 }
1836 else if (!strcmp(args[cur_arg], "backup")) {
1837 newsrv->state |= SRV_BACKUP;
1838 cur_arg ++;
1839 }
1840 else if (!strcmp(args[cur_arg], "weight")) {
1841 int w;
1842 w = atol(args[cur_arg + 1]);
1843 if (w < 1 || w > 256) {
1844 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1845 file, linenum, newsrv->id, w);
1846 return -1;
1847 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001848 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001849 cur_arg += 2;
1850 }
1851 else if (!strcmp(args[cur_arg], "minconn")) {
1852 newsrv->minconn = atol(args[cur_arg + 1]);
1853 cur_arg += 2;
1854 }
1855 else if (!strcmp(args[cur_arg], "maxconn")) {
1856 newsrv->maxconn = atol(args[cur_arg + 1]);
1857 cur_arg += 2;
1858 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001859 else if (!strcmp(args[cur_arg], "maxqueue")) {
1860 newsrv->maxqueue = atol(args[cur_arg + 1]);
1861 cur_arg += 2;
1862 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001863 else if (!strcmp(args[cur_arg], "slowstart")) {
1864 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001865 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001866 if (err) {
1867 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1868 file, linenum, *err, newsrv->id);
1869 return -1;
1870 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001871 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001872 cur_arg += 2;
1873 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001874 else if (!strcmp(args[cur_arg], "track")) {
1875
1876 if (!*args[cur_arg + 1]) {
1877 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1878 file, linenum);
1879 return -1;
1880 }
1881
1882 newsrv->trackit = strdup(args[cur_arg + 1]);
1883
1884 cur_arg += 2;
1885 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001886 else if (!strcmp(args[cur_arg], "check")) {
1887 global.maxsock++;
1888 do_check = 1;
1889 cur_arg += 1;
1890 }
1891 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1892 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001893#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001894 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1895 file, linenum, "source", "usesrc");
1896#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001897 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1898 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001899#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 return -1;
1901 }
1902 newsrv->state |= SRV_BIND_SRC;
1903 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1904 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001905 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001906#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1907#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001908 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001909 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1910 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001911 return -1;
1912 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001913#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001914 if (!*args[cur_arg + 1]) {
1915 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1916 file, linenum, "usesrc");
1917 return -1;
1918 }
1919 if (!strcmp(args[cur_arg + 1], "client")) {
1920 newsrv->state |= SRV_TPROXY_CLI;
1921 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1922 newsrv->state |= SRV_TPROXY_CIP;
1923 } else {
1924 newsrv->state |= SRV_TPROXY_ADDR;
1925 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1926 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001927 global.last_checks |= LSTCHK_NETADM;
1928#if !defined(CONFIG_HAP_LINUX_TPROXY)
1929 global.last_checks |= LSTCHK_CTTPROXY;
1930#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001931 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001932#else /* no TPROXY support */
1933 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001934 file, linenum, "usesrc");
1935 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001936#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001937 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001939 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1940 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1941 file, linenum, "usesrc", "source");
1942 return -1;
1943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001945 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'check', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 file, linenum, newsrv->id);
1947 return -1;
1948 }
1949 }
1950
1951 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001952 if (newsrv->trackit) {
1953 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1954 file, linenum);
1955 return -1;
1956 }
1957
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001958 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1959 newsrv->check_port = newsrv->check_addr.sin_port;
1960
Willy Tarreaubaaee002006-06-26 02:48:02 +02001961 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1962 newsrv->check_port = realport; /* by default */
1963 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001964 /* not yet valid, because no port was set on
1965 * the server either. We'll check if we have
1966 * a known port on the first listener.
1967 */
1968 struct listener *l;
1969 l = curproxy->listen;
1970 if (l) {
1971 int port;
1972 port = (l->addr.ss_family == AF_INET6)
1973 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1974 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1975 newsrv->check_port = port;
1976 }
1977 }
1978 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001979 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1980 file, linenum, newsrv->id);
1981 return -1;
1982 }
1983 newsrv->state |= SRV_CHECKED;
1984 }
1985
1986 if (newsrv->state & SRV_BACKUP)
1987 curproxy->srv_bck++;
1988 else
1989 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001990
1991 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001992 }
1993 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001994 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001995 int facility;
1996
1997 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1998 curproxy->logfac1 = global.logfac1;
1999 curproxy->logsrv1 = global.logsrv1;
2000 curproxy->loglev1 = global.loglev1;
2001 curproxy->logfac2 = global.logfac2;
2002 curproxy->logsrv2 = global.logsrv2;
2003 curproxy->loglev2 = global.loglev2;
2004 }
2005 else if (*(args[1]) && *(args[2])) {
2006 int level;
2007
2008 facility = get_log_facility(args[2]);
2009 if (facility < 0) {
2010 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2011 exit(1);
2012 }
2013
2014 level = 7; /* max syslog level = debug */
2015 if (*(args[3])) {
2016 level = get_log_level(args[3]);
2017 if (level < 0) {
2018 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2019 exit(1);
2020 }
2021 }
2022
Robert Tsai81ae1952007-12-05 10:47:29 +01002023 if (args[1][0] == '/') {
2024 logsrv.u.addr.sa_family = AF_UNIX;
2025 logsrv.u.un = *str2sun(args[1]);
2026 } else {
2027 logsrv.u.addr.sa_family = AF_INET;
2028 logsrv.u.in = *str2sa(args[1]);
2029 if (!logsrv.u.in.sin_port) {
2030 logsrv.u.in.sin_port =
2031 htons(SYSLOG_PORT);
2032 }
2033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002034
2035 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002036 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002037 curproxy->logfac1 = facility;
2038 curproxy->loglev1 = level;
2039 }
2040 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002041 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002042 curproxy->logfac2 = facility;
2043 curproxy->loglev2 = level;
2044 }
2045 else {
2046 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2047 return -1;
2048 }
2049 }
2050 else {
2051 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2052 file, linenum);
2053 return -1;
2054 }
2055 }
2056 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002057 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2058 return 0;
2059
Willy Tarreaubaaee002006-06-26 02:48:02 +02002060 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002061#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002062 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2063 file, linenum, "source", "usesrc");
2064#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002065 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2066 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002067#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002068 return -1;
2069 }
2070
2071 curproxy->source_addr = *str2sa(args[1]);
2072 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01002073 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002074#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2075#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002076 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2077 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2078 file, linenum, "usesrc");
2079 return -1;
2080 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002081#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002082 if (!*args[3]) {
2083 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2084 file, linenum, "usesrc");
2085 return -1;
2086 }
2087
2088 if (!strcmp(args[3], "client")) {
2089 curproxy->options |= PR_O_TPXY_CLI;
2090 } else if (!strcmp(args[3], "clientip")) {
2091 curproxy->options |= PR_O_TPXY_CIP;
2092 } else {
2093 curproxy->options |= PR_O_TPXY_ADDR;
2094 curproxy->tproxy_addr = *str2sa(args[3]);
2095 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002096 global.last_checks |= LSTCHK_NETADM;
2097#if !defined(CONFIG_HAP_LINUX_TPROXY)
2098 global.last_checks |= LSTCHK_CTTPROXY;
2099#endif
2100#else /* no TPROXY support */
2101 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002102 file, linenum, "usesrc");
2103 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002104#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002105 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002107 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2108 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2109 file, linenum, "usesrc", "source");
2110 return -1;
2111 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002112 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2113 regex_t *preg;
2114 if (curproxy == &defproxy) {
2115 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2116 return -1;
2117 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002118 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2119 return 0;
2120
Willy Tarreaubaaee002006-06-26 02:48:02 +02002121 if (*(args[1]) == 0 || *(args[2]) == 0) {
2122 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2123 file, linenum, args[0]);
2124 return -1;
2125 }
2126
2127 preg = calloc(1, sizeof(regex_t));
2128 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2129 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2130 return -1;
2131 }
2132
2133 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2134 if (err) {
2135 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2136 file, linenum, *err);
2137 return -1;
2138 }
2139 }
2140 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2141 regex_t *preg;
2142 if (curproxy == &defproxy) {
2143 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2144 return -1;
2145 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002146 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2147 return 0;
2148
Willy Tarreaubaaee002006-06-26 02:48:02 +02002149 if (*(args[1]) == 0) {
2150 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2151 return -1;
2152 }
2153
2154 preg = calloc(1, sizeof(regex_t));
2155 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2156 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2157 return -1;
2158 }
2159
2160 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2161 }
2162 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2163 regex_t *preg;
2164 if (curproxy == &defproxy) {
2165 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2166 return -1;
2167 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002168 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2169 return 0;
2170
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171 if (*(args[1]) == 0) {
2172 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2173 return -1;
2174 }
2175
2176 preg = calloc(1, sizeof(regex_t));
2177 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2178 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2179 return -1;
2180 }
2181
2182 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2183 }
2184 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2185 regex_t *preg;
2186 if (curproxy == &defproxy) {
2187 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2188 return -1;
2189 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002190 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2191 return 0;
2192
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193 if (*(args[1]) == 0) {
2194 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2195 return -1;
2196 }
2197
2198 preg = calloc(1, sizeof(regex_t));
2199 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2200 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2201 return -1;
2202 }
2203
2204 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2205 }
2206 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2207 regex_t *preg;
2208 if (curproxy == &defproxy) {
2209 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2210 return -1;
2211 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002212 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2213 return 0;
2214
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215 if (*(args[1]) == 0) {
2216 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2217 return -1;
2218 }
2219
2220 preg = calloc(1, sizeof(regex_t));
2221 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2222 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2223 return -1;
2224 }
2225
2226 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2227 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002228 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2229 regex_t *preg;
2230 if (curproxy == &defproxy) {
2231 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2232 return -1;
2233 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002234 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2235 return 0;
2236
Willy Tarreaub8750a82006-09-03 09:56:00 +02002237 if (*(args[1]) == 0) {
2238 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2239 return -1;
2240 }
2241
2242 preg = calloc(1, sizeof(regex_t));
2243 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2244 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2245 return -1;
2246 }
2247
2248 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2249 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002250 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2251 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002252 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002253 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;
Willy Tarreaua496b602006-12-17 23:15:24 +01002258
Willy Tarreau977b8e42006-12-29 14:19:17 +01002259 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002260 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2261 file, linenum, args[0]);
2262 return -1;
2263 }
2264
2265 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002266 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002267 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2268 }
2269
2270 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2271 }
2272 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2273 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002274 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002275 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2276 return -1;
2277 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002278 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2279 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002280
Willy Tarreau977b8e42006-12-29 14:19:17 +01002281 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002282 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2283 file, linenum, args[0]);
2284 return -1;
2285 }
2286
2287 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002288 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002289 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2290 }
2291
2292 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2295 regex_t *preg;
2296 if (curproxy == &defproxy) {
2297 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2298 return -1;
2299 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002300 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2301 return 0;
2302
Willy Tarreaubaaee002006-06-26 02:48:02 +02002303 if (*(args[1]) == 0 || *(args[2]) == 0) {
2304 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2305 file, linenum, args[0]);
2306 return -1;
2307 }
2308
2309 preg = calloc(1, sizeof(regex_t));
2310 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2311 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2312 return -1;
2313 }
2314
2315 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2316 if (err) {
2317 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2318 file, linenum, *err);
2319 return -1;
2320 }
2321 }
2322 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2323 regex_t *preg;
2324 if (curproxy == &defproxy) {
2325 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2326 return -1;
2327 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002328 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2329 return 0;
2330
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 if (*(args[1]) == 0) {
2332 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2333 return -1;
2334 }
2335
2336 preg = calloc(1, sizeof(regex_t));
2337 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2338 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2339 return -1;
2340 }
2341
2342 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2343 }
2344 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2345 regex_t *preg;
2346 if (curproxy == &defproxy) {
2347 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2348 return -1;
2349 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002350 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2351 return 0;
2352
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 if (*(args[1]) == 0) {
2354 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2355 return -1;
2356 }
2357
2358 preg = calloc(1, sizeof(regex_t));
2359 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2360 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2361 return -1;
2362 }
2363
2364 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2365 }
2366 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2367 regex_t *preg;
2368 if (curproxy == &defproxy) {
2369 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2370 return -1;
2371 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002372 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2373 return 0;
2374
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 if (*(args[1]) == 0) {
2376 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2377 return -1;
2378 }
2379
2380 preg = calloc(1, sizeof(regex_t));
2381 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2382 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2383 return -1;
2384 }
2385
2386 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2387 }
2388 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2389 regex_t *preg;
2390 if (curproxy == &defproxy) {
2391 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2392 return -1;
2393 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002394 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2395 return 0;
2396
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 if (*(args[1]) == 0) {
2398 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2399 return -1;
2400 }
2401
2402 preg = calloc(1, sizeof(regex_t));
2403 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2404 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2405 return -1;
2406 }
2407
2408 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2409 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002410 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2411 regex_t *preg;
2412 if (curproxy == &defproxy) {
2413 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2414 return -1;
2415 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002416 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2417 return 0;
2418
Willy Tarreaub8750a82006-09-03 09:56:00 +02002419 if (*(args[1]) == 0) {
2420 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2421 return -1;
2422 }
2423
2424 preg = calloc(1, sizeof(regex_t));
2425 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2426 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2427 return -1;
2428 }
2429
2430 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2431 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2433 if (curproxy == &defproxy) {
2434 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2435 return -1;
2436 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002437 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2438 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002439
2440 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2441 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2442 return 0;
2443 }
2444
2445 if (*(args[1]) == 0) {
2446 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2447 return -1;
2448 }
2449
2450 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2451 }
2452 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2453 regex_t *preg;
2454
2455 if (*(args[1]) == 0 || *(args[2]) == 0) {
2456 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2457 file, linenum, args[0]);
2458 return -1;
2459 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002460 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2461 return 0;
2462
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 preg = calloc(1, sizeof(regex_t));
2464 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2465 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2466 return -1;
2467 }
2468
2469 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2470 if (err) {
2471 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2472 file, linenum, *err);
2473 return -1;
2474 }
2475 }
2476 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2477 regex_t *preg;
2478 if (curproxy == &defproxy) {
2479 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2480 return -1;
2481 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002482 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2483 return 0;
2484
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 if (*(args[1]) == 0) {
2486 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2487 return -1;
2488 }
2489
2490 preg = calloc(1, sizeof(regex_t));
2491 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2492 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2493 return -1;
2494 }
2495
2496 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2497 if (err) {
2498 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2499 file, linenum, *err);
2500 return -1;
2501 }
2502 }
2503 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2504 regex_t *preg;
2505 if (curproxy == &defproxy) {
2506 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2507 return -1;
2508 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002509 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2510 return 0;
2511
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 if (*(args[1]) == 0) {
2513 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2514 return -1;
2515 }
2516
2517 preg = calloc(1, sizeof(regex_t));
2518 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2519 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2520 return -1;
2521 }
2522
2523 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2524 if (err) {
2525 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2526 file, linenum, *err);
2527 return -1;
2528 }
2529 }
2530 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2531 regex_t *preg;
2532 if (curproxy == &defproxy) {
2533 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2534 return -1;
2535 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002536 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2537 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002538
2539 if (*(args[1]) == 0 || *(args[2]) == 0) {
2540 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2541 file, linenum, args[0]);
2542 return -1;
2543 }
2544
2545 preg = calloc(1, sizeof(regex_t));
2546 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2547 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2548 return -1;
2549 }
2550
2551 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2552 if (err) {
2553 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2554 file, linenum, *err);
2555 return -1;
2556 }
2557 }
2558 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2559 regex_t *preg;
2560 if (curproxy == &defproxy) {
2561 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2562 return -1;
2563 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002564 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2565 return 0;
2566
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 if (*(args[1]) == 0) {
2568 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2569 return -1;
2570 }
2571
2572 preg = calloc(1, sizeof(regex_t));
2573 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2574 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2575 return -1;
2576 }
2577
2578 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2579 if (err) {
2580 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2581 file, linenum, *err);
2582 return -1;
2583 }
2584 }
2585 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2586 regex_t *preg;
2587 if (curproxy == &defproxy) {
2588 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2589 return -1;
2590 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002591 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2592 return 0;
2593
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 if (*(args[1]) == 0) {
2595 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2596 return -1;
2597 }
2598
2599 preg = calloc(1, sizeof(regex_t));
2600 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2601 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2602 return -1;
2603 }
2604
2605 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2606 if (err) {
2607 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2608 file, linenum, *err);
2609 return -1;
2610 }
2611 }
2612 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2613 if (curproxy == &defproxy) {
2614 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2615 return -1;
2616 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002617 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2618 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002619
2620 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2621 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2622 return 0;
2623 }
2624
2625 if (*(args[1]) == 0) {
2626 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2627 return -1;
2628 }
2629
2630 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2631 }
2632 else if (!strcmp(args[0], "errorloc") ||
2633 !strcmp(args[0], "errorloc302") ||
2634 !strcmp(args[0], "errorloc303")) { /* error location */
2635 int errnum, errlen;
2636 char *err;
2637
Willy Tarreau977b8e42006-12-29 14:19:17 +01002638 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2639 return 0;
2640
Willy Tarreaubaaee002006-06-26 02:48:02 +02002641 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002642 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 return -1;
2644 }
2645
2646 errnum = atol(args[1]);
2647 if (!strcmp(args[0], "errorloc303")) {
2648 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2649 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2650 } else {
2651 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2652 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2653 }
2654
Willy Tarreau0f772532006-12-23 20:51:41 +01002655 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2656 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002657 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002658 curproxy->errmsg[rc].str = err;
2659 curproxy->errmsg[rc].len = errlen;
2660 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002661 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002662 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002663
2664 if (rc >= HTTP_ERR_SIZE) {
2665 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2666 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667 free(err);
2668 }
2669 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002670 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2671 int errnum, errlen, fd;
2672 char *err;
2673 struct stat stat;
2674
2675 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2676 return 0;
2677
2678 if (*(args[2]) == 0) {
2679 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2680 return -1;
2681 }
2682
2683 fd = open(args[2], O_RDONLY);
2684 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2685 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2686 file, linenum, args[2], args[1]);
2687 if (fd >= 0)
2688 close(fd);
2689 return -1;
2690 }
2691
2692 if (stat.st_size <= BUFSIZE) {
2693 errlen = stat.st_size;
2694 } else {
2695 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2696 file, linenum, args[2], BUFSIZE);
2697 errlen = BUFSIZE;
2698 }
2699
2700 err = malloc(errlen); /* malloc() must succeed during parsing */
2701 errnum = read(fd, err, errlen);
2702 if (errnum != errlen) {
2703 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2704 file, linenum, args[2], args[1]);
2705 close(fd);
2706 free(err);
2707 return -1;
2708 }
2709 close(fd);
2710
2711 errnum = atol(args[1]);
2712 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2713 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002714 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002715 curproxy->errmsg[rc].str = err;
2716 curproxy->errmsg[rc].len = errlen;
2717 break;
2718 }
2719 }
2720
2721 if (rc >= HTTP_ERR_SIZE) {
2722 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2723 file, linenum, errnum);
2724 free(err);
2725 }
2726 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002727 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002728 struct cfg_kw_list *kwl;
2729 int index;
2730
2731 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2732 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2733 if (kwl->kw[index].section != CFG_LISTEN)
2734 continue;
2735 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2736 /* prepare error message just in case */
2737 snprintf(trash, sizeof(trash),
2738 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002739 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2740 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002741 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2742 return -1;
2743 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002744 else if (rc > 0) {
2745 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2746 return 0;
2747 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002748 return 0;
2749 }
2750 }
2751 }
2752
Willy Tarreau6daf3432008-01-22 16:44:08 +01002753 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002754 return -1;
2755 }
2756 return 0;
2757}
2758
2759
2760/*
2761 * This function reads and parses the configuration file given in the argument.
2762 * returns 0 if OK, -1 if error.
2763 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002764int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002765{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002766 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002767 FILE *f;
2768 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 int confsect = CFG_NONE;
2771
2772 struct proxy *curproxy = NULL;
2773 struct server *newsrv = NULL;
2774
2775 if ((f=fopen(file,"r")) == NULL)
2776 return -1;
2777
2778 init_default_instance();
2779
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002780 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002781 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002782 char *end;
2783 char *args[MAX_LINE_ARGS + 1];
2784 char *line = thisline;
2785
Willy Tarreaubaaee002006-06-26 02:48:02 +02002786 linenum++;
2787
2788 end = line + strlen(line);
2789
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002790 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2791 /* Check if we reached the limit and the last char is not \n.
2792 * Watch out for the last line without the terminating '\n'!
2793 */
2794 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2795 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002796 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002797 }
2798
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002800 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002801 line++;
2802
2803 arg = 0;
2804 args[arg] = line;
2805
2806 while (*line && arg < MAX_LINE_ARGS) {
2807 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2808 * C equivalent value. Other combinations left unchanged (eg: \1).
2809 */
2810 if (*line == '\\') {
2811 int skip = 0;
2812 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2813 *line = line[1];
2814 skip = 1;
2815 }
2816 else if (line[1] == 'r') {
2817 *line = '\r';
2818 skip = 1;
2819 }
2820 else if (line[1] == 'n') {
2821 *line = '\n';
2822 skip = 1;
2823 }
2824 else if (line[1] == 't') {
2825 *line = '\t';
2826 skip = 1;
2827 }
2828 else if (line[1] == 'x') {
2829 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2830 unsigned char hex1, hex2;
2831 hex1 = toupper(line[2]) - '0';
2832 hex2 = toupper(line[3]) - '0';
2833 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2834 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2835 *line = (hex1<<4) + hex2;
2836 skip = 3;
2837 }
2838 else {
2839 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002840 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841 }
2842 }
2843 if (skip) {
2844 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2845 end -= skip;
2846 }
2847 line++;
2848 }
2849 else if (*line == '#' || *line == '\n' || *line == '\r') {
2850 /* end of string, end of loop */
2851 *line = 0;
2852 break;
2853 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002854 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002856 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002857 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002858 line++;
2859 args[++arg] = line;
2860 }
2861 else {
2862 line++;
2863 }
2864 }
2865
2866 /* empty line */
2867 if (!**args)
2868 continue;
2869
Willy Tarreau540abe42007-05-02 20:50:16 +02002870 /* zero out remaining args and ensure that at least one entry
2871 * is zeroed out.
2872 */
2873 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874 args[arg] = line;
2875 }
2876
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002877 if (!strcmp(args[0], "no")) {
2878 inv = 1;
2879 for (arg=0; *args[arg+1]; arg++)
2880 args[arg] = args[arg+1]; // shift args after inversion
2881 }
2882
2883 if (inv && strcmp(args[0], "option")) {
2884 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002885 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002886 }
2887
Willy Tarreau977b8e42006-12-29 14:19:17 +01002888 if (!strcmp(args[0], "listen") ||
2889 !strcmp(args[0], "frontend") ||
2890 !strcmp(args[0], "backend") ||
2891 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002892 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002893 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002894 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002895 cursection = strdup(args[0]);
2896 }
2897 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002898 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002899 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002900 cursection = strdup(args[0]);
2901 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002902 /* else it's a section keyword */
2903
2904 switch (confsect) {
2905 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002906 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002907 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002908 break;
2909 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002910 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002911 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 break;
2913 default:
2914 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002915 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002917 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002918 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002919 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002920 fclose(f);
2921
2922 /*
2923 * Now, check for the integrity of all that we have collected.
2924 */
2925
2926 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002927 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928
2929 if ((curproxy = proxy) == NULL) {
2930 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2931 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002932 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002933 }
2934
2935 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002936 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002937 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002938
Willy Tarreaubaaee002006-06-26 02:48:02 +02002939 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02002940 /* ensure we don't keep listeners uselessly bound */
2941 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002942 curproxy = curproxy->next;
2943 continue;
2944 }
2945
Willy Tarreau977b8e42006-12-29 14:19:17 +01002946 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2947 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 +01002948 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002949 cfgerr++;
2950 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002951 else if (curproxy->cap & PR_CAP_BE &&
2952 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002953 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002954 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002955 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2956 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 +01002957 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002958 cfgerr++;
2959 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002960
Willy Tarreau31682232007-11-29 15:38:04 +01002961 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002962 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002963 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002964 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002965 cfgerr++;
2966 }
2967#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2968 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002969 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002970 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 cfgerr++;
2972 }
2973#endif
2974 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002975 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002976 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002977 }
2978 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002979
2980 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002981 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002982 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002983 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002985 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002986 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002987 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002988 }
2989 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002990 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002991 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002992 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002993 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002994 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002995 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002996 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002997 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002998 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2999 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003000
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01003001 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003002 file, proxy_type_str(curproxy), curproxy->id);
3003 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003005
3006 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
3007 if ((newsrv = curproxy->srv) != NULL) {
3008 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
3009 file, proxy_type_str(curproxy), curproxy->id);
3010 }
3011 }
3012
3013 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
3015 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
3016 file, curproxy->id);
3017 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003018 }
3019 }
3020
Willy Tarreau82936582007-11-30 15:20:09 +01003021 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3022 curproxy->options &= ~PR_O_DISABLE404;
3023 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3024 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
3025 }
3026
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003027 /* if a default backend was specified, let's find it */
3028 if (curproxy->defbe.name) {
3029 struct proxy *target;
3030
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003031 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3032 if (!target) {
3033 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3034 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003035 cfgerr++;
3036 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003037 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3038 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003039 } else {
3040 free(curproxy->defbe.name);
3041 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042 }
3043 }
3044
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003045 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003046 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3047 /* map jump target for ACT_SETBE in req_rep chain */
3048 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003049 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003050 struct proxy *target;
3051
Willy Tarreaua496b602006-12-17 23:15:24 +01003052 if (exp->action != ACT_SETBE)
3053 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003054
3055 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3056 if (!target) {
3057 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3058 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003059 cfgerr++;
3060 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003061 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3062 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003063 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003064 } else {
3065 free((void *)exp->replace);
3066 exp->replace = (const char *)target;
3067 }
3068 }
3069 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003070
3071 /* find the target proxy for 'use_backend' rules */
3072 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003073 struct proxy *target;
3074
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003075 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003076
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003077 if (!target) {
3078 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3079 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003080 cfgerr++;
3081 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003082 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3083 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003084 cfgerr++;
3085 } else {
3086 free((void *)rule->be.name);
3087 rule->be.backend = target;
3088 }
3089 }
3090
Willy Tarreau2738a142006-07-08 17:28:09 +02003091 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003092 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003093 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003094 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003095 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003096 " | While not properly invalid, you will certainly encounter various problems\n"
3097 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003098 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003099 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003100 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003101
Willy Tarreau1fa31262007-12-03 00:36:16 +01003102 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3103 * We must still support older configurations, so let's find out whether those
3104 * parameters have been set or must be copied from contimeouts.
3105 */
3106 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003107 if (!curproxy->timeout.tarpit ||
3108 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003109 /* tarpit timeout not set. We search in the following order:
3110 * default.tarpit, curr.connect, default.connect.
3111 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003112 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003113 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003114 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003115 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003116 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003117 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003118 }
3119 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003120 (!curproxy->timeout.queue ||
3121 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003122 /* queue timeout not set. We search in the following order:
3123 * default.queue, curr.connect, default.connect.
3124 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003125 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003126 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003127 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003128 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003129 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003130 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003131 }
3132 }
3133
Willy Tarreauf3c69202006-07-09 16:42:34 +02003134 if (curproxy->options & PR_O_SSL3_CHK) {
3135 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3136 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3137 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3138 }
3139
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003140 /* The small pools required for the capture lists */
3141 if (curproxy->nb_req_cap)
3142 curproxy->req_cap_pool = create_pool("ptrcap",
3143 curproxy->nb_req_cap * sizeof(char *),
3144 MEM_F_SHARED);
3145 if (curproxy->nb_rsp_cap)
3146 curproxy->rsp_cap_pool = create_pool("ptrcap",
3147 curproxy->nb_rsp_cap * sizeof(char *),
3148 MEM_F_SHARED);
3149
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003150 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3151 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3152 MEM_F_SHARED);
3153
Willy Tarreau86034312006-12-29 00:10:33 +01003154 /* for backwards compatibility with "listen" instances, if
3155 * fullconn is not set but maxconn is set, then maxconn
3156 * is used.
3157 */
3158 if (!curproxy->fullconn)
3159 curproxy->fullconn = curproxy->maxconn;
3160
Willy Tarreaubaaee002006-06-26 02:48:02 +02003161 /* first, we will invert the servers list order */
3162 newsrv = NULL;
3163 while (curproxy->srv) {
3164 struct server *next;
3165
3166 next = curproxy->srv->next;
3167 curproxy->srv->next = newsrv;
3168 newsrv = curproxy->srv;
3169 if (!next)
3170 break;
3171 curproxy->srv = next;
3172 }
3173
Willy Tarreau20697042007-11-15 23:26:18 +01003174 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003175 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176
Willy Tarreaub625a082007-11-26 01:15:43 +01003177 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003178 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003179 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003180 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3181 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003182 else
3183 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184
3185 if (curproxy->options & PR_O_LOGASAP)
3186 curproxy->to_log &= ~LW_BYTES;
3187
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003189 * ensure that we're not cross-dressing a TCP server into HTTP.
3190 */
3191 newsrv = curproxy->srv;
3192 while (newsrv != NULL) {
3193 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3194 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3195 file, proxy_type_str(curproxy), curproxy->id, linenum);
3196 goto err;
3197 }
3198 newsrv = newsrv->next;
3199 }
3200
3201 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202 * If this server supports a maxconn parameter, it needs a dedicated
3203 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003204 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003205 */
3206 newsrv = curproxy->srv;
3207 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003208 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 /* Only 'minconn' was specified, or it was higher than or equal
3210 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3211 * this will avoid further useless expensive computations.
3212 */
3213 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003214 } else if (newsrv->maxconn && !newsrv->minconn) {
3215 /* minconn was not specified, so we set it to maxconn */
3216 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003217 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3218 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003219 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003220 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 }
3222
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003223 if (newsrv->trackit) {
3224 struct proxy *px;
3225 struct server *srv;
3226 char *pname, *sname;
3227
3228 pname = newsrv->trackit;
3229 sname = strrchr(pname, '/');
3230
3231 if (sname)
3232 *sname++ = '\0';
3233 else {
3234 sname = pname;
3235 pname = NULL;
3236 }
3237
3238 if (pname) {
3239 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3240 if (!px) {
3241 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3242 file, proxy_type_str(curproxy), curproxy->id,
3243 newsrv->id, pname);
3244 return -1;
3245 }
3246 } else
3247 px = curproxy;
3248
3249 srv = findserver(px, sname);
3250 if (!srv) {
3251 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3252 file, proxy_type_str(curproxy), curproxy->id,
3253 newsrv->id, sname);
3254 return -1;
3255 }
3256
3257 if (!(srv->state & SRV_CHECKED)) {
3258 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3259 "tracing as it does not have checks enabled.\n",
3260 file, proxy_type_str(curproxy), curproxy->id,
3261 newsrv->id, px->id, srv->id);
3262 return -1;
3263 }
3264
3265 if (curproxy != px &&
3266 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3267 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3268 "tracing: disable-on-404 option inconsistency.\n",
3269 file, proxy_type_str(curproxy), curproxy->id,
3270 newsrv->id, px->id, srv->id);
3271 return -1;
3272 }
3273
3274 newsrv->tracked = srv;
3275 newsrv->tracknext = srv->tracknext;
3276 srv->tracknext = newsrv;
3277
3278 free(newsrv->trackit);
3279 }
3280
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 newsrv = newsrv->next;
3282 }
3283
Willy Tarreaue6b98942007-10-29 01:09:36 +01003284 /* adjust this proxy's listeners */
3285 listener = curproxy->listen;
3286 while (listener) {
3287 if (curproxy->options & PR_O_TCP_NOLING)
3288 listener->options |= LI_O_NOLINGER;
3289 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003290 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003291 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003292 listener->accept = event_accept;
3293 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003294 listener->handler = process_session;
3295
3296 if (curproxy->mode == PR_MODE_HTTP)
3297 listener->analysers |= AN_REQ_HTTP_HDR;
3298
3299 if (curproxy->tcp_req.inspect_delay)
3300 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003301
3302 listener = listener->next;
3303 }
3304
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 curproxy = curproxy->next;
3306 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003307
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 if (cfgerr > 0) {
3309 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003310 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003312
3313 /*
3314 * Recount currently required checks.
3315 */
3316
3317 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3318 int optnum;
3319
3320 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3321 if (!(curproxy->options & cfg_opts[optnum].val))
3322 continue;
3323
3324 global.last_checks |= cfg_opts[optnum].checks;
3325 }
3326 }
3327
Willy Tarreaua534fea2008-08-03 12:19:50 +02003328 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003329 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003330 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003331
3332 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003333 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003334 cursection = NULL;
3335 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003336}
3337
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003338/*
3339 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3340 * parsing sessions.
3341 */
3342void cfg_register_keywords(struct cfg_kw_list *kwl)
3343{
3344 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3345}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003346
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003347/*
3348 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3349 */
3350void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3351{
3352 LIST_DEL(&kwl->list);
3353 LIST_INIT(&kwl->list);
3354}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355
3356/*
3357 * Local variables:
3358 * c-indent-level: 8
3359 * c-basic-offset: 8
3360 * End:
3361 */