blob: ede1b22f65ff9650fe0453cf066cdffb7aaf305f [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
110 { "transparent", PR_O_TRANSP, PR_CAP_FE, 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 Tarreau79da4692008-11-19 20:03:04 +01001121 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001122
1123 cur_arg = 1;
1124 while (*(args[cur_arg])) {
1125 if (!strcmp(args[cur_arg], "location")) {
1126 if (!*args[cur_arg + 1]) {
1127 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1128 file, linenum, args[0], args[cur_arg]);
1129 return -1;
1130 }
1131
1132 type = REDIRECT_TYPE_LOCATION;
1133 cur_arg++;
1134 destination = args[cur_arg];
1135 }
1136 else if (!strcmp(args[cur_arg], "prefix")) {
1137 if (!*args[cur_arg + 1]) {
1138 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1139 file, linenum, args[0], args[cur_arg]);
1140 return -1;
1141 }
1142
1143 type = REDIRECT_TYPE_PREFIX;
1144 cur_arg++;
1145 destination = args[cur_arg];
1146 }
1147 else if (!strcmp(args[cur_arg],"code")) {
1148 if (!*args[cur_arg + 1]) {
1149 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1150 file, linenum, args[0]);
1151 return -1;
1152 }
1153 cur_arg++;
1154 code = atol(args[cur_arg]);
1155 if (code < 301 || code > 303) {
1156 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1157 file, linenum, args[0], code);
1158 return -1;
1159 }
1160 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001161 else if (!strcmp(args[cur_arg],"drop-query")) {
1162 flags |= REDIRECT_FLAG_DROP_QS;
1163 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001164 else if (!strcmp(args[cur_arg], "if")) {
1165 pol = ACL_COND_IF;
1166 cur_arg++;
1167 break;
1168 }
1169 else if (!strcmp(args[cur_arg], "unless")) {
1170 pol = ACL_COND_UNLESS;
1171 cur_arg++;
1172 break;
1173 }
1174 else {
1175 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1176 file, linenum, args[0], args[cur_arg]);
1177 return -1;
1178 }
1179 cur_arg++;
1180 }
1181
1182 if (type == REDIRECT_TYPE_NONE) {
1183 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1184 file, linenum, args[0]);
1185 return -1;
1186 }
1187
1188 if (pol == ACL_COND_NONE) {
1189 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1190 file, linenum, args[0]);
1191 return -1;
1192 }
1193
1194 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1195 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1196 file, linenum, args[0]);
1197 return -1;
1198 }
1199
Willy Tarreaua9802632008-07-25 19:13:19 +02001200 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001201 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1202 rule->cond = cond;
1203 rule->rdr_str = strdup(destination);
1204 rule->rdr_len = strlen(destination);
1205 rule->type = type;
1206 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001207 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001208 LIST_INIT(&rule->list);
1209 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1210 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001211 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1212 int pol = ACL_COND_NONE;
1213 struct acl_cond *cond;
1214 struct switching_rule *rule;
1215
Willy Tarreaub099aca2008-10-12 17:26:37 +02001216 if (curproxy == &defproxy) {
1217 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1218 return -1;
1219 }
1220
Willy Tarreau55ea7572007-06-17 19:56:27 +02001221 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1222 return 0;
1223
1224 if (*(args[1]) == 0) {
1225 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1226 return -1;
1227 }
1228
1229 if (!strcmp(args[2], "if"))
1230 pol = ACL_COND_IF;
1231 else if (!strcmp(args[2], "unless"))
1232 pol = ACL_COND_UNLESS;
1233
1234 if (pol == ACL_COND_NONE) {
1235 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1236 file, linenum, args[0]);
1237 return -1;
1238 }
1239
1240 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001241 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001242 file, linenum);
1243 return -1;
1244 }
1245
Willy Tarreaua9802632008-07-25 19:13:19 +02001246 cond->line = linenum;
1247 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001248 struct acl *acl;
1249 const char *name;
1250
1251 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1252 name = acl ? acl->name : "(unknown)";
1253 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1254 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001255 }
1256
Willy Tarreau55ea7572007-06-17 19:56:27 +02001257 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1258 rule->cond = cond;
1259 rule->be.name = strdup(args[1]);
1260 LIST_INIT(&rule->list);
1261 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001263 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001264 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1265 return 0;
1266
Willy Tarreaubaaee002006-06-26 02:48:02 +02001267 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1268 curproxy->uri_auth = NULL; /* we must detach from the default config */
1269
1270 if (*(args[1]) == 0) {
1271 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1272 return -1;
1273 } else if (!strcmp(args[1], "uri")) {
1274 if (*(args[2]) == 0) {
1275 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1276 return -1;
1277 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1278 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1279 return -1;
1280 }
1281 } else if (!strcmp(args[1], "realm")) {
1282 if (*(args[2]) == 0) {
1283 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1284 return -1;
1285 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1286 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1287 return -1;
1288 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001289 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001290 unsigned interval;
1291
1292 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1293 if (err) {
1294 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1295 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001296 return -1;
1297 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1298 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1299 return -1;
1300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001301 } else if (!strcmp(args[1], "auth")) {
1302 if (*(args[2]) == 0) {
1303 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1304 return -1;
1305 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1306 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1307 return -1;
1308 }
1309 } else if (!strcmp(args[1], "scope")) {
1310 if (*(args[2]) == 0) {
1311 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1312 return -1;
1313 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1314 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1315 return -1;
1316 }
1317 } else if (!strcmp(args[1], "enable")) {
1318 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1319 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1320 return -1;
1321 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001322 } else if (!strcmp(args[1], "hide-version")) {
1323 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1324 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1325 return -1;
1326 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001327 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001328 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001329 file, linenum, args[0]);
1330 return -1;
1331 }
1332 }
1333 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001334 int optnum;
1335
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001336 if (*(args[1]) == '\0') {
1337 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1338 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001339 return -1;
1340 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001341
1342 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1343 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1344 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1345 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001346
1347 if (!inv)
1348 curproxy->options |= cfg_opts[optnum].val;
1349 else
1350 curproxy->options &= ~cfg_opts[optnum].val;
1351
Willy Tarreau13943ab2006-12-31 00:24:10 +01001352 return 0;
1353 }
1354 }
1355
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001356 if (inv) {
1357 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1358 file, linenum, args[1]);
1359 return -1;
1360 }
1361
Willy Tarreau13943ab2006-12-31 00:24:10 +01001362 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363 /* generate a complete HTTP log */
1364 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1365 else if (!strcmp(args[1], "tcplog"))
1366 /* generate a detailed TCP log */
1367 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368 else if (!strcmp(args[1], "tcpka")) {
1369 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001370 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1371 return 0;
1372
1373 if (curproxy->cap & PR_CAP_FE)
1374 curproxy->options |= PR_O_TCP_CLI_KA;
1375 if (curproxy->cap & PR_CAP_BE)
1376 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001377 }
1378 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001379 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1380 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001381 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001382 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001383 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001384 curproxy->options &= ~PR_O_SMTP_CHK;
1385 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001386 if (!*args[2]) { /* no argument */
1387 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1388 curproxy->check_len = strlen(DEF_CHECK_REQ);
1389 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001390 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391 curproxy->check_req = (char *)malloc(reqlen);
1392 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1393 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1394 } else { /* more arguments : METHOD URI [HTTP_VER] */
1395 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1396 if (*args[4])
1397 reqlen += strlen(args[4]);
1398 else
1399 reqlen += strlen("HTTP/1.0");
1400
1401 curproxy->check_req = (char *)malloc(reqlen);
1402 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1403 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1404 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001405 }
1406 else if (!strcmp(args[1], "ssl-hello-chk")) {
1407 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001408 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1409 return 0;
1410
Willy Tarreaua534fea2008-08-03 12:19:50 +02001411 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001412 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001413 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001414 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 }
Willy Tarreau23677902007-05-08 23:50:35 +02001416 else if (!strcmp(args[1], "smtpchk")) {
1417 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001418 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001419 curproxy->options &= ~PR_O_HTTP_CHK;
1420 curproxy->options &= ~PR_O_SSL3_CHK;
1421 curproxy->options |= PR_O_SMTP_CHK;
1422
1423 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1424 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1425 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1426 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1427 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1428 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1429 curproxy->check_req = (char *)malloc(reqlen);
1430 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1431 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1432 } else {
1433 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1434 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1435 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1436 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1437 }
1438 }
1439 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001440 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001441 int cur_arg;
1442
1443 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1444 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001445 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001446
1447 curproxy->options |= PR_O_FWDFOR;
1448
1449 free(curproxy->fwdfor_hdr_name);
1450 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1451 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1452
1453 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1454 cur_arg = 2;
1455 while (*(args[cur_arg])) {
1456 if (!strcmp(args[cur_arg], "except")) {
1457 /* suboption except - needs additional argument for it */
1458 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1459 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1460 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001461 return -1;
1462 }
1463 /* flush useless bits */
1464 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001465 cur_arg += 2;
1466 } else if (!strcmp(args[cur_arg], "header")) {
1467 /* suboption header - needs additional argument for it */
1468 if (*(args[cur_arg+1]) == 0) {
1469 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1470 file, linenum, args[0], args[1], args[cur_arg]);
1471 return -1;
1472 }
1473 free(curproxy->fwdfor_hdr_name);
1474 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1475 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1476 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001477 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001478 /* unknown suboption - catchall */
1479 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1480 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001481 return -1;
1482 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001483 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001484 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485 else {
1486 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1487 return -1;
1488 }
1489 return 0;
1490 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001491 else if (!strcmp(args[0], "default_backend")) {
1492 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1493 return 0;
1494
1495 if (*(args[1]) == 0) {
1496 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1497 return -1;
1498 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001499 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001500 curproxy->defbe.name = strdup(args[1]);
1501 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001502 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001503 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1504 return 0;
1505
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001506 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1507 file, linenum, args[0]);
1508
Willy Tarreaubaaee002006-06-26 02:48:02 +02001509 /* enable reconnections to dispatch */
1510 curproxy->options |= PR_O_REDISP;
1511 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001512 else if (!strcmp(args[0], "http-check")) {
1513 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1514 return 0;
1515
1516 if (strcmp(args[1], "disable-on-404") == 0) {
1517 /* enable a graceful server shutdown on an HTTP 404 response */
1518 curproxy->options |= PR_O_DISABLE404;
1519 }
1520 else {
1521 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1522 return -1;
1523 }
1524 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001525 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001526 if (curproxy == &defproxy) {
1527 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1528 return -1;
1529 }
1530
Willy Tarreaub80c2302007-11-30 20:51:32 +01001531 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1532 return 0;
1533
1534 if (strcmp(args[1], "fail") == 0) {
1535 /* add a condition to fail monitor requests */
1536 int pol = ACL_COND_NONE;
1537 struct acl_cond *cond;
1538
1539 if (!strcmp(args[2], "if"))
1540 pol = ACL_COND_IF;
1541 else if (!strcmp(args[2], "unless"))
1542 pol = ACL_COND_UNLESS;
1543
1544 if (pol == ACL_COND_NONE) {
1545 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1546 file, linenum, args[0], args[1]);
1547 return -1;
1548 }
1549
1550 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1551 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1552 file, linenum, args[0], args[1]);
1553 return -1;
1554 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001555 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001556 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1557 }
1558 else {
1559 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1560 return -1;
1561 }
1562 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563#ifdef TPROXY
1564 else if (!strcmp(args[0], "transparent")) {
1565 /* enable transparent proxy connections */
1566 curproxy->options |= PR_O_TRANSP;
1567 }
1568#endif
1569 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001570 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1571 return 0;
1572
Willy Tarreaubaaee002006-06-26 02:48:02 +02001573 if (*(args[1]) == 0) {
1574 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1575 return -1;
1576 }
1577 curproxy->maxconn = atol(args[1]);
1578 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001579 else if (!strcmp(args[0], "backlog")) { /* backlog */
1580 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1581 return 0;
1582
1583 if (*(args[1]) == 0) {
1584 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1585 return -1;
1586 }
1587 curproxy->backlog = atol(args[1]);
1588 }
Willy Tarreau86034312006-12-29 00:10:33 +01001589 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001590 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1591 return 0;
1592
Willy Tarreau86034312006-12-29 00:10:33 +01001593 if (*(args[1]) == 0) {
1594 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1595 return -1;
1596 }
1597 curproxy->fullconn = atol(args[1]);
1598 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001599 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1600 if (*(args[1]) == 0) {
1601 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1602 return -1;
1603 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001604 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1605 if (err) {
1606 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1607 file, linenum, *err);
1608 return -1;
1609 }
1610 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611 }
1612 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1613 if (curproxy == &defproxy) {
1614 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1615 return -1;
1616 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001617 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1618 return 0;
1619
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 if (strchr(args[1], ':') == NULL) {
1621 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1622 return -1;
1623 }
1624 curproxy->dispatch_addr = *str2sa(args[1]);
1625 }
1626 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001627 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1628 return 0;
1629
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02001630 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001631 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1632 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1633 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001634 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635 }
1636 else if (!strcmp(args[0], "server")) { /* server address */
1637 int cur_arg;
1638 char *rport;
1639 char *raddr;
1640 short realport;
1641 int do_check;
1642
1643 if (curproxy == &defproxy) {
1644 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1645 return -1;
1646 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001647 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1648 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649
1650 if (!*args[2]) {
1651 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1652 file, linenum, args[0]);
1653 return -1;
1654 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001655
1656 err = invalid_char(args[1]);
1657 if (err) {
1658 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1659 file, linenum, *err, args[1]);
1660 return -1;
1661 }
1662
Willy Tarreaubaaee002006-06-26 02:48:02 +02001663 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1664 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1665 return -1;
1666 }
1667
1668 /* the servers are linked backwards first */
1669 newsrv->next = curproxy->srv;
1670 curproxy->srv = newsrv;
1671 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001672 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673
1674 LIST_INIT(&newsrv->pendconns);
1675 do_check = 0;
1676 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001677 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001678 newsrv->id = strdup(args[1]);
1679
1680 /* several ways to check the port component :
1681 * - IP => port=+0, relative
1682 * - IP: => port=+0, relative
1683 * - IP:N => port=N, absolute
1684 * - IP:+N => port=+N, relative
1685 * - IP:-N => port=-N, relative
1686 */
1687 raddr = strdup(args[2]);
1688 rport = strchr(raddr, ':');
1689 if (rport) {
1690 *rport++ = 0;
1691 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001692 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001693 newsrv->state |= SRV_MAPPORTS;
1694 } else {
1695 realport = 0;
1696 newsrv->state |= SRV_MAPPORTS;
1697 }
1698
1699 newsrv->addr = *str2sa(raddr);
1700 newsrv->addr.sin_port = htons(realport);
1701 free(raddr);
1702
1703 newsrv->curfd = -1; /* no health-check in progress */
1704 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001705 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1706 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001707 newsrv->rise = DEF_RISETIME;
1708 newsrv->fall = DEF_FALLTIME;
1709 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001710 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001711 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001712 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001713
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 cur_arg = 3;
1715 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001716 if (!strcmp(args[cur_arg], "id")) {
1717 struct server *target;
1718
1719 if (!*args[cur_arg + 1]) {
1720 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1721 file, linenum, args[cur_arg]);
1722 return -1;
1723 }
1724
1725 newsrv->puid = atol(args[cur_arg + 1]);
1726
1727 if (newsrv->puid< 1001) {
1728 Alert("parsing [%s:%d]: custom id has to be > 1000",
1729 file, linenum);
1730 return -1;
1731 }
1732
1733 for (target = proxy->srv; target; target = target->next)
1734 if (newsrv != target && newsrv->puid == target->puid) {
1735 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1736 file, linenum, newsrv->id, target->id);
1737 return -1;
1738 }
1739 cur_arg += 2;
1740 }
1741 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742 newsrv->cookie = strdup(args[cur_arg + 1]);
1743 newsrv->cklen = strlen(args[cur_arg + 1]);
1744 cur_arg += 2;
1745 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001746 else if (!strcmp(args[cur_arg], "redir")) {
1747 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1748 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1749 cur_arg += 2;
1750 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001751 else if (!strcmp(args[cur_arg], "rise")) {
1752 newsrv->rise = atol(args[cur_arg + 1]);
1753 newsrv->health = newsrv->rise;
1754 cur_arg += 2;
1755 }
1756 else if (!strcmp(args[cur_arg], "fall")) {
1757 newsrv->fall = atol(args[cur_arg + 1]);
1758 cur_arg += 2;
1759 }
1760 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001761 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1762 if (err) {
1763 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1764 file, linenum, *err, newsrv->id);
1765 return -1;
1766 }
1767 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001768 cur_arg += 2;
1769 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001770 else if (!strcmp(args[cur_arg], "fastinter")) {
1771 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1772 if (err) {
1773 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1774 file, linenum, *err, newsrv->id);
1775 return -1;
1776 }
1777 newsrv->fastinter = val;
1778 cur_arg += 2;
1779 }
1780 else if (!strcmp(args[cur_arg], "downinter")) {
1781 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1782 if (err) {
1783 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1784 file, linenum, *err, newsrv->id);
1785 return -1;
1786 }
1787 newsrv->downinter = val;
1788 cur_arg += 2;
1789 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001790 else if (!strcmp(args[cur_arg], "addr")) {
1791 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001792 cur_arg += 2;
1793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794 else if (!strcmp(args[cur_arg], "port")) {
1795 newsrv->check_port = atol(args[cur_arg + 1]);
1796 cur_arg += 2;
1797 }
1798 else if (!strcmp(args[cur_arg], "backup")) {
1799 newsrv->state |= SRV_BACKUP;
1800 cur_arg ++;
1801 }
1802 else if (!strcmp(args[cur_arg], "weight")) {
1803 int w;
1804 w = atol(args[cur_arg + 1]);
1805 if (w < 1 || w > 256) {
1806 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1807 file, linenum, newsrv->id, w);
1808 return -1;
1809 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001810 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001811 cur_arg += 2;
1812 }
1813 else if (!strcmp(args[cur_arg], "minconn")) {
1814 newsrv->minconn = atol(args[cur_arg + 1]);
1815 cur_arg += 2;
1816 }
1817 else if (!strcmp(args[cur_arg], "maxconn")) {
1818 newsrv->maxconn = atol(args[cur_arg + 1]);
1819 cur_arg += 2;
1820 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001821 else if (!strcmp(args[cur_arg], "maxqueue")) {
1822 newsrv->maxqueue = atol(args[cur_arg + 1]);
1823 cur_arg += 2;
1824 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001825 else if (!strcmp(args[cur_arg], "slowstart")) {
1826 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001827 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001828 if (err) {
1829 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1830 file, linenum, *err, newsrv->id);
1831 return -1;
1832 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001833 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001834 cur_arg += 2;
1835 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001836 else if (!strcmp(args[cur_arg], "track")) {
1837
1838 if (!*args[cur_arg + 1]) {
1839 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1840 file, linenum);
1841 return -1;
1842 }
1843
1844 newsrv->trackit = strdup(args[cur_arg + 1]);
1845
1846 cur_arg += 2;
1847 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001848 else if (!strcmp(args[cur_arg], "check")) {
1849 global.maxsock++;
1850 do_check = 1;
1851 cur_arg += 1;
1852 }
1853 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1854 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001855#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001856 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1857 file, linenum, "source", "usesrc");
1858#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001859 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1860 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001861#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001862 return -1;
1863 }
1864 newsrv->state |= SRV_BIND_SRC;
1865 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1866 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001867 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001868#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1869#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001870 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001871 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1872 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001873 return -1;
1874 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001875#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001876 if (!*args[cur_arg + 1]) {
1877 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1878 file, linenum, "usesrc");
1879 return -1;
1880 }
1881 if (!strcmp(args[cur_arg + 1], "client")) {
1882 newsrv->state |= SRV_TPROXY_CLI;
1883 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1884 newsrv->state |= SRV_TPROXY_CIP;
1885 } else {
1886 newsrv->state |= SRV_TPROXY_ADDR;
1887 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1888 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001889 global.last_checks |= LSTCHK_NETADM;
1890#if !defined(CONFIG_HAP_LINUX_TPROXY)
1891 global.last_checks |= LSTCHK_CTTPROXY;
1892#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001893 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001894#else /* no TPROXY support */
1895 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001896 file, linenum, "usesrc");
1897 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001898#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001901 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1902 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1903 file, linenum, "usesrc", "source");
1904 return -1;
1905 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001907 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 +02001908 file, linenum, newsrv->id);
1909 return -1;
1910 }
1911 }
1912
1913 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001914 if (newsrv->trackit) {
1915 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1916 file, linenum);
1917 return -1;
1918 }
1919
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001920 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1921 newsrv->check_port = newsrv->check_addr.sin_port;
1922
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1924 newsrv->check_port = realport; /* by default */
1925 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001926 /* not yet valid, because no port was set on
1927 * the server either. We'll check if we have
1928 * a known port on the first listener.
1929 */
1930 struct listener *l;
1931 l = curproxy->listen;
1932 if (l) {
1933 int port;
1934 port = (l->addr.ss_family == AF_INET6)
1935 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1936 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1937 newsrv->check_port = port;
1938 }
1939 }
1940 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001941 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1942 file, linenum, newsrv->id);
1943 return -1;
1944 }
1945 newsrv->state |= SRV_CHECKED;
1946 }
1947
1948 if (newsrv->state & SRV_BACKUP)
1949 curproxy->srv_bck++;
1950 else
1951 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001952
1953 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001954 }
1955 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001956 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001957 int facility;
1958
1959 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1960 curproxy->logfac1 = global.logfac1;
1961 curproxy->logsrv1 = global.logsrv1;
1962 curproxy->loglev1 = global.loglev1;
1963 curproxy->logfac2 = global.logfac2;
1964 curproxy->logsrv2 = global.logsrv2;
1965 curproxy->loglev2 = global.loglev2;
1966 }
1967 else if (*(args[1]) && *(args[2])) {
1968 int level;
1969
1970 facility = get_log_facility(args[2]);
1971 if (facility < 0) {
1972 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1973 exit(1);
1974 }
1975
1976 level = 7; /* max syslog level = debug */
1977 if (*(args[3])) {
1978 level = get_log_level(args[3]);
1979 if (level < 0) {
1980 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1981 exit(1);
1982 }
1983 }
1984
Robert Tsai81ae1952007-12-05 10:47:29 +01001985 if (args[1][0] == '/') {
1986 logsrv.u.addr.sa_family = AF_UNIX;
1987 logsrv.u.un = *str2sun(args[1]);
1988 } else {
1989 logsrv.u.addr.sa_family = AF_INET;
1990 logsrv.u.in = *str2sa(args[1]);
1991 if (!logsrv.u.in.sin_port) {
1992 logsrv.u.in.sin_port =
1993 htons(SYSLOG_PORT);
1994 }
1995 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001996
1997 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001998 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001999 curproxy->logfac1 = facility;
2000 curproxy->loglev1 = level;
2001 }
2002 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002003 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004 curproxy->logfac2 = facility;
2005 curproxy->loglev2 = level;
2006 }
2007 else {
2008 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2009 return -1;
2010 }
2011 }
2012 else {
2013 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2014 file, linenum);
2015 return -1;
2016 }
2017 }
2018 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002019 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2020 return 0;
2021
Willy Tarreaubaaee002006-06-26 02:48:02 +02002022 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002023#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002024 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2025 file, linenum, "source", "usesrc");
2026#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002027 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2028 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002029#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002030 return -1;
2031 }
2032
2033 curproxy->source_addr = *str2sa(args[1]);
2034 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01002035 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002036#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2037#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002038 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2039 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2040 file, linenum, "usesrc");
2041 return -1;
2042 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002043#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002044 if (!*args[3]) {
2045 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2046 file, linenum, "usesrc");
2047 return -1;
2048 }
2049
2050 if (!strcmp(args[3], "client")) {
2051 curproxy->options |= PR_O_TPXY_CLI;
2052 } else if (!strcmp(args[3], "clientip")) {
2053 curproxy->options |= PR_O_TPXY_CIP;
2054 } else {
2055 curproxy->options |= PR_O_TPXY_ADDR;
2056 curproxy->tproxy_addr = *str2sa(args[3]);
2057 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002058 global.last_checks |= LSTCHK_NETADM;
2059#if !defined(CONFIG_HAP_LINUX_TPROXY)
2060 global.last_checks |= LSTCHK_CTTPROXY;
2061#endif
2062#else /* no TPROXY support */
2063 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002064 file, linenum, "usesrc");
2065 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002066#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002067 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002068 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002069 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2070 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2071 file, linenum, "usesrc", "source");
2072 return -1;
2073 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2075 regex_t *preg;
2076 if (curproxy == &defproxy) {
2077 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2078 return -1;
2079 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002080 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2081 return 0;
2082
Willy Tarreaubaaee002006-06-26 02:48:02 +02002083 if (*(args[1]) == 0 || *(args[2]) == 0) {
2084 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2085 file, linenum, args[0]);
2086 return -1;
2087 }
2088
2089 preg = calloc(1, sizeof(regex_t));
2090 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2091 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2092 return -1;
2093 }
2094
2095 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2096 if (err) {
2097 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2098 file, linenum, *err);
2099 return -1;
2100 }
2101 }
2102 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2103 regex_t *preg;
2104 if (curproxy == &defproxy) {
2105 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2106 return -1;
2107 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002108 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2109 return 0;
2110
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 if (*(args[1]) == 0) {
2112 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2113 return -1;
2114 }
2115
2116 preg = calloc(1, sizeof(regex_t));
2117 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2118 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2119 return -1;
2120 }
2121
2122 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2123 }
2124 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2125 regex_t *preg;
2126 if (curproxy == &defproxy) {
2127 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2128 return -1;
2129 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002130 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2131 return 0;
2132
Willy Tarreaubaaee002006-06-26 02:48:02 +02002133 if (*(args[1]) == 0) {
2134 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2135 return -1;
2136 }
2137
2138 preg = calloc(1, sizeof(regex_t));
2139 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2140 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2141 return -1;
2142 }
2143
2144 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2145 }
2146 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2147 regex_t *preg;
2148 if (curproxy == &defproxy) {
2149 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2150 return -1;
2151 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002152 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2153 return 0;
2154
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155 if (*(args[1]) == 0) {
2156 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2157 return -1;
2158 }
2159
2160 preg = calloc(1, sizeof(regex_t));
2161 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2162 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2163 return -1;
2164 }
2165
2166 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2167 }
2168 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2169 regex_t *preg;
2170 if (curproxy == &defproxy) {
2171 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2172 return -1;
2173 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002174 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2175 return 0;
2176
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 if (*(args[1]) == 0) {
2178 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2179 return -1;
2180 }
2181
2182 preg = calloc(1, sizeof(regex_t));
2183 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2184 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2185 return -1;
2186 }
2187
2188 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2189 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002190 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2191 regex_t *preg;
2192 if (curproxy == &defproxy) {
2193 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2194 return -1;
2195 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002196 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2197 return 0;
2198
Willy Tarreaub8750a82006-09-03 09:56:00 +02002199 if (*(args[1]) == 0) {
2200 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2201 return -1;
2202 }
2203
2204 preg = calloc(1, sizeof(regex_t));
2205 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2206 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2207 return -1;
2208 }
2209
2210 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2211 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002212 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2213 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002214 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002215 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2216 return -1;
2217 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002218 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2219 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002220
Willy Tarreau977b8e42006-12-29 14:19:17 +01002221 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002222 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2223 file, linenum, args[0]);
2224 return -1;
2225 }
2226
2227 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002228 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002229 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2230 }
2231
2232 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2233 }
2234 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2235 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002236 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002237 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2238 return -1;
2239 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002240 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2241 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002242
Willy Tarreau977b8e42006-12-29 14:19:17 +01002243 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002244 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2245 file, linenum, args[0]);
2246 return -1;
2247 }
2248
2249 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002250 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002251 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2252 }
2253
2254 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2257 regex_t *preg;
2258 if (curproxy == &defproxy) {
2259 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2260 return -1;
2261 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002262 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2263 return 0;
2264
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 if (*(args[1]) == 0 || *(args[2]) == 0) {
2266 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2267 file, linenum, args[0]);
2268 return -1;
2269 }
2270
2271 preg = calloc(1, sizeof(regex_t));
2272 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2273 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2274 return -1;
2275 }
2276
2277 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2278 if (err) {
2279 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2280 file, linenum, *err);
2281 return -1;
2282 }
2283 }
2284 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2285 regex_t *preg;
2286 if (curproxy == &defproxy) {
2287 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2288 return -1;
2289 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002290 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2291 return 0;
2292
Willy Tarreaubaaee002006-06-26 02:48:02 +02002293 if (*(args[1]) == 0) {
2294 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2295 return -1;
2296 }
2297
2298 preg = calloc(1, sizeof(regex_t));
2299 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2300 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2301 return -1;
2302 }
2303
2304 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2305 }
2306 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2307 regex_t *preg;
2308 if (curproxy == &defproxy) {
2309 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2310 return -1;
2311 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002312 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2313 return 0;
2314
Willy Tarreaubaaee002006-06-26 02:48:02 +02002315 if (*(args[1]) == 0) {
2316 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2317 return -1;
2318 }
2319
2320 preg = calloc(1, sizeof(regex_t));
2321 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2322 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2323 return -1;
2324 }
2325
2326 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2327 }
2328 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2329 regex_t *preg;
2330 if (curproxy == &defproxy) {
2331 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2332 return -1;
2333 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002334 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2335 return 0;
2336
Willy Tarreaubaaee002006-06-26 02:48:02 +02002337 if (*(args[1]) == 0) {
2338 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2339 return -1;
2340 }
2341
2342 preg = calloc(1, sizeof(regex_t));
2343 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2344 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2345 return -1;
2346 }
2347
2348 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2349 }
2350 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2351 regex_t *preg;
2352 if (curproxy == &defproxy) {
2353 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2354 return -1;
2355 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002356 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2357 return 0;
2358
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 if (*(args[1]) == 0) {
2360 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2361 return -1;
2362 }
2363
2364 preg = calloc(1, sizeof(regex_t));
2365 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2366 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2367 return -1;
2368 }
2369
2370 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2371 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002372 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2373 regex_t *preg;
2374 if (curproxy == &defproxy) {
2375 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2376 return -1;
2377 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002378 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2379 return 0;
2380
Willy Tarreaub8750a82006-09-03 09:56:00 +02002381 if (*(args[1]) == 0) {
2382 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2383 return -1;
2384 }
2385
2386 preg = calloc(1, sizeof(regex_t));
2387 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2388 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2389 return -1;
2390 }
2391
2392 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002394 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2395 if (curproxy == &defproxy) {
2396 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2397 return -1;
2398 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002399 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2400 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401
2402 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2403 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2404 return 0;
2405 }
2406
2407 if (*(args[1]) == 0) {
2408 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2409 return -1;
2410 }
2411
2412 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2413 }
2414 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2415 regex_t *preg;
2416
2417 if (*(args[1]) == 0 || *(args[2]) == 0) {
2418 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2419 file, linenum, args[0]);
2420 return -1;
2421 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002422 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2423 return 0;
2424
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 preg = calloc(1, sizeof(regex_t));
2426 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2427 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2428 return -1;
2429 }
2430
2431 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2432 if (err) {
2433 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2434 file, linenum, *err);
2435 return -1;
2436 }
2437 }
2438 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2439 regex_t *preg;
2440 if (curproxy == &defproxy) {
2441 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2442 return -1;
2443 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002444 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2445 return 0;
2446
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447 if (*(args[1]) == 0) {
2448 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2449 return -1;
2450 }
2451
2452 preg = calloc(1, sizeof(regex_t));
2453 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2454 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2455 return -1;
2456 }
2457
2458 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2459 if (err) {
2460 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2461 file, linenum, *err);
2462 return -1;
2463 }
2464 }
2465 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2466 regex_t *preg;
2467 if (curproxy == &defproxy) {
2468 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2469 return -1;
2470 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002471 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2472 return 0;
2473
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 if (*(args[1]) == 0) {
2475 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2476 return -1;
2477 }
2478
2479 preg = calloc(1, sizeof(regex_t));
2480 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2481 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2482 return -1;
2483 }
2484
2485 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2486 if (err) {
2487 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2488 file, linenum, *err);
2489 return -1;
2490 }
2491 }
2492 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2493 regex_t *preg;
2494 if (curproxy == &defproxy) {
2495 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2496 return -1;
2497 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002498 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2499 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500
2501 if (*(args[1]) == 0 || *(args[2]) == 0) {
2502 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2503 file, linenum, args[0]);
2504 return -1;
2505 }
2506
2507 preg = calloc(1, sizeof(regex_t));
2508 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2509 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2510 return -1;
2511 }
2512
2513 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2514 if (err) {
2515 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2516 file, linenum, *err);
2517 return -1;
2518 }
2519 }
2520 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2521 regex_t *preg;
2522 if (curproxy == &defproxy) {
2523 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2524 return -1;
2525 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002526 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2527 return 0;
2528
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 if (*(args[1]) == 0) {
2530 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2531 return -1;
2532 }
2533
2534 preg = calloc(1, sizeof(regex_t));
2535 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2536 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2537 return -1;
2538 }
2539
2540 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2541 if (err) {
2542 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2543 file, linenum, *err);
2544 return -1;
2545 }
2546 }
2547 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2548 regex_t *preg;
2549 if (curproxy == &defproxy) {
2550 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2551 return -1;
2552 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002553 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2554 return 0;
2555
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 if (*(args[1]) == 0) {
2557 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2558 return -1;
2559 }
2560
2561 preg = calloc(1, sizeof(regex_t));
2562 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2563 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2564 return -1;
2565 }
2566
2567 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2568 if (err) {
2569 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2570 file, linenum, *err);
2571 return -1;
2572 }
2573 }
2574 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2575 if (curproxy == &defproxy) {
2576 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2577 return -1;
2578 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002579 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2580 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581
2582 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2583 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2584 return 0;
2585 }
2586
2587 if (*(args[1]) == 0) {
2588 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2589 return -1;
2590 }
2591
2592 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2593 }
2594 else if (!strcmp(args[0], "errorloc") ||
2595 !strcmp(args[0], "errorloc302") ||
2596 !strcmp(args[0], "errorloc303")) { /* error location */
2597 int errnum, errlen;
2598 char *err;
2599
Willy Tarreau977b8e42006-12-29 14:19:17 +01002600 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2601 return 0;
2602
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002604 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 return -1;
2606 }
2607
2608 errnum = atol(args[1]);
2609 if (!strcmp(args[0], "errorloc303")) {
2610 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2611 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2612 } else {
2613 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2614 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2615 }
2616
Willy Tarreau0f772532006-12-23 20:51:41 +01002617 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2618 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002619 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002620 curproxy->errmsg[rc].str = err;
2621 curproxy->errmsg[rc].len = errlen;
2622 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002625
2626 if (rc >= HTTP_ERR_SIZE) {
2627 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2628 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629 free(err);
2630 }
2631 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002632 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2633 int errnum, errlen, fd;
2634 char *err;
2635 struct stat stat;
2636
2637 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2638 return 0;
2639
2640 if (*(args[2]) == 0) {
2641 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2642 return -1;
2643 }
2644
2645 fd = open(args[2], O_RDONLY);
2646 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2647 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2648 file, linenum, args[2], args[1]);
2649 if (fd >= 0)
2650 close(fd);
2651 return -1;
2652 }
2653
2654 if (stat.st_size <= BUFSIZE) {
2655 errlen = stat.st_size;
2656 } else {
2657 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2658 file, linenum, args[2], BUFSIZE);
2659 errlen = BUFSIZE;
2660 }
2661
2662 err = malloc(errlen); /* malloc() must succeed during parsing */
2663 errnum = read(fd, err, errlen);
2664 if (errnum != errlen) {
2665 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2666 file, linenum, args[2], args[1]);
2667 close(fd);
2668 free(err);
2669 return -1;
2670 }
2671 close(fd);
2672
2673 errnum = atol(args[1]);
2674 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2675 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002676 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002677 curproxy->errmsg[rc].str = err;
2678 curproxy->errmsg[rc].len = errlen;
2679 break;
2680 }
2681 }
2682
2683 if (rc >= HTTP_ERR_SIZE) {
2684 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2685 file, linenum, errnum);
2686 free(err);
2687 }
2688 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002690 struct cfg_kw_list *kwl;
2691 int index;
2692
2693 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2694 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2695 if (kwl->kw[index].section != CFG_LISTEN)
2696 continue;
2697 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2698 /* prepare error message just in case */
2699 snprintf(trash, sizeof(trash),
2700 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002701 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2702 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002703 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2704 return -1;
2705 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002706 else if (rc > 0) {
2707 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2708 return 0;
2709 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002710 return 0;
2711 }
2712 }
2713 }
2714
Willy Tarreau6daf3432008-01-22 16:44:08 +01002715 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716 return -1;
2717 }
2718 return 0;
2719}
2720
2721
2722/*
2723 * This function reads and parses the configuration file given in the argument.
2724 * returns 0 if OK, -1 if error.
2725 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002726int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002727{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002728 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 FILE *f;
2730 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 int confsect = CFG_NONE;
2733
2734 struct proxy *curproxy = NULL;
2735 struct server *newsrv = NULL;
2736
2737 if ((f=fopen(file,"r")) == NULL)
2738 return -1;
2739
2740 init_default_instance();
2741
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002742 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002743 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002744 char *end;
2745 char *args[MAX_LINE_ARGS + 1];
2746 char *line = thisline;
2747
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748 linenum++;
2749
2750 end = line + strlen(line);
2751
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002752 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2753 /* Check if we reached the limit and the last char is not \n.
2754 * Watch out for the last line without the terminating '\n'!
2755 */
2756 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2757 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002758 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002759 }
2760
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002762 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 line++;
2764
2765 arg = 0;
2766 args[arg] = line;
2767
2768 while (*line && arg < MAX_LINE_ARGS) {
2769 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2770 * C equivalent value. Other combinations left unchanged (eg: \1).
2771 */
2772 if (*line == '\\') {
2773 int skip = 0;
2774 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2775 *line = line[1];
2776 skip = 1;
2777 }
2778 else if (line[1] == 'r') {
2779 *line = '\r';
2780 skip = 1;
2781 }
2782 else if (line[1] == 'n') {
2783 *line = '\n';
2784 skip = 1;
2785 }
2786 else if (line[1] == 't') {
2787 *line = '\t';
2788 skip = 1;
2789 }
2790 else if (line[1] == 'x') {
2791 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2792 unsigned char hex1, hex2;
2793 hex1 = toupper(line[2]) - '0';
2794 hex2 = toupper(line[3]) - '0';
2795 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2796 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2797 *line = (hex1<<4) + hex2;
2798 skip = 3;
2799 }
2800 else {
2801 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002802 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002803 }
2804 }
2805 if (skip) {
2806 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2807 end -= skip;
2808 }
2809 line++;
2810 }
2811 else if (*line == '#' || *line == '\n' || *line == '\r') {
2812 /* end of string, end of loop */
2813 *line = 0;
2814 break;
2815 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002816 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002817 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002818 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002819 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002820 line++;
2821 args[++arg] = line;
2822 }
2823 else {
2824 line++;
2825 }
2826 }
2827
2828 /* empty line */
2829 if (!**args)
2830 continue;
2831
Willy Tarreau540abe42007-05-02 20:50:16 +02002832 /* zero out remaining args and ensure that at least one entry
2833 * is zeroed out.
2834 */
2835 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002836 args[arg] = line;
2837 }
2838
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002839 if (!strcmp(args[0], "no")) {
2840 inv = 1;
2841 for (arg=0; *args[arg+1]; arg++)
2842 args[arg] = args[arg+1]; // shift args after inversion
2843 }
2844
2845 if (inv && strcmp(args[0], "option")) {
2846 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002847 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002848 }
2849
Willy Tarreau977b8e42006-12-29 14:19:17 +01002850 if (!strcmp(args[0], "listen") ||
2851 !strcmp(args[0], "frontend") ||
2852 !strcmp(args[0], "backend") ||
2853 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002854 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002856 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002857 cursection = strdup(args[0]);
2858 }
2859 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002860 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002861 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002862 cursection = strdup(args[0]);
2863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864 /* else it's a section keyword */
2865
2866 switch (confsect) {
2867 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002868 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002869 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 break;
2871 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002872 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002873 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874 break;
2875 default:
2876 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002877 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002878 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002880 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002881 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882 fclose(f);
2883
2884 /*
2885 * Now, check for the integrity of all that we have collected.
2886 */
2887
2888 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002889 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890
2891 if ((curproxy = proxy) == NULL) {
2892 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2893 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002894 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002895 }
2896
2897 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002898 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002899 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002900
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02002902 /* ensure we don't keep listeners uselessly bound */
2903 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 curproxy = curproxy->next;
2905 continue;
2906 }
2907
Willy Tarreau977b8e42006-12-29 14:19:17 +01002908 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2909 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 +01002910 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002911 cfgerr++;
2912 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002913 else if (curproxy->cap & PR_CAP_BE &&
2914 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002915 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002916 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002917 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2918 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 +01002919 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002920 cfgerr++;
2921 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002922
Willy Tarreau31682232007-11-29 15:38:04 +01002923 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002924 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002925 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002926 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002927 cfgerr++;
2928 }
2929#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2930 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002931 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002932 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002933 cfgerr++;
2934 }
2935#endif
2936 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002937 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002938 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002939 }
2940 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002941
2942 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002943 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002944 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002945 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002948 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002949 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002950 }
2951 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002952 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002953 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002954 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002955 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002956 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002957 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002958 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002959 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002960 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2961 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002962
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002963 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002964 file, proxy_type_str(curproxy), curproxy->id);
2965 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002967
2968 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2969 if ((newsrv = curproxy->srv) != NULL) {
2970 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2971 file, proxy_type_str(curproxy), curproxy->id);
2972 }
2973 }
2974
2975 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002976 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2977 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2978 file, curproxy->id);
2979 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002980 }
2981 }
2982
Willy Tarreau82936582007-11-30 15:20:09 +01002983 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2984 curproxy->options &= ~PR_O_DISABLE404;
2985 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2986 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2987 }
2988
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002989 /* if a default backend was specified, let's find it */
2990 if (curproxy->defbe.name) {
2991 struct proxy *target;
2992
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002993 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2994 if (!target) {
2995 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2996 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002997 cfgerr++;
2998 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002999 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3000 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003001 } else {
3002 free(curproxy->defbe.name);
3003 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 }
3005 }
3006
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003007 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003008 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3009 /* map jump target for ACT_SETBE in req_rep chain */
3010 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003011 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003012 struct proxy *target;
3013
Willy Tarreaua496b602006-12-17 23:15:24 +01003014 if (exp->action != ACT_SETBE)
3015 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003016
3017 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3018 if (!target) {
3019 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3020 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003021 cfgerr++;
3022 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003023 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3024 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003025 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003026 } else {
3027 free((void *)exp->replace);
3028 exp->replace = (const char *)target;
3029 }
3030 }
3031 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003032
3033 /* find the target proxy for 'use_backend' rules */
3034 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003035 struct proxy *target;
3036
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003037 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003038
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003039 if (!target) {
3040 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3041 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003042 cfgerr++;
3043 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003044 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3045 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003046 cfgerr++;
3047 } else {
3048 free((void *)rule->be.name);
3049 rule->be.backend = target;
3050 }
3051 }
3052
Willy Tarreau2738a142006-07-08 17:28:09 +02003053 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003054 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003055 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003056 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003057 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003058 " | While not properly invalid, you will certainly encounter various problems\n"
3059 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003060 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003061 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003062 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003063
Willy Tarreau1fa31262007-12-03 00:36:16 +01003064 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3065 * We must still support older configurations, so let's find out whether those
3066 * parameters have been set or must be copied from contimeouts.
3067 */
3068 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003069 if (!curproxy->timeout.tarpit ||
3070 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003071 /* tarpit timeout not set. We search in the following order:
3072 * default.tarpit, curr.connect, default.connect.
3073 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003074 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003075 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003076 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003077 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003078 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003079 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003080 }
3081 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003082 (!curproxy->timeout.queue ||
3083 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003084 /* queue timeout not set. We search in the following order:
3085 * default.queue, curr.connect, default.connect.
3086 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003087 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003088 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003089 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003090 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003091 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003092 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003093 }
3094 }
3095
Willy Tarreauf3c69202006-07-09 16:42:34 +02003096 if (curproxy->options & PR_O_SSL3_CHK) {
3097 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3098 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3099 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3100 }
3101
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003102 /* The small pools required for the capture lists */
3103 if (curproxy->nb_req_cap)
3104 curproxy->req_cap_pool = create_pool("ptrcap",
3105 curproxy->nb_req_cap * sizeof(char *),
3106 MEM_F_SHARED);
3107 if (curproxy->nb_rsp_cap)
3108 curproxy->rsp_cap_pool = create_pool("ptrcap",
3109 curproxy->nb_rsp_cap * sizeof(char *),
3110 MEM_F_SHARED);
3111
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003112 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3113 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3114 MEM_F_SHARED);
3115
Willy Tarreau86034312006-12-29 00:10:33 +01003116 /* for backwards compatibility with "listen" instances, if
3117 * fullconn is not set but maxconn is set, then maxconn
3118 * is used.
3119 */
3120 if (!curproxy->fullconn)
3121 curproxy->fullconn = curproxy->maxconn;
3122
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 /* first, we will invert the servers list order */
3124 newsrv = NULL;
3125 while (curproxy->srv) {
3126 struct server *next;
3127
3128 next = curproxy->srv->next;
3129 curproxy->srv->next = newsrv;
3130 newsrv = curproxy->srv;
3131 if (!next)
3132 break;
3133 curproxy->srv = next;
3134 }
3135
Willy Tarreau20697042007-11-15 23:26:18 +01003136 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003137 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138
Willy Tarreaub625a082007-11-26 01:15:43 +01003139 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003140 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003141 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003142 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3143 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003144 else
3145 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003146
3147 if (curproxy->options & PR_O_LOGASAP)
3148 curproxy->to_log &= ~LW_BYTES;
3149
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003151 * ensure that we're not cross-dressing a TCP server into HTTP.
3152 */
3153 newsrv = curproxy->srv;
3154 while (newsrv != NULL) {
3155 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3156 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3157 file, proxy_type_str(curproxy), curproxy->id, linenum);
3158 goto err;
3159 }
3160 newsrv = newsrv->next;
3161 }
3162
3163 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 * If this server supports a maxconn parameter, it needs a dedicated
3165 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003166 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 */
3168 newsrv = curproxy->srv;
3169 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003170 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003171 /* Only 'minconn' was specified, or it was higher than or equal
3172 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3173 * this will avoid further useless expensive computations.
3174 */
3175 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003176 } else if (newsrv->maxconn && !newsrv->minconn) {
3177 /* minconn was not specified, so we set it to maxconn */
3178 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003179 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3180 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003181 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003182 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 }
3184
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003185 if (newsrv->trackit) {
3186 struct proxy *px;
3187 struct server *srv;
3188 char *pname, *sname;
3189
3190 pname = newsrv->trackit;
3191 sname = strrchr(pname, '/');
3192
3193 if (sname)
3194 *sname++ = '\0';
3195 else {
3196 sname = pname;
3197 pname = NULL;
3198 }
3199
3200 if (pname) {
3201 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3202 if (!px) {
3203 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3204 file, proxy_type_str(curproxy), curproxy->id,
3205 newsrv->id, pname);
3206 return -1;
3207 }
3208 } else
3209 px = curproxy;
3210
3211 srv = findserver(px, sname);
3212 if (!srv) {
3213 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3214 file, proxy_type_str(curproxy), curproxy->id,
3215 newsrv->id, sname);
3216 return -1;
3217 }
3218
3219 if (!(srv->state & SRV_CHECKED)) {
3220 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3221 "tracing as it does not have checks enabled.\n",
3222 file, proxy_type_str(curproxy), curproxy->id,
3223 newsrv->id, px->id, srv->id);
3224 return -1;
3225 }
3226
3227 if (curproxy != px &&
3228 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3229 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3230 "tracing: disable-on-404 option inconsistency.\n",
3231 file, proxy_type_str(curproxy), curproxy->id,
3232 newsrv->id, px->id, srv->id);
3233 return -1;
3234 }
3235
3236 newsrv->tracked = srv;
3237 newsrv->tracknext = srv->tracknext;
3238 srv->tracknext = newsrv;
3239
3240 free(newsrv->trackit);
3241 }
3242
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 newsrv = newsrv->next;
3244 }
3245
Willy Tarreaue6b98942007-10-29 01:09:36 +01003246 /* adjust this proxy's listeners */
3247 listener = curproxy->listen;
3248 while (listener) {
3249 if (curproxy->options & PR_O_TCP_NOLING)
3250 listener->options |= LI_O_NOLINGER;
3251 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003252 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003253 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003254 listener->accept = event_accept;
3255 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003256 listener->handler = process_session;
3257
3258 if (curproxy->mode == PR_MODE_HTTP)
3259 listener->analysers |= AN_REQ_HTTP_HDR;
3260
3261 if (curproxy->tcp_req.inspect_delay)
3262 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003263
3264 listener = listener->next;
3265 }
3266
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 curproxy = curproxy->next;
3268 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003269
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 if (cfgerr > 0) {
3271 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003272 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003274
3275 /*
3276 * Recount currently required checks.
3277 */
3278
3279 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3280 int optnum;
3281
3282 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3283 if (!(curproxy->options & cfg_opts[optnum].val))
3284 continue;
3285
3286 global.last_checks |= cfg_opts[optnum].checks;
3287 }
3288 }
3289
Willy Tarreaua534fea2008-08-03 12:19:50 +02003290 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003291 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003292 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003293
3294 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003295 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003296 cursection = NULL;
3297 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298}
3299
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003300/*
3301 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3302 * parsing sessions.
3303 */
3304void cfg_register_keywords(struct cfg_kw_list *kwl)
3305{
3306 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3307}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003309/*
3310 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3311 */
3312void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3313{
3314 LIST_DEL(&kwl->list);
3315 LIST_INIT(&kwl->list);
3316}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003317
3318/*
3319 * Local variables:
3320 * c-indent-level: 8
3321 * c-basic-offset: 8
3322 * End:
3323 */