blob: a5f49acb8355fa1c146e7d4d714e6ce4eecc6fff [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;
1121
1122 cur_arg = 1;
1123 while (*(args[cur_arg])) {
1124 if (!strcmp(args[cur_arg], "location")) {
1125 if (!*args[cur_arg + 1]) {
1126 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1127 file, linenum, args[0], args[cur_arg]);
1128 return -1;
1129 }
1130
1131 type = REDIRECT_TYPE_LOCATION;
1132 cur_arg++;
1133 destination = args[cur_arg];
1134 }
1135 else if (!strcmp(args[cur_arg], "prefix")) {
1136 if (!*args[cur_arg + 1]) {
1137 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1138 file, linenum, args[0], args[cur_arg]);
1139 return -1;
1140 }
1141
1142 type = REDIRECT_TYPE_PREFIX;
1143 cur_arg++;
1144 destination = args[cur_arg];
1145 }
1146 else if (!strcmp(args[cur_arg],"code")) {
1147 if (!*args[cur_arg + 1]) {
1148 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1149 file, linenum, args[0]);
1150 return -1;
1151 }
1152 cur_arg++;
1153 code = atol(args[cur_arg]);
1154 if (code < 301 || code > 303) {
1155 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1156 file, linenum, args[0], code);
1157 return -1;
1158 }
1159 }
1160 else if (!strcmp(args[cur_arg], "if")) {
1161 pol = ACL_COND_IF;
1162 cur_arg++;
1163 break;
1164 }
1165 else if (!strcmp(args[cur_arg], "unless")) {
1166 pol = ACL_COND_UNLESS;
1167 cur_arg++;
1168 break;
1169 }
1170 else {
1171 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1172 file, linenum, args[0], args[cur_arg]);
1173 return -1;
1174 }
1175 cur_arg++;
1176 }
1177
1178 if (type == REDIRECT_TYPE_NONE) {
1179 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1180 file, linenum, args[0]);
1181 return -1;
1182 }
1183
1184 if (pol == ACL_COND_NONE) {
1185 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1186 file, linenum, args[0]);
1187 return -1;
1188 }
1189
1190 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1191 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1192 file, linenum, args[0]);
1193 return -1;
1194 }
1195
Willy Tarreaua9802632008-07-25 19:13:19 +02001196 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001197 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1198 rule->cond = cond;
1199 rule->rdr_str = strdup(destination);
1200 rule->rdr_len = strlen(destination);
1201 rule->type = type;
1202 rule->code = code;
1203 LIST_INIT(&rule->list);
1204 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1205 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001206 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1207 int pol = ACL_COND_NONE;
1208 struct acl_cond *cond;
1209 struct switching_rule *rule;
1210
Willy Tarreaub099aca2008-10-12 17:26:37 +02001211 if (curproxy == &defproxy) {
1212 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1213 return -1;
1214 }
1215
Willy Tarreau55ea7572007-06-17 19:56:27 +02001216 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1217 return 0;
1218
1219 if (*(args[1]) == 0) {
1220 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1221 return -1;
1222 }
1223
1224 if (!strcmp(args[2], "if"))
1225 pol = ACL_COND_IF;
1226 else if (!strcmp(args[2], "unless"))
1227 pol = ACL_COND_UNLESS;
1228
1229 if (pol == ACL_COND_NONE) {
1230 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1231 file, linenum, args[0]);
1232 return -1;
1233 }
1234
1235 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001236 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001237 file, linenum);
1238 return -1;
1239 }
1240
Willy Tarreaua9802632008-07-25 19:13:19 +02001241 cond->line = linenum;
1242 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001243 struct acl *acl;
1244 const char *name;
1245
1246 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1247 name = acl ? acl->name : "(unknown)";
1248 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1249 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001250 }
1251
Willy Tarreau55ea7572007-06-17 19:56:27 +02001252 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1253 rule->cond = cond;
1254 rule->be.name = strdup(args[1]);
1255 LIST_INIT(&rule->list);
1256 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001259 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1260 return 0;
1261
Willy Tarreaubaaee002006-06-26 02:48:02 +02001262 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1263 curproxy->uri_auth = NULL; /* we must detach from the default config */
1264
1265 if (*(args[1]) == 0) {
1266 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1267 return -1;
1268 } else if (!strcmp(args[1], "uri")) {
1269 if (*(args[2]) == 0) {
1270 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1271 return -1;
1272 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1273 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1274 return -1;
1275 }
1276 } else if (!strcmp(args[1], "realm")) {
1277 if (*(args[2]) == 0) {
1278 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1279 return -1;
1280 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1281 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1282 return -1;
1283 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001284 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001285 unsigned interval;
1286
1287 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1288 if (err) {
1289 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1290 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001291 return -1;
1292 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1293 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1294 return -1;
1295 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001296 } else if (!strcmp(args[1], "auth")) {
1297 if (*(args[2]) == 0) {
1298 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1299 return -1;
1300 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1301 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1302 return -1;
1303 }
1304 } else if (!strcmp(args[1], "scope")) {
1305 if (*(args[2]) == 0) {
1306 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1307 return -1;
1308 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1309 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1310 return -1;
1311 }
1312 } else if (!strcmp(args[1], "enable")) {
1313 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1314 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1315 return -1;
1316 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001317 } else if (!strcmp(args[1], "hide-version")) {
1318 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1319 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1320 return -1;
1321 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001322 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001323 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001324 file, linenum, args[0]);
1325 return -1;
1326 }
1327 }
1328 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001329 int optnum;
1330
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001331 if (*(args[1]) == '\0') {
1332 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1333 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001334 return -1;
1335 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001336
1337 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1338 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1339 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1340 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001341
1342 if (!inv)
1343 curproxy->options |= cfg_opts[optnum].val;
1344 else
1345 curproxy->options &= ~cfg_opts[optnum].val;
1346
Willy Tarreau13943ab2006-12-31 00:24:10 +01001347 return 0;
1348 }
1349 }
1350
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001351 if (inv) {
1352 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1353 file, linenum, args[1]);
1354 return -1;
1355 }
1356
Willy Tarreau13943ab2006-12-31 00:24:10 +01001357 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 /* generate a complete HTTP log */
1359 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1360 else if (!strcmp(args[1], "tcplog"))
1361 /* generate a detailed TCP log */
1362 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363 else if (!strcmp(args[1], "tcpka")) {
1364 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001365 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1366 return 0;
1367
1368 if (curproxy->cap & PR_CAP_FE)
1369 curproxy->options |= PR_O_TCP_CLI_KA;
1370 if (curproxy->cap & PR_CAP_BE)
1371 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001372 }
1373 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001374 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1375 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001377 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001378 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001379 curproxy->options &= ~PR_O_SMTP_CHK;
1380 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001381 if (!*args[2]) { /* no argument */
1382 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1383 curproxy->check_len = strlen(DEF_CHECK_REQ);
1384 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001385 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001386 curproxy->check_req = (char *)malloc(reqlen);
1387 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1388 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1389 } else { /* more arguments : METHOD URI [HTTP_VER] */
1390 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1391 if (*args[4])
1392 reqlen += strlen(args[4]);
1393 else
1394 reqlen += strlen("HTTP/1.0");
1395
1396 curproxy->check_req = (char *)malloc(reqlen);
1397 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1398 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1399 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001400 }
1401 else if (!strcmp(args[1], "ssl-hello-chk")) {
1402 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001403 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1404 return 0;
1405
Willy Tarreaua534fea2008-08-03 12:19:50 +02001406 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001407 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001408 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001409 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410 }
Willy Tarreau23677902007-05-08 23:50:35 +02001411 else if (!strcmp(args[1], "smtpchk")) {
1412 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001413 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001414 curproxy->options &= ~PR_O_HTTP_CHK;
1415 curproxy->options &= ~PR_O_SSL3_CHK;
1416 curproxy->options |= PR_O_SMTP_CHK;
1417
1418 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1419 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1420 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1421 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1422 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1423 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1424 curproxy->check_req = (char *)malloc(reqlen);
1425 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1426 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1427 } else {
1428 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1429 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1430 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1431 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1432 }
1433 }
1434 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001435 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001436 int cur_arg;
1437
1438 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1439 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001440 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001441
1442 curproxy->options |= PR_O_FWDFOR;
1443
1444 free(curproxy->fwdfor_hdr_name);
1445 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1446 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1447
1448 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1449 cur_arg = 2;
1450 while (*(args[cur_arg])) {
1451 if (!strcmp(args[cur_arg], "except")) {
1452 /* suboption except - needs additional argument for it */
1453 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1454 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1455 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001456 return -1;
1457 }
1458 /* flush useless bits */
1459 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001460 cur_arg += 2;
1461 } else if (!strcmp(args[cur_arg], "header")) {
1462 /* suboption header - needs additional argument for it */
1463 if (*(args[cur_arg+1]) == 0) {
1464 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1465 file, linenum, args[0], args[1], args[cur_arg]);
1466 return -1;
1467 }
1468 free(curproxy->fwdfor_hdr_name);
1469 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1470 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1471 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001472 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001473 /* unknown suboption - catchall */
1474 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1475 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001476 return -1;
1477 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001478 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001480 else {
1481 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1482 return -1;
1483 }
1484 return 0;
1485 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001486 else if (!strcmp(args[0], "default_backend")) {
1487 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1488 return 0;
1489
1490 if (*(args[1]) == 0) {
1491 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1492 return -1;
1493 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001494 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001495 curproxy->defbe.name = strdup(args[1]);
1496 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001497 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001498 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1499 return 0;
1500
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001501 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1502 file, linenum, args[0]);
1503
Willy Tarreaubaaee002006-06-26 02:48:02 +02001504 /* enable reconnections to dispatch */
1505 curproxy->options |= PR_O_REDISP;
1506 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001507 else if (!strcmp(args[0], "http-check")) {
1508 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1509 return 0;
1510
1511 if (strcmp(args[1], "disable-on-404") == 0) {
1512 /* enable a graceful server shutdown on an HTTP 404 response */
1513 curproxy->options |= PR_O_DISABLE404;
1514 }
1515 else {
1516 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1517 return -1;
1518 }
1519 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001520 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001521 if (curproxy == &defproxy) {
1522 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1523 return -1;
1524 }
1525
Willy Tarreaub80c2302007-11-30 20:51:32 +01001526 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1527 return 0;
1528
1529 if (strcmp(args[1], "fail") == 0) {
1530 /* add a condition to fail monitor requests */
1531 int pol = ACL_COND_NONE;
1532 struct acl_cond *cond;
1533
1534 if (!strcmp(args[2], "if"))
1535 pol = ACL_COND_IF;
1536 else if (!strcmp(args[2], "unless"))
1537 pol = ACL_COND_UNLESS;
1538
1539 if (pol == ACL_COND_NONE) {
1540 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1541 file, linenum, args[0], args[1]);
1542 return -1;
1543 }
1544
1545 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1546 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1547 file, linenum, args[0], args[1]);
1548 return -1;
1549 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001550 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001551 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1552 }
1553 else {
1554 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1555 return -1;
1556 }
1557 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558#ifdef TPROXY
1559 else if (!strcmp(args[0], "transparent")) {
1560 /* enable transparent proxy connections */
1561 curproxy->options |= PR_O_TRANSP;
1562 }
1563#endif
1564 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001565 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1566 return 0;
1567
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 if (*(args[1]) == 0) {
1569 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1570 return -1;
1571 }
1572 curproxy->maxconn = atol(args[1]);
1573 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001574 else if (!strcmp(args[0], "backlog")) { /* backlog */
1575 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1576 return 0;
1577
1578 if (*(args[1]) == 0) {
1579 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1580 return -1;
1581 }
1582 curproxy->backlog = atol(args[1]);
1583 }
Willy Tarreau86034312006-12-29 00:10:33 +01001584 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001585 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1586 return 0;
1587
Willy Tarreau86034312006-12-29 00:10:33 +01001588 if (*(args[1]) == 0) {
1589 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1590 return -1;
1591 }
1592 curproxy->fullconn = atol(args[1]);
1593 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1595 if (*(args[1]) == 0) {
1596 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1597 return -1;
1598 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001599 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1600 if (err) {
1601 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1602 file, linenum, *err);
1603 return -1;
1604 }
1605 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001606 }
1607 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1608 if (curproxy == &defproxy) {
1609 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1610 return -1;
1611 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001612 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1613 return 0;
1614
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615 if (strchr(args[1], ':') == NULL) {
1616 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1617 return -1;
1618 }
1619 curproxy->dispatch_addr = *str2sa(args[1]);
1620 }
1621 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001622 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1623 return 0;
1624
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001625 memcpy(trash, "error near 'balance'", 19);
1626 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1627 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1628 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630 }
1631 else if (!strcmp(args[0], "server")) { /* server address */
1632 int cur_arg;
1633 char *rport;
1634 char *raddr;
1635 short realport;
1636 int do_check;
1637
1638 if (curproxy == &defproxy) {
1639 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1640 return -1;
1641 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001642 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1643 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644
1645 if (!*args[2]) {
1646 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1647 file, linenum, args[0]);
1648 return -1;
1649 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001650
1651 err = invalid_char(args[1]);
1652 if (err) {
1653 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1654 file, linenum, *err, args[1]);
1655 return -1;
1656 }
1657
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1659 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1660 return -1;
1661 }
1662
1663 /* the servers are linked backwards first */
1664 newsrv->next = curproxy->srv;
1665 curproxy->srv = newsrv;
1666 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001667 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001668
1669 LIST_INIT(&newsrv->pendconns);
1670 do_check = 0;
1671 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001672 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 newsrv->id = strdup(args[1]);
1674
1675 /* several ways to check the port component :
1676 * - IP => port=+0, relative
1677 * - IP: => port=+0, relative
1678 * - IP:N => port=N, absolute
1679 * - IP:+N => port=+N, relative
1680 * - IP:-N => port=-N, relative
1681 */
1682 raddr = strdup(args[2]);
1683 rport = strchr(raddr, ':');
1684 if (rport) {
1685 *rport++ = 0;
1686 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001687 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688 newsrv->state |= SRV_MAPPORTS;
1689 } else {
1690 realport = 0;
1691 newsrv->state |= SRV_MAPPORTS;
1692 }
1693
1694 newsrv->addr = *str2sa(raddr);
1695 newsrv->addr.sin_port = htons(realport);
1696 free(raddr);
1697
1698 newsrv->curfd = -1; /* no health-check in progress */
1699 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001700 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1701 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001702 newsrv->rise = DEF_RISETIME;
1703 newsrv->fall = DEF_FALLTIME;
1704 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001705 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001706 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001707 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001708
Willy Tarreaubaaee002006-06-26 02:48:02 +02001709 cur_arg = 3;
1710 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001711 if (!strcmp(args[cur_arg], "id")) {
1712 struct server *target;
1713
1714 if (!*args[cur_arg + 1]) {
1715 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1716 file, linenum, args[cur_arg]);
1717 return -1;
1718 }
1719
1720 newsrv->puid = atol(args[cur_arg + 1]);
1721
1722 if (newsrv->puid< 1001) {
1723 Alert("parsing [%s:%d]: custom id has to be > 1000",
1724 file, linenum);
1725 return -1;
1726 }
1727
1728 for (target = proxy->srv; target; target = target->next)
1729 if (newsrv != target && newsrv->puid == target->puid) {
1730 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1731 file, linenum, newsrv->id, target->id);
1732 return -1;
1733 }
1734 cur_arg += 2;
1735 }
1736 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001737 newsrv->cookie = strdup(args[cur_arg + 1]);
1738 newsrv->cklen = strlen(args[cur_arg + 1]);
1739 cur_arg += 2;
1740 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001741 else if (!strcmp(args[cur_arg], "redir")) {
1742 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1743 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1744 cur_arg += 2;
1745 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746 else if (!strcmp(args[cur_arg], "rise")) {
1747 newsrv->rise = atol(args[cur_arg + 1]);
1748 newsrv->health = newsrv->rise;
1749 cur_arg += 2;
1750 }
1751 else if (!strcmp(args[cur_arg], "fall")) {
1752 newsrv->fall = atol(args[cur_arg + 1]);
1753 cur_arg += 2;
1754 }
1755 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001756 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1757 if (err) {
1758 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1759 file, linenum, *err, newsrv->id);
1760 return -1;
1761 }
1762 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763 cur_arg += 2;
1764 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001765 else if (!strcmp(args[cur_arg], "fastinter")) {
1766 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1767 if (err) {
1768 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1769 file, linenum, *err, newsrv->id);
1770 return -1;
1771 }
1772 newsrv->fastinter = val;
1773 cur_arg += 2;
1774 }
1775 else if (!strcmp(args[cur_arg], "downinter")) {
1776 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1777 if (err) {
1778 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1779 file, linenum, *err, newsrv->id);
1780 return -1;
1781 }
1782 newsrv->downinter = val;
1783 cur_arg += 2;
1784 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001785 else if (!strcmp(args[cur_arg], "addr")) {
1786 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001787 cur_arg += 2;
1788 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001789 else if (!strcmp(args[cur_arg], "port")) {
1790 newsrv->check_port = atol(args[cur_arg + 1]);
1791 cur_arg += 2;
1792 }
1793 else if (!strcmp(args[cur_arg], "backup")) {
1794 newsrv->state |= SRV_BACKUP;
1795 cur_arg ++;
1796 }
1797 else if (!strcmp(args[cur_arg], "weight")) {
1798 int w;
1799 w = atol(args[cur_arg + 1]);
1800 if (w < 1 || w > 256) {
1801 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1802 file, linenum, newsrv->id, w);
1803 return -1;
1804 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001805 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001806 cur_arg += 2;
1807 }
1808 else if (!strcmp(args[cur_arg], "minconn")) {
1809 newsrv->minconn = atol(args[cur_arg + 1]);
1810 cur_arg += 2;
1811 }
1812 else if (!strcmp(args[cur_arg], "maxconn")) {
1813 newsrv->maxconn = atol(args[cur_arg + 1]);
1814 cur_arg += 2;
1815 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001816 else if (!strcmp(args[cur_arg], "maxqueue")) {
1817 newsrv->maxqueue = atol(args[cur_arg + 1]);
1818 cur_arg += 2;
1819 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001820 else if (!strcmp(args[cur_arg], "slowstart")) {
1821 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001822 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001823 if (err) {
1824 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1825 file, linenum, *err, newsrv->id);
1826 return -1;
1827 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001828 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001829 cur_arg += 2;
1830 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001831 else if (!strcmp(args[cur_arg], "track")) {
1832
1833 if (!*args[cur_arg + 1]) {
1834 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1835 file, linenum);
1836 return -1;
1837 }
1838
1839 newsrv->trackit = strdup(args[cur_arg + 1]);
1840
1841 cur_arg += 2;
1842 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001843 else if (!strcmp(args[cur_arg], "check")) {
1844 global.maxsock++;
1845 do_check = 1;
1846 cur_arg += 1;
1847 }
1848 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1849 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001850#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001851 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1852 file, linenum, "source", "usesrc");
1853#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001854 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1855 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001856#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857 return -1;
1858 }
1859 newsrv->state |= SRV_BIND_SRC;
1860 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1861 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001862 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001863#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1864#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001865 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001866 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1867 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001868 return -1;
1869 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001870#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001871 if (!*args[cur_arg + 1]) {
1872 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1873 file, linenum, "usesrc");
1874 return -1;
1875 }
1876 if (!strcmp(args[cur_arg + 1], "client")) {
1877 newsrv->state |= SRV_TPROXY_CLI;
1878 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1879 newsrv->state |= SRV_TPROXY_CIP;
1880 } else {
1881 newsrv->state |= SRV_TPROXY_ADDR;
1882 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1883 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001884 global.last_checks |= LSTCHK_NETADM;
1885#if !defined(CONFIG_HAP_LINUX_TPROXY)
1886 global.last_checks |= LSTCHK_CTTPROXY;
1887#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001888 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001889#else /* no TPROXY support */
1890 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001891 file, linenum, "usesrc");
1892 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001893#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001894 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001895 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001896 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1897 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1898 file, linenum, "usesrc", "source");
1899 return -1;
1900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001902 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 +02001903 file, linenum, newsrv->id);
1904 return -1;
1905 }
1906 }
1907
1908 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001909 if (newsrv->trackit) {
1910 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1911 file, linenum);
1912 return -1;
1913 }
1914
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001915 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1916 newsrv->check_port = newsrv->check_addr.sin_port;
1917
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1919 newsrv->check_port = realport; /* by default */
1920 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001921 /* not yet valid, because no port was set on
1922 * the server either. We'll check if we have
1923 * a known port on the first listener.
1924 */
1925 struct listener *l;
1926 l = curproxy->listen;
1927 if (l) {
1928 int port;
1929 port = (l->addr.ss_family == AF_INET6)
1930 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1931 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1932 newsrv->check_port = port;
1933 }
1934 }
1935 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1937 file, linenum, newsrv->id);
1938 return -1;
1939 }
1940 newsrv->state |= SRV_CHECKED;
1941 }
1942
1943 if (newsrv->state & SRV_BACKUP)
1944 curproxy->srv_bck++;
1945 else
1946 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001947
1948 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001949 }
1950 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001951 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001952 int facility;
1953
1954 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1955 curproxy->logfac1 = global.logfac1;
1956 curproxy->logsrv1 = global.logsrv1;
1957 curproxy->loglev1 = global.loglev1;
1958 curproxy->logfac2 = global.logfac2;
1959 curproxy->logsrv2 = global.logsrv2;
1960 curproxy->loglev2 = global.loglev2;
1961 }
1962 else if (*(args[1]) && *(args[2])) {
1963 int level;
1964
1965 facility = get_log_facility(args[2]);
1966 if (facility < 0) {
1967 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1968 exit(1);
1969 }
1970
1971 level = 7; /* max syslog level = debug */
1972 if (*(args[3])) {
1973 level = get_log_level(args[3]);
1974 if (level < 0) {
1975 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1976 exit(1);
1977 }
1978 }
1979
Robert Tsai81ae1952007-12-05 10:47:29 +01001980 if (args[1][0] == '/') {
1981 logsrv.u.addr.sa_family = AF_UNIX;
1982 logsrv.u.un = *str2sun(args[1]);
1983 } else {
1984 logsrv.u.addr.sa_family = AF_INET;
1985 logsrv.u.in = *str2sa(args[1]);
1986 if (!logsrv.u.in.sin_port) {
1987 logsrv.u.in.sin_port =
1988 htons(SYSLOG_PORT);
1989 }
1990 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991
1992 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001993 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994 curproxy->logfac1 = facility;
1995 curproxy->loglev1 = level;
1996 }
1997 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001998 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001999 curproxy->logfac2 = facility;
2000 curproxy->loglev2 = level;
2001 }
2002 else {
2003 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2004 return -1;
2005 }
2006 }
2007 else {
2008 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2009 file, linenum);
2010 return -1;
2011 }
2012 }
2013 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002014 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2015 return 0;
2016
Willy Tarreaubaaee002006-06-26 02:48:02 +02002017 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002018#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002019 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2020 file, linenum, "source", "usesrc");
2021#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002022 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2023 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002024#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002025 return -1;
2026 }
2027
2028 curproxy->source_addr = *str2sa(args[1]);
2029 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01002030 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002031#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2032#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002033 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2034 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2035 file, linenum, "usesrc");
2036 return -1;
2037 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002038#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002039 if (!*args[3]) {
2040 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2041 file, linenum, "usesrc");
2042 return -1;
2043 }
2044
2045 if (!strcmp(args[3], "client")) {
2046 curproxy->options |= PR_O_TPXY_CLI;
2047 } else if (!strcmp(args[3], "clientip")) {
2048 curproxy->options |= PR_O_TPXY_CIP;
2049 } else {
2050 curproxy->options |= PR_O_TPXY_ADDR;
2051 curproxy->tproxy_addr = *str2sa(args[3]);
2052 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002053 global.last_checks |= LSTCHK_NETADM;
2054#if !defined(CONFIG_HAP_LINUX_TPROXY)
2055 global.last_checks |= LSTCHK_CTTPROXY;
2056#endif
2057#else /* no TPROXY support */
2058 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002059 file, linenum, "usesrc");
2060 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002061#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002062 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002064 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2065 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2066 file, linenum, "usesrc", "source");
2067 return -1;
2068 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002069 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2070 regex_t *preg;
2071 if (curproxy == &defproxy) {
2072 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2073 return -1;
2074 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002075 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2076 return 0;
2077
Willy Tarreaubaaee002006-06-26 02:48:02 +02002078 if (*(args[1]) == 0 || *(args[2]) == 0) {
2079 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2080 file, linenum, args[0]);
2081 return -1;
2082 }
2083
2084 preg = calloc(1, sizeof(regex_t));
2085 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2086 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2087 return -1;
2088 }
2089
2090 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2091 if (err) {
2092 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2093 file, linenum, *err);
2094 return -1;
2095 }
2096 }
2097 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2098 regex_t *preg;
2099 if (curproxy == &defproxy) {
2100 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2101 return -1;
2102 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002103 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2104 return 0;
2105
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 if (*(args[1]) == 0) {
2107 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2108 return -1;
2109 }
2110
2111 preg = calloc(1, sizeof(regex_t));
2112 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2113 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2114 return -1;
2115 }
2116
2117 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2118 }
2119 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2120 regex_t *preg;
2121 if (curproxy == &defproxy) {
2122 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2123 return -1;
2124 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002125 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2126 return 0;
2127
Willy Tarreaubaaee002006-06-26 02:48:02 +02002128 if (*(args[1]) == 0) {
2129 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2130 return -1;
2131 }
2132
2133 preg = calloc(1, sizeof(regex_t));
2134 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2135 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2136 return -1;
2137 }
2138
2139 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2140 }
2141 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2142 regex_t *preg;
2143 if (curproxy == &defproxy) {
2144 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2145 return -1;
2146 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002147 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2148 return 0;
2149
Willy Tarreaubaaee002006-06-26 02:48:02 +02002150 if (*(args[1]) == 0) {
2151 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2152 return -1;
2153 }
2154
2155 preg = calloc(1, sizeof(regex_t));
2156 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2157 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2158 return -1;
2159 }
2160
2161 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2162 }
2163 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2164 regex_t *preg;
2165 if (curproxy == &defproxy) {
2166 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2167 return -1;
2168 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002169 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2170 return 0;
2171
Willy Tarreaubaaee002006-06-26 02:48:02 +02002172 if (*(args[1]) == 0) {
2173 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2174 return -1;
2175 }
2176
2177 preg = calloc(1, sizeof(regex_t));
2178 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2179 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2180 return -1;
2181 }
2182
2183 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2184 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002185 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2186 regex_t *preg;
2187 if (curproxy == &defproxy) {
2188 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2189 return -1;
2190 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002191 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2192 return 0;
2193
Willy Tarreaub8750a82006-09-03 09:56:00 +02002194 if (*(args[1]) == 0) {
2195 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2196 return -1;
2197 }
2198
2199 preg = calloc(1, sizeof(regex_t));
2200 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2201 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2202 return -1;
2203 }
2204
2205 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2206 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002207 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2208 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002209 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002210 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2211 return -1;
2212 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002213 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2214 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002215
Willy Tarreau977b8e42006-12-29 14:19:17 +01002216 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002217 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2218 file, linenum, args[0]);
2219 return -1;
2220 }
2221
2222 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002223 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002224 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2225 }
2226
2227 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2228 }
2229 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2230 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002231 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002232 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2233 return -1;
2234 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002235 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2236 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002237
Willy Tarreau977b8e42006-12-29 14:19:17 +01002238 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002239 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2240 file, linenum, args[0]);
2241 return -1;
2242 }
2243
2244 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002245 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002246 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2247 }
2248
2249 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2252 regex_t *preg;
2253 if (curproxy == &defproxy) {
2254 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2255 return -1;
2256 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002257 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2258 return 0;
2259
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 if (*(args[1]) == 0 || *(args[2]) == 0) {
2261 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2262 file, linenum, args[0]);
2263 return -1;
2264 }
2265
2266 preg = calloc(1, sizeof(regex_t));
2267 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2268 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2269 return -1;
2270 }
2271
2272 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2273 if (err) {
2274 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2275 file, linenum, *err);
2276 return -1;
2277 }
2278 }
2279 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2280 regex_t *preg;
2281 if (curproxy == &defproxy) {
2282 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2283 return -1;
2284 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002285 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2286 return 0;
2287
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 if (*(args[1]) == 0) {
2289 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2290 return -1;
2291 }
2292
2293 preg = calloc(1, sizeof(regex_t));
2294 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2295 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2296 return -1;
2297 }
2298
2299 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2300 }
2301 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2302 regex_t *preg;
2303 if (curproxy == &defproxy) {
2304 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2305 return -1;
2306 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002307 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2308 return 0;
2309
Willy Tarreaubaaee002006-06-26 02:48:02 +02002310 if (*(args[1]) == 0) {
2311 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2312 return -1;
2313 }
2314
2315 preg = calloc(1, sizeof(regex_t));
2316 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2317 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2318 return -1;
2319 }
2320
2321 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2322 }
2323 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2324 regex_t *preg;
2325 if (curproxy == &defproxy) {
2326 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2327 return -1;
2328 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002329 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2330 return 0;
2331
Willy Tarreaubaaee002006-06-26 02:48:02 +02002332 if (*(args[1]) == 0) {
2333 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2334 return -1;
2335 }
2336
2337 preg = calloc(1, sizeof(regex_t));
2338 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2339 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2340 return -1;
2341 }
2342
2343 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2344 }
2345 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2346 regex_t *preg;
2347 if (curproxy == &defproxy) {
2348 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2349 return -1;
2350 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002351 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2352 return 0;
2353
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 if (*(args[1]) == 0) {
2355 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2356 return -1;
2357 }
2358
2359 preg = calloc(1, sizeof(regex_t));
2360 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2361 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2362 return -1;
2363 }
2364
2365 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2366 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002367 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2368 regex_t *preg;
2369 if (curproxy == &defproxy) {
2370 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2371 return -1;
2372 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002373 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2374 return 0;
2375
Willy Tarreaub8750a82006-09-03 09:56:00 +02002376 if (*(args[1]) == 0) {
2377 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2378 return -1;
2379 }
2380
2381 preg = calloc(1, sizeof(regex_t));
2382 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2383 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2384 return -1;
2385 }
2386
2387 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2388 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2390 if (curproxy == &defproxy) {
2391 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2392 return -1;
2393 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002394 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2395 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396
2397 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2398 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2399 return 0;
2400 }
2401
2402 if (*(args[1]) == 0) {
2403 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2404 return -1;
2405 }
2406
2407 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2408 }
2409 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2410 regex_t *preg;
2411
2412 if (*(args[1]) == 0 || *(args[2]) == 0) {
2413 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2414 file, linenum, args[0]);
2415 return -1;
2416 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002417 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2418 return 0;
2419
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 preg = calloc(1, sizeof(regex_t));
2421 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2422 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2423 return -1;
2424 }
2425
2426 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2427 if (err) {
2428 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2429 file, linenum, *err);
2430 return -1;
2431 }
2432 }
2433 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2434 regex_t *preg;
2435 if (curproxy == &defproxy) {
2436 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2437 return -1;
2438 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002439 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2440 return 0;
2441
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 if (*(args[1]) == 0) {
2443 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2444 return -1;
2445 }
2446
2447 preg = calloc(1, sizeof(regex_t));
2448 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2449 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2450 return -1;
2451 }
2452
2453 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2454 if (err) {
2455 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2456 file, linenum, *err);
2457 return -1;
2458 }
2459 }
2460 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2461 regex_t *preg;
2462 if (curproxy == &defproxy) {
2463 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2464 return -1;
2465 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002466 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2467 return 0;
2468
Willy Tarreaubaaee002006-06-26 02:48:02 +02002469 if (*(args[1]) == 0) {
2470 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2471 return -1;
2472 }
2473
2474 preg = calloc(1, sizeof(regex_t));
2475 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2476 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2477 return -1;
2478 }
2479
2480 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2481 if (err) {
2482 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2483 file, linenum, *err);
2484 return -1;
2485 }
2486 }
2487 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2488 regex_t *preg;
2489 if (curproxy == &defproxy) {
2490 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2491 return -1;
2492 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002493 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2494 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495
2496 if (*(args[1]) == 0 || *(args[2]) == 0) {
2497 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2498 file, linenum, args[0]);
2499 return -1;
2500 }
2501
2502 preg = calloc(1, sizeof(regex_t));
2503 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2504 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2505 return -1;
2506 }
2507
2508 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2509 if (err) {
2510 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2511 file, linenum, *err);
2512 return -1;
2513 }
2514 }
2515 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2516 regex_t *preg;
2517 if (curproxy == &defproxy) {
2518 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2519 return -1;
2520 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002521 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2522 return 0;
2523
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 if (*(args[1]) == 0) {
2525 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2526 return -1;
2527 }
2528
2529 preg = calloc(1, sizeof(regex_t));
2530 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2531 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2532 return -1;
2533 }
2534
2535 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2536 if (err) {
2537 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2538 file, linenum, *err);
2539 return -1;
2540 }
2541 }
2542 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2543 regex_t *preg;
2544 if (curproxy == &defproxy) {
2545 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2546 return -1;
2547 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002548 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2549 return 0;
2550
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 if (*(args[1]) == 0) {
2552 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2553 return -1;
2554 }
2555
2556 preg = calloc(1, sizeof(regex_t));
2557 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2558 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2559 return -1;
2560 }
2561
2562 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2563 if (err) {
2564 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2565 file, linenum, *err);
2566 return -1;
2567 }
2568 }
2569 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2570 if (curproxy == &defproxy) {
2571 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2572 return -1;
2573 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002574 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2575 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576
2577 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2578 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2579 return 0;
2580 }
2581
2582 if (*(args[1]) == 0) {
2583 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2584 return -1;
2585 }
2586
2587 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2588 }
2589 else if (!strcmp(args[0], "errorloc") ||
2590 !strcmp(args[0], "errorloc302") ||
2591 !strcmp(args[0], "errorloc303")) { /* error location */
2592 int errnum, errlen;
2593 char *err;
2594
Willy Tarreau977b8e42006-12-29 14:19:17 +01002595 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2596 return 0;
2597
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002599 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002600 return -1;
2601 }
2602
2603 errnum = atol(args[1]);
2604 if (!strcmp(args[0], "errorloc303")) {
2605 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2606 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2607 } else {
2608 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2609 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2610 }
2611
Willy Tarreau0f772532006-12-23 20:51:41 +01002612 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2613 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002614 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002615 curproxy->errmsg[rc].str = err;
2616 curproxy->errmsg[rc].len = errlen;
2617 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002618 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002619 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002620
2621 if (rc >= HTTP_ERR_SIZE) {
2622 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2623 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 free(err);
2625 }
2626 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002627 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2628 int errnum, errlen, fd;
2629 char *err;
2630 struct stat stat;
2631
2632 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2633 return 0;
2634
2635 if (*(args[2]) == 0) {
2636 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2637 return -1;
2638 }
2639
2640 fd = open(args[2], O_RDONLY);
2641 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2642 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2643 file, linenum, args[2], args[1]);
2644 if (fd >= 0)
2645 close(fd);
2646 return -1;
2647 }
2648
2649 if (stat.st_size <= BUFSIZE) {
2650 errlen = stat.st_size;
2651 } else {
2652 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2653 file, linenum, args[2], BUFSIZE);
2654 errlen = BUFSIZE;
2655 }
2656
2657 err = malloc(errlen); /* malloc() must succeed during parsing */
2658 errnum = read(fd, err, errlen);
2659 if (errnum != errlen) {
2660 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2661 file, linenum, args[2], args[1]);
2662 close(fd);
2663 free(err);
2664 return -1;
2665 }
2666 close(fd);
2667
2668 errnum = atol(args[1]);
2669 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2670 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002671 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002672 curproxy->errmsg[rc].str = err;
2673 curproxy->errmsg[rc].len = errlen;
2674 break;
2675 }
2676 }
2677
2678 if (rc >= HTTP_ERR_SIZE) {
2679 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2680 file, linenum, errnum);
2681 free(err);
2682 }
2683 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002685 struct cfg_kw_list *kwl;
2686 int index;
2687
2688 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2689 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2690 if (kwl->kw[index].section != CFG_LISTEN)
2691 continue;
2692 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2693 /* prepare error message just in case */
2694 snprintf(trash, sizeof(trash),
2695 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002696 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2697 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002698 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2699 return -1;
2700 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002701 else if (rc > 0) {
2702 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2703 return 0;
2704 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002705 return 0;
2706 }
2707 }
2708 }
2709
Willy Tarreau6daf3432008-01-22 16:44:08 +01002710 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002711 return -1;
2712 }
2713 return 0;
2714}
2715
2716
2717/*
2718 * This function reads and parses the configuration file given in the argument.
2719 * returns 0 if OK, -1 if error.
2720 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002721int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002722{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002723 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002724 FILE *f;
2725 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002726 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002727 int confsect = CFG_NONE;
2728
2729 struct proxy *curproxy = NULL;
2730 struct server *newsrv = NULL;
2731
2732 if ((f=fopen(file,"r")) == NULL)
2733 return -1;
2734
2735 init_default_instance();
2736
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002737 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002738 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002739 char *end;
2740 char *args[MAX_LINE_ARGS + 1];
2741 char *line = thisline;
2742
Willy Tarreaubaaee002006-06-26 02:48:02 +02002743 linenum++;
2744
2745 end = line + strlen(line);
2746
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002747 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2748 /* Check if we reached the limit and the last char is not \n.
2749 * Watch out for the last line without the terminating '\n'!
2750 */
2751 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2752 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002753 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002754 }
2755
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002757 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002758 line++;
2759
2760 arg = 0;
2761 args[arg] = line;
2762
2763 while (*line && arg < MAX_LINE_ARGS) {
2764 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2765 * C equivalent value. Other combinations left unchanged (eg: \1).
2766 */
2767 if (*line == '\\') {
2768 int skip = 0;
2769 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2770 *line = line[1];
2771 skip = 1;
2772 }
2773 else if (line[1] == 'r') {
2774 *line = '\r';
2775 skip = 1;
2776 }
2777 else if (line[1] == 'n') {
2778 *line = '\n';
2779 skip = 1;
2780 }
2781 else if (line[1] == 't') {
2782 *line = '\t';
2783 skip = 1;
2784 }
2785 else if (line[1] == 'x') {
2786 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2787 unsigned char hex1, hex2;
2788 hex1 = toupper(line[2]) - '0';
2789 hex2 = toupper(line[3]) - '0';
2790 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2791 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2792 *line = (hex1<<4) + hex2;
2793 skip = 3;
2794 }
2795 else {
2796 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002797 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002798 }
2799 }
2800 if (skip) {
2801 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2802 end -= skip;
2803 }
2804 line++;
2805 }
2806 else if (*line == '#' || *line == '\n' || *line == '\r') {
2807 /* end of string, end of loop */
2808 *line = 0;
2809 break;
2810 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002811 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002812 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002813 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002814 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815 line++;
2816 args[++arg] = line;
2817 }
2818 else {
2819 line++;
2820 }
2821 }
2822
2823 /* empty line */
2824 if (!**args)
2825 continue;
2826
Willy Tarreau540abe42007-05-02 20:50:16 +02002827 /* zero out remaining args and ensure that at least one entry
2828 * is zeroed out.
2829 */
2830 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002831 args[arg] = line;
2832 }
2833
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002834 if (!strcmp(args[0], "no")) {
2835 inv = 1;
2836 for (arg=0; *args[arg+1]; arg++)
2837 args[arg] = args[arg+1]; // shift args after inversion
2838 }
2839
2840 if (inv && strcmp(args[0], "option")) {
2841 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002842 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002843 }
2844
Willy Tarreau977b8e42006-12-29 14:19:17 +01002845 if (!strcmp(args[0], "listen") ||
2846 !strcmp(args[0], "frontend") ||
2847 !strcmp(args[0], "backend") ||
2848 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002849 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002850 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002851 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002852 cursection = strdup(args[0]);
2853 }
2854 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002856 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002857 cursection = strdup(args[0]);
2858 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002859 /* else it's a section keyword */
2860
2861 switch (confsect) {
2862 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002863 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002864 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002865 break;
2866 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002867 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002868 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869 break;
2870 default:
2871 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002872 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002875 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002876 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 fclose(f);
2878
2879 /*
2880 * Now, check for the integrity of all that we have collected.
2881 */
2882
2883 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002884 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885
2886 if ((curproxy = proxy) == NULL) {
2887 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2888 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002889 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 }
2891
2892 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002893 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002894 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002895
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02002897 /* ensure we don't keep listeners uselessly bound */
2898 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899 curproxy = curproxy->next;
2900 continue;
2901 }
2902
Willy Tarreau977b8e42006-12-29 14:19:17 +01002903 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2904 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 +01002905 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002906 cfgerr++;
2907 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002908 else if (curproxy->cap & PR_CAP_BE &&
2909 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002910 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002911 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002912 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2913 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 +01002914 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 cfgerr++;
2916 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002917
Willy Tarreau31682232007-11-29 15:38:04 +01002918 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002920 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002921 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002922 cfgerr++;
2923 }
2924#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2925 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002926 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002927 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928 cfgerr++;
2929 }
2930#endif
2931 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002932 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002933 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934 }
2935 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002936
2937 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002938 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002939 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002940 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002941 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002942 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002943 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002944 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002945 }
2946 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002947 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002948 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002949 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002950 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002951 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002952 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002953 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002954 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002955 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2956 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002957
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002958 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002959 file, proxy_type_str(curproxy), curproxy->id);
2960 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002961 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002962
2963 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2964 if ((newsrv = curproxy->srv) != NULL) {
2965 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2966 file, proxy_type_str(curproxy), curproxy->id);
2967 }
2968 }
2969
2970 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2972 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2973 file, curproxy->id);
2974 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002975 }
2976 }
2977
Willy Tarreau82936582007-11-30 15:20:09 +01002978 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2979 curproxy->options &= ~PR_O_DISABLE404;
2980 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2981 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2982 }
2983
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002984 /* if a default backend was specified, let's find it */
2985 if (curproxy->defbe.name) {
2986 struct proxy *target;
2987
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002988 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2989 if (!target) {
2990 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2991 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002992 cfgerr++;
2993 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002994 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2995 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002996 } else {
2997 free(curproxy->defbe.name);
2998 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002999 }
3000 }
3001
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003002 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003003 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3004 /* map jump target for ACT_SETBE in req_rep chain */
3005 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003006 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003007 struct proxy *target;
3008
Willy Tarreaua496b602006-12-17 23:15:24 +01003009 if (exp->action != ACT_SETBE)
3010 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003011
3012 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3013 if (!target) {
3014 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3015 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003016 cfgerr++;
3017 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003018 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3019 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003020 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003021 } else {
3022 free((void *)exp->replace);
3023 exp->replace = (const char *)target;
3024 }
3025 }
3026 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003027
3028 /* find the target proxy for 'use_backend' rules */
3029 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003030 struct proxy *target;
3031
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003032 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003033
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003034 if (!target) {
3035 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3036 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003037 cfgerr++;
3038 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003039 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3040 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003041 cfgerr++;
3042 } else {
3043 free((void *)rule->be.name);
3044 rule->be.backend = target;
3045 }
3046 }
3047
Willy Tarreau2738a142006-07-08 17:28:09 +02003048 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003049 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003050 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003051 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003052 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003053 " | While not properly invalid, you will certainly encounter various problems\n"
3054 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003055 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003056 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003057 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003058
Willy Tarreau1fa31262007-12-03 00:36:16 +01003059 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3060 * We must still support older configurations, so let's find out whether those
3061 * parameters have been set or must be copied from contimeouts.
3062 */
3063 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003064 if (!curproxy->timeout.tarpit ||
3065 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003066 /* tarpit timeout not set. We search in the following order:
3067 * default.tarpit, curr.connect, default.connect.
3068 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003069 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003070 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003071 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003072 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003073 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003074 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003075 }
3076 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003077 (!curproxy->timeout.queue ||
3078 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003079 /* queue timeout not set. We search in the following order:
3080 * default.queue, curr.connect, default.connect.
3081 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003082 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003083 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003084 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003085 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003086 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003087 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003088 }
3089 }
3090
Willy Tarreauf3c69202006-07-09 16:42:34 +02003091 if (curproxy->options & PR_O_SSL3_CHK) {
3092 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3093 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3094 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3095 }
3096
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003097 /* The small pools required for the capture lists */
3098 if (curproxy->nb_req_cap)
3099 curproxy->req_cap_pool = create_pool("ptrcap",
3100 curproxy->nb_req_cap * sizeof(char *),
3101 MEM_F_SHARED);
3102 if (curproxy->nb_rsp_cap)
3103 curproxy->rsp_cap_pool = create_pool("ptrcap",
3104 curproxy->nb_rsp_cap * sizeof(char *),
3105 MEM_F_SHARED);
3106
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003107 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3108 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3109 MEM_F_SHARED);
3110
Willy Tarreau86034312006-12-29 00:10:33 +01003111 /* for backwards compatibility with "listen" instances, if
3112 * fullconn is not set but maxconn is set, then maxconn
3113 * is used.
3114 */
3115 if (!curproxy->fullconn)
3116 curproxy->fullconn = curproxy->maxconn;
3117
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 /* first, we will invert the servers list order */
3119 newsrv = NULL;
3120 while (curproxy->srv) {
3121 struct server *next;
3122
3123 next = curproxy->srv->next;
3124 curproxy->srv->next = newsrv;
3125 newsrv = curproxy->srv;
3126 if (!next)
3127 break;
3128 curproxy->srv = next;
3129 }
3130
Willy Tarreau20697042007-11-15 23:26:18 +01003131 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003132 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133
Willy Tarreaub625a082007-11-26 01:15:43 +01003134 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003135 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003136 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003137 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3138 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003139 else
3140 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141
3142 if (curproxy->options & PR_O_LOGASAP)
3143 curproxy->to_log &= ~LW_BYTES;
3144
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003146 * ensure that we're not cross-dressing a TCP server into HTTP.
3147 */
3148 newsrv = curproxy->srv;
3149 while (newsrv != NULL) {
3150 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3151 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3152 file, proxy_type_str(curproxy), curproxy->id, linenum);
3153 goto err;
3154 }
3155 newsrv = newsrv->next;
3156 }
3157
3158 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159 * If this server supports a maxconn parameter, it needs a dedicated
3160 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003161 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 */
3163 newsrv = curproxy->srv;
3164 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003165 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003166 /* Only 'minconn' was specified, or it was higher than or equal
3167 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3168 * this will avoid further useless expensive computations.
3169 */
3170 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003171 } else if (newsrv->maxconn && !newsrv->minconn) {
3172 /* minconn was not specified, so we set it to maxconn */
3173 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003174 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3175 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003176 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003177 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 }
3179
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003180 if (newsrv->trackit) {
3181 struct proxy *px;
3182 struct server *srv;
3183 char *pname, *sname;
3184
3185 pname = newsrv->trackit;
3186 sname = strrchr(pname, '/');
3187
3188 if (sname)
3189 *sname++ = '\0';
3190 else {
3191 sname = pname;
3192 pname = NULL;
3193 }
3194
3195 if (pname) {
3196 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3197 if (!px) {
3198 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3199 file, proxy_type_str(curproxy), curproxy->id,
3200 newsrv->id, pname);
3201 return -1;
3202 }
3203 } else
3204 px = curproxy;
3205
3206 srv = findserver(px, sname);
3207 if (!srv) {
3208 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3209 file, proxy_type_str(curproxy), curproxy->id,
3210 newsrv->id, sname);
3211 return -1;
3212 }
3213
3214 if (!(srv->state & SRV_CHECKED)) {
3215 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3216 "tracing as it does not have checks enabled.\n",
3217 file, proxy_type_str(curproxy), curproxy->id,
3218 newsrv->id, px->id, srv->id);
3219 return -1;
3220 }
3221
3222 if (curproxy != px &&
3223 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3224 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3225 "tracing: disable-on-404 option inconsistency.\n",
3226 file, proxy_type_str(curproxy), curproxy->id,
3227 newsrv->id, px->id, srv->id);
3228 return -1;
3229 }
3230
3231 newsrv->tracked = srv;
3232 newsrv->tracknext = srv->tracknext;
3233 srv->tracknext = newsrv;
3234
3235 free(newsrv->trackit);
3236 }
3237
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 newsrv = newsrv->next;
3239 }
3240
Willy Tarreaue6b98942007-10-29 01:09:36 +01003241 /* adjust this proxy's listeners */
3242 listener = curproxy->listen;
3243 while (listener) {
3244 if (curproxy->options & PR_O_TCP_NOLING)
3245 listener->options |= LI_O_NOLINGER;
3246 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003247 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003248 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003249 listener->accept = event_accept;
3250 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003251 listener->handler = process_session;
3252
3253 if (curproxy->mode == PR_MODE_HTTP)
3254 listener->analysers |= AN_REQ_HTTP_HDR;
3255
3256 if (curproxy->tcp_req.inspect_delay)
3257 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003258
3259 listener = listener->next;
3260 }
3261
Willy Tarreaubaaee002006-06-26 02:48:02 +02003262 curproxy = curproxy->next;
3263 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003264
Willy Tarreaubaaee002006-06-26 02:48:02 +02003265 if (cfgerr > 0) {
3266 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003267 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003269
3270 /*
3271 * Recount currently required checks.
3272 */
3273
3274 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3275 int optnum;
3276
3277 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3278 if (!(curproxy->options & cfg_opts[optnum].val))
3279 continue;
3280
3281 global.last_checks |= cfg_opts[optnum].checks;
3282 }
3283 }
3284
Willy Tarreaua534fea2008-08-03 12:19:50 +02003285 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003286 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003287 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003288
3289 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003290 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003291 cursection = NULL;
3292 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293}
3294
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003295/*
3296 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3297 * parsing sessions.
3298 */
3299void cfg_register_keywords(struct cfg_kw_list *kwl)
3300{
3301 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3302}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003304/*
3305 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3306 */
3307void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3308{
3309 LIST_DEL(&kwl->list);
3310 LIST_INIT(&kwl->list);
3311}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003312
3313/*
3314 * Local variables:
3315 * c-indent-level: 8
3316 * c-basic-offset: 8
3317 * End:
3318 */