blob: a492a932eddbc26d007ca619f89438921b63cb27 [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>
Willy Tarreau0f772532006-12-23 20:51:41 +010035#include <types/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <types/polling.h>
37#include <types/proxy.h>
38#include <types/queue.h>
39
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010045#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020046#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010047#include <proto/protocols.h>
48#include <proto/proto_tcp.h>
49#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010050#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/server.h>
52#include <proto/task.h>
53
54
Willy Tarreauf3c69202006-07-09 16:42:34 +020055/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
56 * ssl-hello-chk option to ensure that the remote server speaks SSL.
57 *
58 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
59 */
60const char sslv3_client_hello_pkt[] = {
61 "\x16" /* ContentType : 0x16 = Hanshake */
62 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
63 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
64 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
65 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
66 "\x03\x00" /* Hello Version : 0x0300 = v3 */
67 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
68 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
69 "\x00" /* Session ID length : empty (no session ID) */
70 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
71 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
72 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
73 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
74 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
75 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
76 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
77 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
78 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
79 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
80 "\x00\x38" "\x00\x39" "\x00\x3A"
81 "\x01" /* Compression Length : 0x01 = 1 byte for types */
82 "\x00" /* Compression Type : 0x00 = NULL compression */
83};
84
Willy Tarreau13943ab2006-12-31 00:24:10 +010085/* some of the most common options which are also the easiest to handle */
86static const struct {
87 const char *name;
88 unsigned int val;
89 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010090 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010091} cfg_opts[] =
92{
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010094 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010095 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010096 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010097 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
98 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
99 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
100 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
101 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
102 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
103 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
104 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100106 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
107 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100108#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100109 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
110#endif
111#ifdef TPROXY
112 { "transparent", PR_O_TRANSP, PR_CAP_FE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100113#endif
114
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116};
117
Willy Tarreaubaaee002006-06-26 02:48:02 +0200118
Willy Tarreau6daf3432008-01-22 16:44:08 +0100119static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200120static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
121int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
122int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
123
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200124/* List head of all known configuration keywords */
125static struct cfg_kw_list cfg_keywords = {
126 .list = LIST_HEAD_INIT(cfg_keywords.list)
127};
128
Willy Tarreaubaaee002006-06-26 02:48:02 +0200129/*
130 * converts <str> to a list of listeners which are dynamically allocated.
131 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
132 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
133 * - <port> is a numerical port from 1 to 65535 ;
134 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
135 * This can be repeated as many times as necessary, separated by a coma.
136 * The <tail> argument is a pointer to a current list which should be appended
137 * to the tail of the new list. The pointer to the new list is returned.
138 */
139static struct listener *str2listener(char *str, struct listener *tail)
140{
141 struct listener *l;
142 char *c, *next, *range, *dupstr;
143 int port, end;
144
145 next = dupstr = strdup(str);
146
147 while (next && *next) {
148 struct sockaddr_storage ss;
149
150 str = next;
151 /* 1) look for the end of the first address */
152 if ((next = strrchr(str, ',')) != NULL) {
153 *next++ = 0;
154 }
155
156 /* 2) look for the addr/port delimiter, it's the last colon. */
157 if ((range = strrchr(str, ':')) == NULL) {
158 Alert("Missing port number: '%s'\n", str);
159 goto fail;
160 }
161
162 *range++ = 0;
163
164 if (strrchr(str, ':') != NULL) {
165 /* IPv6 address contains ':' */
166 memset(&ss, 0, sizeof(ss));
167 ss.ss_family = AF_INET6;
168
169 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
170 Alert("Invalid server address: '%s'\n", str);
171 goto fail;
172 }
173 }
174 else {
175 memset(&ss, 0, sizeof(ss));
176 ss.ss_family = AF_INET;
177
178 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
179 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
180 }
181 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
182 struct hostent *he;
183
184 if ((he = gethostbyname(str)) == NULL) {
185 Alert("Invalid server name: '%s'\n", str);
186 goto fail;
187 }
188 else
189 ((struct sockaddr_in *)&ss)->sin_addr =
190 *(struct in_addr *) *(he->h_addr_list);
191 }
192 }
193
194 /* 3) look for the port-end delimiter */
195 if ((c = strchr(range, '-')) != NULL) {
196 *c++ = 0;
197 end = atol(c);
198 }
199 else {
200 end = atol(range);
201 }
202
203 port = atol(range);
204
205 if (port < 1 || port > 65535) {
206 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
207 goto fail;
208 }
209
210 if (end < 1 || end > 65535) {
211 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
212 goto fail;
213 }
214
215 for (; port <= end; port++) {
216 l = (struct listener *)calloc(1, sizeof(struct listener));
217 l->next = tail;
218 tail = l;
219
220 l->fd = -1;
221 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100222 l->state = LI_INIT;
223
224 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100226 tcpv6_add_listener(l);
227 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100229 tcpv4_add_listener(l);
230 }
231 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200232 } /* end for(port) */
233 } /* end while(next) */
234 free(dupstr);
235 return tail;
236 fail:
237 free(dupstr);
238 return NULL;
239}
240
Willy Tarreau977b8e42006-12-29 14:19:17 +0100241/*
242 * Sends a warning if proxy <proxy> does not have at least one of the
243 * capabilities in <cap>. An optionnal <hint> may be added at the end
244 * of the warning to help the user. Returns 1 if a warning was emitted
245 * or 0 if the condition is valid.
246 */
247int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
248{
249 char *msg;
250
251 switch (cap) {
252 case PR_CAP_BE: msg = "no backend"; break;
253 case PR_CAP_FE: msg = "no frontend"; break;
254 case PR_CAP_RS: msg = "no ruleset"; break;
255 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
256 default: msg = "not enough"; break;
257 }
258
259 if (!(proxy->cap & cap)) {
260 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100261 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100262 return 1;
263 }
264 return 0;
265}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266
267/*
268 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
269 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100270int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271{
272
273 if (!strcmp(args[0], "global")) { /* new section */
274 /* no option, nothing special to do */
275 return 0;
276 }
277 else if (!strcmp(args[0], "daemon")) {
278 global.mode |= MODE_DAEMON;
279 }
280 else if (!strcmp(args[0], "debug")) {
281 global.mode |= MODE_DEBUG;
282 }
283 else if (!strcmp(args[0], "noepoll")) {
284 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
285 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200286 else if (!strcmp(args[0], "nosepoll")) {
287 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
288 }
289 else if (!strcmp(args[0], "nokqueue")) {
290 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
291 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292 else if (!strcmp(args[0], "nopoll")) {
293 cfg_polling_mechanism &= ~POLL_USE_POLL;
294 }
295 else if (!strcmp(args[0], "quiet")) {
296 global.mode |= MODE_QUIET;
297 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200298 else if (!strcmp(args[0], "tune.maxpollevents")) {
299 if (global.tune.maxpollevents != 0) {
300 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
301 return 0;
302 }
303 if (*(args[1]) == 0) {
304 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
305 return -1;
306 }
307 global.tune.maxpollevents = atol(args[1]);
308 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100309 else if (!strcmp(args[0], "tune.maxaccept")) {
310 if (global.tune.maxaccept != 0) {
311 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
312 return 0;
313 }
314 if (*(args[1]) == 0) {
315 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
316 return -1;
317 }
318 global.tune.maxaccept = atol(args[1]);
319 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200320 else if (!strcmp(args[0], "uid")) {
321 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200322 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323 return 0;
324 }
325 if (*(args[1]) == 0) {
326 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
327 return -1;
328 }
329 global.uid = atol(args[1]);
330 }
331 else if (!strcmp(args[0], "gid")) {
332 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200333 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200334 return 0;
335 }
336 if (*(args[1]) == 0) {
337 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
338 return -1;
339 }
340 global.gid = atol(args[1]);
341 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200342 /* user/group name handling */
343 else if (!strcmp(args[0], "user")) {
344 struct passwd *ha_user;
345 if (global.uid != 0) {
346 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
347 return 0;
348 }
349 errno = 0;
350 ha_user = getpwnam(args[1]);
351 if (ha_user != NULL) {
352 global.uid = (int)ha_user->pw_uid;
353 }
354 else {
355 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
356 exit(1);
357 }
358 }
359 else if (!strcmp(args[0], "group")) {
360 struct group *ha_group;
361 if (global.gid != 0) {
362 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
363 return 0;
364 }
365 errno = 0;
366 ha_group = getgrnam(args[1]);
367 if (ha_group != NULL) {
368 global.gid = (int)ha_group->gr_gid;
369 }
370 else {
371 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
372 exit(1);
373 }
374 }
375 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200376 else if (!strcmp(args[0], "nbproc")) {
377 if (global.nbproc != 0) {
378 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
379 return 0;
380 }
381 if (*(args[1]) == 0) {
382 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
383 return -1;
384 }
385 global.nbproc = atol(args[1]);
386 }
387 else if (!strcmp(args[0], "maxconn")) {
388 if (global.maxconn != 0) {
389 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
390 return 0;
391 }
392 if (*(args[1]) == 0) {
393 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
394 return -1;
395 }
396 global.maxconn = atol(args[1]);
397#ifdef SYSTEM_MAXCONN
398 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
399 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);
400 global.maxconn = DEFAULT_MAXCONN;
401 }
402#endif /* SYSTEM_MAXCONN */
403 }
404 else if (!strcmp(args[0], "ulimit-n")) {
405 if (global.rlimit_nofile != 0) {
406 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
407 return 0;
408 }
409 if (*(args[1]) == 0) {
410 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
411 return -1;
412 }
413 global.rlimit_nofile = atol(args[1]);
414 }
415 else if (!strcmp(args[0], "chroot")) {
416 if (global.chroot != NULL) {
417 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
418 return 0;
419 }
420 if (*(args[1]) == 0) {
421 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
422 return -1;
423 }
424 global.chroot = strdup(args[1]);
425 }
426 else if (!strcmp(args[0], "pidfile")) {
427 if (global.pidfile != NULL) {
428 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
429 return 0;
430 }
431 if (*(args[1]) == 0) {
432 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
433 return -1;
434 }
435 global.pidfile = strdup(args[1]);
436 }
437 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100438 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200439 int facility, level;
440
441 if (*(args[1]) == 0 || *(args[2]) == 0) {
442 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
443 return -1;
444 }
445
446 facility = get_log_facility(args[2]);
447 if (facility < 0) {
448 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
449 exit(1);
450 }
451
452 level = 7; /* max syslog level = debug */
453 if (*(args[3])) {
454 level = get_log_level(args[3]);
455 if (level < 0) {
456 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
457 exit(1);
458 }
459 }
460
Robert Tsai81ae1952007-12-05 10:47:29 +0100461 if (args[1][0] == '/') {
462 logsrv.u.addr.sa_family = AF_UNIX;
463 logsrv.u.un = *str2sun(args[1]);
464 } else {
465 logsrv.u.addr.sa_family = AF_INET;
466 logsrv.u.in = *str2sa(args[1]);
467 if (!logsrv.u.in.sin_port)
468 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470
471 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100472 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200473 global.logfac1 = facility;
474 global.loglev1 = level;
475 }
476 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100477 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200478 global.logfac2 = facility;
479 global.loglev2 = level;
480 }
481 else {
482 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
483 return -1;
484 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200485 }
486 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
487 if (global.spread_checks != 0) {
488 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
489 return 0;
490 }
491 if (*(args[1]) == 0) {
492 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
493 return -1;
494 }
495 global.spread_checks = atol(args[1]);
496 if (global.spread_checks < 0 || global.spread_checks > 50) {
497 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
498 return -1;
499 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200500 }
501 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200502 struct cfg_kw_list *kwl;
503 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200504 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200505
506 list_for_each_entry(kwl, &cfg_keywords.list, list) {
507 for (index = 0; kwl->kw[index].kw != NULL; index++) {
508 if (kwl->kw[index].section != CFG_GLOBAL)
509 continue;
510 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
511 /* prepare error message just in case */
512 snprintf(trash, sizeof(trash),
513 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200514 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
515 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200516 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
517 return -1;
518 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200519 else if (rc > 0) {
520 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
521 return 0;
522 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200523 return 0;
524 }
525 }
526 }
527
Willy Tarreaubaaee002006-06-26 02:48:02 +0200528 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
529 return -1;
530 }
531 return 0;
532}
533
534
535static void init_default_instance()
536{
537 memset(&defproxy, 0, sizeof(defproxy));
538 defproxy.mode = PR_MODE_TCP;
539 defproxy.state = PR_STNEW;
540 defproxy.maxconn = cfg_maxpconn;
541 defproxy.conn_retries = CONN_RETRIES;
542 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100543 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200544}
545
546/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100547 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
548 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200549 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100550int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200551{
552 static struct proxy *curproxy = NULL;
553 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200554 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100555 int rc;
556 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200557
Willy Tarreau977b8e42006-12-29 14:19:17 +0100558 if (!strcmp(args[0], "listen"))
559 rc = PR_CAP_LISTEN;
560 else if (!strcmp(args[0], "frontend"))
561 rc = PR_CAP_FE | PR_CAP_RS;
562 else if (!strcmp(args[0], "backend"))
563 rc = PR_CAP_BE | PR_CAP_RS;
564 else if (!strcmp(args[0], "ruleset"))
565 rc = PR_CAP_RS;
566 else
567 rc = PR_CAP_NONE;
568
569 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200570 if (!*args[1]) {
571 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
572 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
573 file, linenum, args[0]);
574 return -1;
575 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200576
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100577 err = invalid_char(args[1]);
578 if (err) {
579 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
580 file, linenum, *err, args[0], args[1]);
581 return -1;
582 }
583
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200584 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
585 /*
586 * If there are two proxies with the same name only following
587 * combinations are allowed:
588 *
589 * listen backend frontend ruleset
590 * listen - - - -
591 * backend - - OK -
592 * frontend - OK - -
593 * ruleset - - - -
594 */
595
596 if (!strcmp(curproxy->id, args[1]) &&
597 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
598 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100599 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
600 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200601 }
602 }
603
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
605 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
606 return -1;
607 }
608
609 curproxy->next = proxy;
610 proxy = curproxy;
611 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200612 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200613 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200614 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100615 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200616 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200617 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618
Willy Tarreauee991362007-05-14 14:37:50 +0200619 /* Timeouts are defined as -1, so we cannot use the zeroed area
620 * as a default value.
621 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100622 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200623
624 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200625 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100626 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200627
628 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100629 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 curproxy->listen = str2listener(args[2], curproxy->listen);
631 if (!curproxy->listen)
632 return -1;
633 global.maxsock++;
634 }
635
636 /* set default values */
637 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200638 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100639 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200640 curproxy->except_net = defproxy.except_net;
641 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642
Willy Tarreau977b8e42006-12-29 14:19:17 +0100643 if (curproxy->cap & PR_CAP_FE) {
644 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100645 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100646
647 /* initialize error relocations */
648 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
649 if (defproxy.errmsg[rc].str)
650 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
651 }
652
653 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200655
Willy Tarreau977b8e42006-12-29 14:19:17 +0100656 if (curproxy->cap & PR_CAP_BE) {
657 curproxy->fullconn = defproxy.fullconn;
658 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200659
Willy Tarreau977b8e42006-12-29 14:19:17 +0100660 if (defproxy.check_req)
661 curproxy->check_req = strdup(defproxy.check_req);
662 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200663
Willy Tarreau977b8e42006-12-29 14:19:17 +0100664 if (defproxy.cookie_name)
665 curproxy->cookie_name = strdup(defproxy.cookie_name);
666 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100667
668 if (defproxy.url_param_name)
669 curproxy->url_param_name = strdup(defproxy.url_param_name);
670 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100671 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200672
Willy Tarreau977b8e42006-12-29 14:19:17 +0100673 if (curproxy->cap & PR_CAP_RS) {
674 if (defproxy.capture_name)
675 curproxy->capture_name = strdup(defproxy.capture_name);
676 curproxy->capture_namelen = defproxy.capture_namelen;
677 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200679
Willy Tarreau977b8e42006-12-29 14:19:17 +0100680 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100681 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100682 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100683 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100684 curproxy->uri_auth = defproxy.uri_auth;
685 curproxy->mon_net = defproxy.mon_net;
686 curproxy->mon_mask = defproxy.mon_mask;
687 if (defproxy.monitor_uri)
688 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
689 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100690 if (defproxy.defbe.name)
691 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100692 }
693
694 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100695 curproxy->timeout.connect = defproxy.timeout.connect;
696 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100697 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100698 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100699 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100700 curproxy->source_addr = defproxy.source_addr;
701 }
702
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 curproxy->mode = defproxy.mode;
704 curproxy->logfac1 = defproxy.logfac1;
705 curproxy->logsrv1 = defproxy.logsrv1;
706 curproxy->loglev1 = defproxy.loglev1;
707 curproxy->logfac2 = defproxy.logfac2;
708 curproxy->logsrv2 = defproxy.logsrv2;
709 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200710 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100711 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
712 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200713
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714 return 0;
715 }
716 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
717 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100718 /* FIXME-20070101: we should do this too at the end of the
719 * config parsing to free all default values.
720 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 if (defproxy.check_req) free(defproxy.check_req);
722 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100723 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200724 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200725 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100726 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100727
728 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
729 if (defproxy.errmsg[rc].len)
730 free(defproxy.errmsg[rc].str);
731 }
732
Willy Tarreaubaaee002006-06-26 02:48:02 +0200733 /* we cannot free uri_auth because it might already be used */
734 init_default_instance();
735 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100736 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200737 return 0;
738 }
739 else if (curproxy == NULL) {
740 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
741 return -1;
742 }
743
Willy Tarreau977b8e42006-12-29 14:19:17 +0100744
745 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200746 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100747 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748 if (curproxy == &defproxy) {
749 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
750 return -1;
751 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100752 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
753 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200754
755 if (strchr(args[1], ':') == NULL) {
756 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
757 file, linenum, args[0]);
758 return -1;
759 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100760
761 last_listen = curproxy->listen;
762 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200763 if (!curproxy->listen)
764 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100765 if (*args[2]) {
766#ifdef CONFIG_HAP_LINUX_TPROXY
767 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
768 struct listener *l;
769
770 for (l = curproxy->listen; l != last_listen; l = l->next)
771 l->options |= LI_O_FOREIGN;
772 }
773 else {
774 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
775 file, linenum, args[0]);
776 return -1;
777 }
778#else
779 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
780 file, linenum, args[0]);
781 return -1;
782#endif
783 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784 global.maxsock++;
785 return 0;
786 }
787 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
788 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
789 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
790 file, linenum, args[0]);
791 return -1;
792 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100793 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
794 return 0;
795
Willy Tarreaubaaee002006-06-26 02:48:02 +0200796 /* flush useless bits */
797 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
798 return 0;
799 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200800 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100801 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
802 return 0;
803
Willy Tarreau1c47f852006-07-09 08:22:27 +0200804 if (!*args[1]) {
805 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
806 file, linenum, args[0]);
807 return -1;
808 }
809
810 if (curproxy->monitor_uri != NULL)
811 free(curproxy->monitor_uri);
812
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100813 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200814 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100815 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200816 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
817
818 return 0;
819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200820 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
821 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
822 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
823 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
824 else {
825 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
826 return -1;
827 }
828 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100829 else if (!strcmp(args[0], "id")) {
830 struct proxy *target;
831
832 if (curproxy == &defproxy) {
833 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
834 file, linenum, args[0]);
835 return -1;
836 }
837
838 if (!*args[1]) {
839 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
840 file, linenum, args[0]);
841 return -1;
842 }
843
844 curproxy->uuid = atol(args[1]);
845
846 if (curproxy->uuid < 1001) {
847 Alert("parsing [%s:%d]: custom id has to be > 1000",
848 file, linenum);
849 return -1;
850 }
851
852 for (target = proxy; target; target = target->next)
853 if (curproxy != target && curproxy->uuid == target->uuid) {
854 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
855 file, linenum, curproxy->id, target->id);
856 return -1;
857 }
858 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200859 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
860 curproxy->state = PR_STSTOPPED;
861 }
862 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
863 curproxy->state = PR_STNEW;
864 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200865 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100866 err = invalid_char(args[1]);
867 if (err) {
868 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
869 file, linenum, *err, args[1]);
870 return -1;
871 }
872
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200873 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
874 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
875 file, linenum, args[1]);
876 return -1;
877 }
878 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879 else if (!strcmp(args[0], "cookie")) { /* cookie name */
880 int cur_arg;
881 // if (curproxy == &defproxy) {
882 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
883 // return -1;
884 // }
885
Willy Tarreau977b8e42006-12-29 14:19:17 +0100886 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
887 return 0;
888
Willy Tarreaubaaee002006-06-26 02:48:02 +0200889 if (curproxy->cookie_name != NULL) {
890 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
891 // file, linenum);
892 // return 0;
893 free(curproxy->cookie_name);
894 }
895
896 if (*(args[1]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
898 file, linenum, args[0]);
899 return -1;
900 }
901 curproxy->cookie_name = strdup(args[1]);
902 curproxy->cookie_len = strlen(curproxy->cookie_name);
903
904 cur_arg = 2;
905 while (*(args[cur_arg])) {
906 if (!strcmp(args[cur_arg], "rewrite")) {
907 curproxy->options |= PR_O_COOK_RW;
908 }
909 else if (!strcmp(args[cur_arg], "indirect")) {
910 curproxy->options |= PR_O_COOK_IND;
911 }
912 else if (!strcmp(args[cur_arg], "insert")) {
913 curproxy->options |= PR_O_COOK_INS;
914 }
915 else if (!strcmp(args[cur_arg], "nocache")) {
916 curproxy->options |= PR_O_COOK_NOC;
917 }
918 else if (!strcmp(args[cur_arg], "postonly")) {
919 curproxy->options |= PR_O_COOK_POST;
920 }
921 else if (!strcmp(args[cur_arg], "prefix")) {
922 curproxy->options |= PR_O_COOK_PFX;
923 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200924 else if (!strcmp(args[cur_arg], "domain")) {
925 if (!*args[cur_arg + 1]) {
926 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
927 file, linenum, args[cur_arg]);
928 return -1;
929 }
930
931 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
932 /* rfc2109, 4.3.2 Rejecting Cookies */
933 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
934 " dots or does not start with a dot.\n",
935 file, linenum, args[cur_arg + 1]);
936 return -1;
937 }
938
939 err = invalid_domainchar(args[cur_arg + 1]);
940 if (err) {
941 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
942 file, linenum, *err, args[cur_arg + 1]);
943 return -1;
944 }
945
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +0200946 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200947 cur_arg++;
948 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200950 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 file, linenum, args[0]);
952 return -1;
953 }
954 cur_arg++;
955 }
956 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
957 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
958 file, linenum);
959 return -1;
960 }
961
962 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
963 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
964 file, linenum);
965 return -1;
966 }
967 }/* end else if (!strcmp(args[0], "cookie")) */
968 else if (!strcmp(args[0], "appsession")) { /* cookie name */
969 // if (curproxy == &defproxy) {
970 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
971 // return -1;
972 // }
973
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 (curproxy->appsession_name != NULL) {
978 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
979 // file, linenum);
980 // return 0;
981 free(curproxy->appsession_name);
982 }
983
984 if (*(args[5]) == 0) {
985 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
986 file, linenum, args[0]);
987 return -1;
988 }
989 have_appsession = 1;
990 curproxy->appsession_name = strdup(args[1]);
991 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
992 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100993 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
994 if (err) {
995 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
996 file, linenum, *err, args[0]);
997 return -1;
998 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200999 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001000
Willy Tarreau51041c72007-09-09 21:56:53 +02001001 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1002 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001003 return -1;
1004 }
1005 } /* Url App Session */
1006 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001007 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1008 return 0;
1009
Willy Tarreaubaaee002006-06-26 02:48:02 +02001010 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
1011 // if (curproxy == &defproxy) {
1012 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1013 // return -1;
1014 // }
1015
1016 if (curproxy->capture_name != NULL) {
1017 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
1018 // file, linenum, args[0]);
1019 // return 0;
1020 free(curproxy->capture_name);
1021 }
1022
1023 if (*(args[4]) == 0) {
1024 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1025 file, linenum, args[0]);
1026 return -1;
1027 }
1028 curproxy->capture_name = strdup(args[2]);
1029 curproxy->capture_namelen = strlen(curproxy->capture_name);
1030 curproxy->capture_len = atol(args[4]);
1031 if (curproxy->capture_len >= CAPTURE_LEN) {
1032 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1033 file, linenum, CAPTURE_LEN - 1);
1034 curproxy->capture_len = CAPTURE_LEN - 1;
1035 }
1036 curproxy->to_log |= LW_COOKIE;
1037 }
1038 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1039 struct cap_hdr *hdr;
1040
1041 if (curproxy == &defproxy) {
1042 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1043 return -1;
1044 }
1045
1046 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1047 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1048 file, linenum, args[0], args[1]);
1049 return -1;
1050 }
1051
1052 hdr = calloc(sizeof(struct cap_hdr), 1);
1053 hdr->next = curproxy->req_cap;
1054 hdr->name = strdup(args[3]);
1055 hdr->namelen = strlen(args[3]);
1056 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001057 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 hdr->index = curproxy->nb_req_cap++;
1059 curproxy->req_cap = hdr;
1060 curproxy->to_log |= LW_REQHDR;
1061 }
1062 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1063 struct cap_hdr *hdr;
1064
1065 if (curproxy == &defproxy) {
1066 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1067 return -1;
1068 }
1069
1070 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1071 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1072 file, linenum, args[0], args[1]);
1073 return -1;
1074 }
1075 hdr = calloc(sizeof(struct cap_hdr), 1);
1076 hdr->next = curproxy->rsp_cap;
1077 hdr->name = strdup(args[3]);
1078 hdr->namelen = strlen(args[3]);
1079 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001080 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081 hdr->index = curproxy->nb_rsp_cap++;
1082 curproxy->rsp_cap = hdr;
1083 curproxy->to_log |= LW_RSPHDR;
1084 }
1085 else {
1086 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1087 file, linenum, args[0]);
1088 return -1;
1089 }
1090 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001092 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1093 return 0;
1094
Willy Tarreaubaaee002006-06-26 02:48:02 +02001095 if (*(args[1]) == 0) {
1096 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1097 file, linenum, args[0]);
1098 return -1;
1099 }
1100 curproxy->conn_retries = atol(args[1]);
1101 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001102 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1103 int pol = ACL_COND_NONE;
1104 struct acl_cond *cond;
1105
1106 if (!strcmp(args[1], "if"))
1107 pol = ACL_COND_IF;
1108 else if (!strcmp(args[1], "unless"))
1109 pol = ACL_COND_UNLESS;
1110
1111 if (pol == ACL_COND_NONE) {
1112 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1113 file, linenum, args[0]);
1114 return -1;
1115 }
1116
1117 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1118 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1119 file, linenum);
1120 return -1;
1121 }
1122 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1123 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001124 else if (!strcmp(args[0], "redirect")) {
1125 int pol = ACL_COND_NONE;
1126 struct acl_cond *cond;
1127 struct redirect_rule *rule;
1128 int cur_arg;
1129 int type = REDIRECT_TYPE_NONE;
1130 int code = 302;
1131 char *destination = NULL;
1132
1133 cur_arg = 1;
1134 while (*(args[cur_arg])) {
1135 if (!strcmp(args[cur_arg], "location")) {
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_LOCATION;
1143 cur_arg++;
1144 destination = args[cur_arg];
1145 }
1146 else if (!strcmp(args[cur_arg], "prefix")) {
1147 if (!*args[cur_arg + 1]) {
1148 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1149 file, linenum, args[0], args[cur_arg]);
1150 return -1;
1151 }
1152
1153 type = REDIRECT_TYPE_PREFIX;
1154 cur_arg++;
1155 destination = args[cur_arg];
1156 }
1157 else if (!strcmp(args[cur_arg],"code")) {
1158 if (!*args[cur_arg + 1]) {
1159 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1160 file, linenum, args[0]);
1161 return -1;
1162 }
1163 cur_arg++;
1164 code = atol(args[cur_arg]);
1165 if (code < 301 || code > 303) {
1166 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1167 file, linenum, args[0], code);
1168 return -1;
1169 }
1170 }
1171 else if (!strcmp(args[cur_arg], "if")) {
1172 pol = ACL_COND_IF;
1173 cur_arg++;
1174 break;
1175 }
1176 else if (!strcmp(args[cur_arg], "unless")) {
1177 pol = ACL_COND_UNLESS;
1178 cur_arg++;
1179 break;
1180 }
1181 else {
1182 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1183 file, linenum, args[0], args[cur_arg]);
1184 return -1;
1185 }
1186 cur_arg++;
1187 }
1188
1189 if (type == REDIRECT_TYPE_NONE) {
1190 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1191 file, linenum, args[0]);
1192 return -1;
1193 }
1194
1195 if (pol == ACL_COND_NONE) {
1196 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1197 file, linenum, args[0]);
1198 return -1;
1199 }
1200
1201 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1202 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1203 file, linenum, args[0]);
1204 return -1;
1205 }
1206
1207 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1208 rule->cond = cond;
1209 rule->rdr_str = strdup(destination);
1210 rule->rdr_len = strlen(destination);
1211 rule->type = type;
1212 rule->code = code;
1213 LIST_INIT(&rule->list);
1214 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1215 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001216 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1217 int pol = ACL_COND_NONE;
1218 struct acl_cond *cond;
1219 struct switching_rule *rule;
1220
1221 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1222 return 0;
1223
1224 if (*(args[1]) == 0) {
1225 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1226 return -1;
1227 }
1228
1229 if (!strcmp(args[2], "if"))
1230 pol = ACL_COND_IF;
1231 else if (!strcmp(args[2], "unless"))
1232 pol = ACL_COND_UNLESS;
1233
1234 if (pol == ACL_COND_NONE) {
1235 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1236 file, linenum, args[0]);
1237 return -1;
1238 }
1239
1240 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1241 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1242 file, linenum);
1243 return -1;
1244 }
1245
1246 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1247 rule->cond = cond;
1248 rule->be.name = strdup(args[1]);
1249 LIST_INIT(&rule->list);
1250 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001252 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001253 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1254 return 0;
1255
Willy Tarreaubaaee002006-06-26 02:48:02 +02001256 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1257 curproxy->uri_auth = NULL; /* we must detach from the default config */
1258
1259 if (*(args[1]) == 0) {
1260 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1261 return -1;
1262 } else if (!strcmp(args[1], "uri")) {
1263 if (*(args[2]) == 0) {
1264 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1265 return -1;
1266 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1267 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1268 return -1;
1269 }
1270 } else if (!strcmp(args[1], "realm")) {
1271 if (*(args[2]) == 0) {
1272 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1273 return -1;
1274 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1275 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1276 return -1;
1277 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001278 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001279 unsigned interval;
1280
1281 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1282 if (err) {
1283 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1284 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001285 return -1;
1286 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1287 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1288 return -1;
1289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001290 } else if (!strcmp(args[1], "auth")) {
1291 if (*(args[2]) == 0) {
1292 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1293 return -1;
1294 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1295 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1296 return -1;
1297 }
1298 } else if (!strcmp(args[1], "scope")) {
1299 if (*(args[2]) == 0) {
1300 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1301 return -1;
1302 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1303 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1304 return -1;
1305 }
1306 } else if (!strcmp(args[1], "enable")) {
1307 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1308 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1309 return -1;
1310 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001311 } else if (!strcmp(args[1], "hide-version")) {
1312 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1313 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1314 return -1;
1315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001316 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001317 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318 file, linenum, args[0]);
1319 return -1;
1320 }
1321 }
1322 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001323 int optnum;
1324
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001325 if (*(args[1]) == '\0') {
1326 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1327 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001328 return -1;
1329 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001330
1331 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1332 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1333 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1334 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001335
1336 if (!inv)
1337 curproxy->options |= cfg_opts[optnum].val;
1338 else
1339 curproxy->options &= ~cfg_opts[optnum].val;
1340
Willy Tarreau13943ab2006-12-31 00:24:10 +01001341 return 0;
1342 }
1343 }
1344
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001345 if (inv) {
1346 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1347 file, linenum, args[1]);
1348 return -1;
1349 }
1350
Willy Tarreau13943ab2006-12-31 00:24:10 +01001351 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001352 /* generate a complete HTTP log */
1353 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1354 else if (!strcmp(args[1], "tcplog"))
1355 /* generate a detailed TCP log */
1356 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357 else if (!strcmp(args[1], "tcpka")) {
1358 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001359 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1360 return 0;
1361
1362 if (curproxy->cap & PR_CAP_FE)
1363 curproxy->options |= PR_O_TCP_CLI_KA;
1364 if (curproxy->cap & PR_CAP_BE)
1365 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001366 }
1367 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001368 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1369 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 /* use HTTP request to check servers' health */
1371 if (curproxy->check_req != NULL) {
1372 free(curproxy->check_req);
1373 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001374 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001375 curproxy->options &= ~PR_O_SMTP_CHK;
1376 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001377 if (!*args[2]) { /* no argument */
1378 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1379 curproxy->check_len = strlen(DEF_CHECK_REQ);
1380 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001381 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001382 curproxy->check_req = (char *)malloc(reqlen);
1383 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1384 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1385 } else { /* more arguments : METHOD URI [HTTP_VER] */
1386 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1387 if (*args[4])
1388 reqlen += strlen(args[4]);
1389 else
1390 reqlen += strlen("HTTP/1.0");
1391
1392 curproxy->check_req = (char *)malloc(reqlen);
1393 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1394 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1395 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001396 }
1397 else if (!strcmp(args[1], "ssl-hello-chk")) {
1398 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001399 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1400 return 0;
1401
Willy Tarreauf3c69202006-07-09 16:42:34 +02001402 if (curproxy->check_req != NULL) {
1403 free(curproxy->check_req);
1404 }
1405 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001406 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001407 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001408 }
Willy Tarreau23677902007-05-08 23:50:35 +02001409 else if (!strcmp(args[1], "smtpchk")) {
1410 /* use SMTP request to check servers' health */
1411 if (curproxy->check_req != NULL) {
1412 free(curproxy->check_req);
1413 }
1414 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")) {
1436 /* insert x-forwarded-for field, but not for the
1437 * IP address listed as an except.
1438 */
1439 if (*(args[2])) {
1440 if (!strcmp(args[2], "except")) {
1441 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1442 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1443 file, linenum, args[0]);
1444 return -1;
1445 }
1446 /* flush useless bits */
1447 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1448 } else {
1449 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1450 file, linenum, args[0]);
1451 return -1;
1452 }
1453 }
1454 curproxy->options |= PR_O_FWDFOR;
1455 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456 else {
1457 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1458 return -1;
1459 }
1460 return 0;
1461 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001462 else if (!strcmp(args[0], "default_backend")) {
1463 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1464 return 0;
1465
1466 if (*(args[1]) == 0) {
1467 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1468 return -1;
1469 }
1470 if (curproxy->defbe.name)
1471 free(curproxy->defbe.name);
1472 curproxy->defbe.name = strdup(args[1]);
1473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001474 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001475 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1476 return 0;
1477
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001478 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1479 file, linenum, args[0]);
1480
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481 /* enable reconnections to dispatch */
1482 curproxy->options |= PR_O_REDISP;
1483 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001484 else if (!strcmp(args[0], "http-check")) {
1485 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1486 return 0;
1487
1488 if (strcmp(args[1], "disable-on-404") == 0) {
1489 /* enable a graceful server shutdown on an HTTP 404 response */
1490 curproxy->options |= PR_O_DISABLE404;
1491 }
1492 else {
1493 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1494 return -1;
1495 }
1496 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001497 else if (!strcmp(args[0], "monitor")) {
1498 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1499 return 0;
1500
1501 if (strcmp(args[1], "fail") == 0) {
1502 /* add a condition to fail monitor requests */
1503 int pol = ACL_COND_NONE;
1504 struct acl_cond *cond;
1505
1506 if (!strcmp(args[2], "if"))
1507 pol = ACL_COND_IF;
1508 else if (!strcmp(args[2], "unless"))
1509 pol = ACL_COND_UNLESS;
1510
1511 if (pol == ACL_COND_NONE) {
1512 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1513 file, linenum, args[0], args[1]);
1514 return -1;
1515 }
1516
1517 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1518 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1519 file, linenum, args[0], args[1]);
1520 return -1;
1521 }
1522 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1523 }
1524 else {
1525 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1526 return -1;
1527 }
1528 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529#ifdef TPROXY
1530 else if (!strcmp(args[0], "transparent")) {
1531 /* enable transparent proxy connections */
1532 curproxy->options |= PR_O_TRANSP;
1533 }
1534#endif
1535 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001536 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1537 return 0;
1538
Willy Tarreaubaaee002006-06-26 02:48:02 +02001539 if (*(args[1]) == 0) {
1540 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1541 return -1;
1542 }
1543 curproxy->maxconn = atol(args[1]);
1544 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001545 else if (!strcmp(args[0], "backlog")) { /* backlog */
1546 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1547 return 0;
1548
1549 if (*(args[1]) == 0) {
1550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1551 return -1;
1552 }
1553 curproxy->backlog = atol(args[1]);
1554 }
Willy Tarreau86034312006-12-29 00:10:33 +01001555 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001556 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1557 return 0;
1558
Willy Tarreau86034312006-12-29 00:10:33 +01001559 if (*(args[1]) == 0) {
1560 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1561 return -1;
1562 }
1563 curproxy->fullconn = atol(args[1]);
1564 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1566 if (*(args[1]) == 0) {
1567 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1568 return -1;
1569 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001570 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1571 if (err) {
1572 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1573 file, linenum, *err);
1574 return -1;
1575 }
1576 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577 }
1578 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1579 if (curproxy == &defproxy) {
1580 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1581 return -1;
1582 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001583 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1584 return 0;
1585
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 if (strchr(args[1], ':') == NULL) {
1587 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1588 return -1;
1589 }
1590 curproxy->dispatch_addr = *str2sa(args[1]);
1591 }
1592 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001593 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1594 return 0;
1595
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001596 memcpy(trash, "error near 'balance'", 19);
1597 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1598 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1599 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001600 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 }
1602 else if (!strcmp(args[0], "server")) { /* server address */
1603 int cur_arg;
1604 char *rport;
1605 char *raddr;
1606 short realport;
1607 int do_check;
1608
1609 if (curproxy == &defproxy) {
1610 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1611 return -1;
1612 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001613 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1614 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615
1616 if (!*args[2]) {
1617 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1618 file, linenum, args[0]);
1619 return -1;
1620 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001621
1622 err = invalid_char(args[1]);
1623 if (err) {
1624 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1625 file, linenum, *err, args[1]);
1626 return -1;
1627 }
1628
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1630 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1631 return -1;
1632 }
1633
1634 /* the servers are linked backwards first */
1635 newsrv->next = curproxy->srv;
1636 curproxy->srv = newsrv;
1637 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001638 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639
1640 LIST_INIT(&newsrv->pendconns);
1641 do_check = 0;
1642 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001643 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644 newsrv->id = strdup(args[1]);
1645
1646 /* several ways to check the port component :
1647 * - IP => port=+0, relative
1648 * - IP: => port=+0, relative
1649 * - IP:N => port=N, absolute
1650 * - IP:+N => port=+N, relative
1651 * - IP:-N => port=-N, relative
1652 */
1653 raddr = strdup(args[2]);
1654 rport = strchr(raddr, ':');
1655 if (rport) {
1656 *rport++ = 0;
1657 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001658 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001659 newsrv->state |= SRV_MAPPORTS;
1660 } else {
1661 realport = 0;
1662 newsrv->state |= SRV_MAPPORTS;
1663 }
1664
1665 newsrv->addr = *str2sa(raddr);
1666 newsrv->addr.sin_port = htons(realport);
1667 free(raddr);
1668
1669 newsrv->curfd = -1; /* no health-check in progress */
1670 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001671 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1672 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 newsrv->rise = DEF_RISETIME;
1674 newsrv->fall = DEF_FALLTIME;
1675 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001676 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001677 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001678 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001679
Willy Tarreaubaaee002006-06-26 02:48:02 +02001680 cur_arg = 3;
1681 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001682 if (!strcmp(args[cur_arg], "id")) {
1683 struct server *target;
1684
1685 if (!*args[cur_arg + 1]) {
1686 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1687 file, linenum, args[cur_arg]);
1688 return -1;
1689 }
1690
1691 newsrv->puid = atol(args[cur_arg + 1]);
1692
1693 if (newsrv->puid< 1001) {
1694 Alert("parsing [%s:%d]: custom id has to be > 1000",
1695 file, linenum);
1696 return -1;
1697 }
1698
1699 for (target = proxy->srv; target; target = target->next)
1700 if (newsrv != target && newsrv->puid == target->puid) {
1701 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1702 file, linenum, newsrv->id, target->id);
1703 return -1;
1704 }
1705 cur_arg += 2;
1706 }
1707 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 newsrv->cookie = strdup(args[cur_arg + 1]);
1709 newsrv->cklen = strlen(args[cur_arg + 1]);
1710 cur_arg += 2;
1711 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001712 else if (!strcmp(args[cur_arg], "redir")) {
1713 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1714 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1715 cur_arg += 2;
1716 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001717 else if (!strcmp(args[cur_arg], "rise")) {
1718 newsrv->rise = atol(args[cur_arg + 1]);
1719 newsrv->health = newsrv->rise;
1720 cur_arg += 2;
1721 }
1722 else if (!strcmp(args[cur_arg], "fall")) {
1723 newsrv->fall = atol(args[cur_arg + 1]);
1724 cur_arg += 2;
1725 }
1726 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001727 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1728 if (err) {
1729 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1730 file, linenum, *err, newsrv->id);
1731 return -1;
1732 }
1733 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001734 cur_arg += 2;
1735 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001736 else if (!strcmp(args[cur_arg], "fastinter")) {
1737 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1738 if (err) {
1739 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1740 file, linenum, *err, newsrv->id);
1741 return -1;
1742 }
1743 newsrv->fastinter = val;
1744 cur_arg += 2;
1745 }
1746 else if (!strcmp(args[cur_arg], "downinter")) {
1747 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1748 if (err) {
1749 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1750 file, linenum, *err, newsrv->id);
1751 return -1;
1752 }
1753 newsrv->downinter = val;
1754 cur_arg += 2;
1755 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001756 else if (!strcmp(args[cur_arg], "addr")) {
1757 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001758 cur_arg += 2;
1759 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001760 else if (!strcmp(args[cur_arg], "port")) {
1761 newsrv->check_port = atol(args[cur_arg + 1]);
1762 cur_arg += 2;
1763 }
1764 else if (!strcmp(args[cur_arg], "backup")) {
1765 newsrv->state |= SRV_BACKUP;
1766 cur_arg ++;
1767 }
1768 else if (!strcmp(args[cur_arg], "weight")) {
1769 int w;
1770 w = atol(args[cur_arg + 1]);
1771 if (w < 1 || w > 256) {
1772 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1773 file, linenum, newsrv->id, w);
1774 return -1;
1775 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001776 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777 cur_arg += 2;
1778 }
1779 else if (!strcmp(args[cur_arg], "minconn")) {
1780 newsrv->minconn = atol(args[cur_arg + 1]);
1781 cur_arg += 2;
1782 }
1783 else if (!strcmp(args[cur_arg], "maxconn")) {
1784 newsrv->maxconn = atol(args[cur_arg + 1]);
1785 cur_arg += 2;
1786 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001787 else if (!strcmp(args[cur_arg], "maxqueue")) {
1788 newsrv->maxqueue = atol(args[cur_arg + 1]);
1789 cur_arg += 2;
1790 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001791 else if (!strcmp(args[cur_arg], "slowstart")) {
1792 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001793 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001794 if (err) {
1795 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1796 file, linenum, *err, newsrv->id);
1797 return -1;
1798 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001799 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001800 cur_arg += 2;
1801 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001802 else if (!strcmp(args[cur_arg], "track")) {
1803
1804 if (!*args[cur_arg + 1]) {
1805 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1806 file, linenum);
1807 return -1;
1808 }
1809
1810 newsrv->trackit = strdup(args[cur_arg + 1]);
1811
1812 cur_arg += 2;
1813 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001814 else if (!strcmp(args[cur_arg], "check")) {
1815 global.maxsock++;
1816 do_check = 1;
1817 cur_arg += 1;
1818 }
1819 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1820 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001821#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001822 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1823 file, linenum, "source", "usesrc");
1824#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001825 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1826 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001827#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001828 return -1;
1829 }
1830 newsrv->state |= SRV_BIND_SRC;
1831 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1832 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001833 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001834#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1835#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001836 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001837 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1838 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001839 return -1;
1840 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001841#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001842 if (!*args[cur_arg + 1]) {
1843 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1844 file, linenum, "usesrc");
1845 return -1;
1846 }
1847 if (!strcmp(args[cur_arg + 1], "client")) {
1848 newsrv->state |= SRV_TPROXY_CLI;
1849 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1850 newsrv->state |= SRV_TPROXY_CIP;
1851 } else {
1852 newsrv->state |= SRV_TPROXY_ADDR;
1853 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1854 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001855 global.last_checks |= LSTCHK_NETADM;
1856#if !defined(CONFIG_HAP_LINUX_TPROXY)
1857 global.last_checks |= LSTCHK_CTTPROXY;
1858#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001859 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001860#else /* no TPROXY support */
1861 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001862 file, linenum, "usesrc");
1863 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001864#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001865 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001866 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001867 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1868 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1869 file, linenum, "usesrc", "source");
1870 return -1;
1871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001872 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001873 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 +02001874 file, linenum, newsrv->id);
1875 return -1;
1876 }
1877 }
1878
1879 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001880 if (newsrv->trackit) {
1881 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1882 file, linenum);
1883 return -1;
1884 }
1885
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001886 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1887 newsrv->check_port = newsrv->check_addr.sin_port;
1888
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1890 newsrv->check_port = realport; /* by default */
1891 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001892 /* not yet valid, because no port was set on
1893 * the server either. We'll check if we have
1894 * a known port on the first listener.
1895 */
1896 struct listener *l;
1897 l = curproxy->listen;
1898 if (l) {
1899 int port;
1900 port = (l->addr.ss_family == AF_INET6)
1901 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1902 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1903 newsrv->check_port = port;
1904 }
1905 }
1906 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1908 file, linenum, newsrv->id);
1909 return -1;
1910 }
1911 newsrv->state |= SRV_CHECKED;
1912 }
1913
1914 if (newsrv->state & SRV_BACKUP)
1915 curproxy->srv_bck++;
1916 else
1917 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001918
1919 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 }
1921 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001922 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 int facility;
1924
1925 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1926 curproxy->logfac1 = global.logfac1;
1927 curproxy->logsrv1 = global.logsrv1;
1928 curproxy->loglev1 = global.loglev1;
1929 curproxy->logfac2 = global.logfac2;
1930 curproxy->logsrv2 = global.logsrv2;
1931 curproxy->loglev2 = global.loglev2;
1932 }
1933 else if (*(args[1]) && *(args[2])) {
1934 int level;
1935
1936 facility = get_log_facility(args[2]);
1937 if (facility < 0) {
1938 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1939 exit(1);
1940 }
1941
1942 level = 7; /* max syslog level = debug */
1943 if (*(args[3])) {
1944 level = get_log_level(args[3]);
1945 if (level < 0) {
1946 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1947 exit(1);
1948 }
1949 }
1950
Robert Tsai81ae1952007-12-05 10:47:29 +01001951 if (args[1][0] == '/') {
1952 logsrv.u.addr.sa_family = AF_UNIX;
1953 logsrv.u.un = *str2sun(args[1]);
1954 } else {
1955 logsrv.u.addr.sa_family = AF_INET;
1956 logsrv.u.in = *str2sa(args[1]);
1957 if (!logsrv.u.in.sin_port) {
1958 logsrv.u.in.sin_port =
1959 htons(SYSLOG_PORT);
1960 }
1961 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962
1963 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001964 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001965 curproxy->logfac1 = facility;
1966 curproxy->loglev1 = level;
1967 }
1968 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001969 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001970 curproxy->logfac2 = facility;
1971 curproxy->loglev2 = level;
1972 }
1973 else {
1974 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1975 return -1;
1976 }
1977 }
1978 else {
1979 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1980 file, linenum);
1981 return -1;
1982 }
1983 }
1984 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001985 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1986 return 0;
1987
Willy Tarreaubaaee002006-06-26 02:48:02 +02001988 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001989#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001990 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1991 file, linenum, "source", "usesrc");
1992#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001993 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1994 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001995#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001996 return -1;
1997 }
1998
1999 curproxy->source_addr = *str2sa(args[1]);
2000 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01002001 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002002#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2003#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002004 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2005 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2006 file, linenum, "usesrc");
2007 return -1;
2008 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002009#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002010 if (!*args[3]) {
2011 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2012 file, linenum, "usesrc");
2013 return -1;
2014 }
2015
2016 if (!strcmp(args[3], "client")) {
2017 curproxy->options |= PR_O_TPXY_CLI;
2018 } else if (!strcmp(args[3], "clientip")) {
2019 curproxy->options |= PR_O_TPXY_CIP;
2020 } else {
2021 curproxy->options |= PR_O_TPXY_ADDR;
2022 curproxy->tproxy_addr = *str2sa(args[3]);
2023 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002024 global.last_checks |= LSTCHK_NETADM;
2025#if !defined(CONFIG_HAP_LINUX_TPROXY)
2026 global.last_checks |= LSTCHK_CTTPROXY;
2027#endif
2028#else /* no TPROXY support */
2029 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002030 file, linenum, "usesrc");
2031 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002032#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002034 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002035 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2036 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2037 file, linenum, "usesrc", "source");
2038 return -1;
2039 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002040 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2041 regex_t *preg;
2042 if (curproxy == &defproxy) {
2043 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2044 return -1;
2045 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002046 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2047 return 0;
2048
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049 if (*(args[1]) == 0 || *(args[2]) == 0) {
2050 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2051 file, linenum, args[0]);
2052 return -1;
2053 }
2054
2055 preg = calloc(1, sizeof(regex_t));
2056 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2057 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2058 return -1;
2059 }
2060
2061 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2062 if (err) {
2063 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2064 file, linenum, *err);
2065 return -1;
2066 }
2067 }
2068 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2069 regex_t *preg;
2070 if (curproxy == &defproxy) {
2071 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2072 return -1;
2073 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002074 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2075 return 0;
2076
Willy Tarreaubaaee002006-06-26 02:48:02 +02002077 if (*(args[1]) == 0) {
2078 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2079 return -1;
2080 }
2081
2082 preg = calloc(1, sizeof(regex_t));
2083 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2084 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2085 return -1;
2086 }
2087
2088 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2089 }
2090 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2091 regex_t *preg;
2092 if (curproxy == &defproxy) {
2093 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2094 return -1;
2095 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002096 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2097 return 0;
2098
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 if (*(args[1]) == 0) {
2100 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2101 return -1;
2102 }
2103
2104 preg = calloc(1, sizeof(regex_t));
2105 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2106 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2107 return -1;
2108 }
2109
2110 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2111 }
2112 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2113 regex_t *preg;
2114 if (curproxy == &defproxy) {
2115 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2116 return -1;
2117 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002118 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2119 return 0;
2120
Willy Tarreaubaaee002006-06-26 02:48:02 +02002121 if (*(args[1]) == 0) {
2122 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2123 return -1;
2124 }
2125
2126 preg = calloc(1, sizeof(regex_t));
2127 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2128 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2129 return -1;
2130 }
2131
2132 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2133 }
2134 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2135 regex_t *preg;
2136 if (curproxy == &defproxy) {
2137 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2138 return -1;
2139 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002140 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2141 return 0;
2142
Willy Tarreaubaaee002006-06-26 02:48:02 +02002143 if (*(args[1]) == 0) {
2144 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2145 return -1;
2146 }
2147
2148 preg = calloc(1, sizeof(regex_t));
2149 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2150 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2151 return -1;
2152 }
2153
2154 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2155 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002156 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2157 regex_t *preg;
2158 if (curproxy == &defproxy) {
2159 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2160 return -1;
2161 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002162 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2163 return 0;
2164
Willy Tarreaub8750a82006-09-03 09:56:00 +02002165 if (*(args[1]) == 0) {
2166 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2167 return -1;
2168 }
2169
2170 preg = calloc(1, sizeof(regex_t));
2171 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2172 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2173 return -1;
2174 }
2175
2176 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2177 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002178 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2179 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002180 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002181 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2182 return -1;
2183 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002184 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2185 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002186
Willy Tarreau977b8e42006-12-29 14:19:17 +01002187 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002188 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2189 file, linenum, args[0]);
2190 return -1;
2191 }
2192
2193 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002194 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002195 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2196 }
2197
2198 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2199 }
2200 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2201 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002202 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002203 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2204 return -1;
2205 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002206 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2207 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002208
Willy Tarreau977b8e42006-12-29 14:19:17 +01002209 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002210 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2211 file, linenum, args[0]);
2212 return -1;
2213 }
2214
2215 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002216 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002217 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2218 }
2219
2220 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002222 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2223 regex_t *preg;
2224 if (curproxy == &defproxy) {
2225 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2226 return -1;
2227 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002228 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2229 return 0;
2230
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 if (*(args[1]) == 0 || *(args[2]) == 0) {
2232 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2233 file, linenum, args[0]);
2234 return -1;
2235 }
2236
2237 preg = calloc(1, sizeof(regex_t));
2238 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2239 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2240 return -1;
2241 }
2242
2243 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2244 if (err) {
2245 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2246 file, linenum, *err);
2247 return -1;
2248 }
2249 }
2250 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2251 regex_t *preg;
2252 if (curproxy == &defproxy) {
2253 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2254 return -1;
2255 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002256 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2257 return 0;
2258
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 if (*(args[1]) == 0) {
2260 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2261 return -1;
2262 }
2263
2264 preg = calloc(1, sizeof(regex_t));
2265 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2266 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2267 return -1;
2268 }
2269
2270 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2271 }
2272 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2273 regex_t *preg;
2274 if (curproxy == &defproxy) {
2275 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2276 return -1;
2277 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002278 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2279 return 0;
2280
Willy Tarreaubaaee002006-06-26 02:48:02 +02002281 if (*(args[1]) == 0) {
2282 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2283 return -1;
2284 }
2285
2286 preg = calloc(1, sizeof(regex_t));
2287 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2288 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2289 return -1;
2290 }
2291
2292 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2293 }
2294 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2295 regex_t *preg;
2296 if (curproxy == &defproxy) {
2297 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2298 return -1;
2299 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002300 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2301 return 0;
2302
Willy Tarreaubaaee002006-06-26 02:48:02 +02002303 if (*(args[1]) == 0) {
2304 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2305 return -1;
2306 }
2307
2308 preg = calloc(1, sizeof(regex_t));
2309 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2310 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2311 return -1;
2312 }
2313
2314 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2315 }
2316 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2317 regex_t *preg;
2318 if (curproxy == &defproxy) {
2319 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2320 return -1;
2321 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002322 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2323 return 0;
2324
Willy Tarreaubaaee002006-06-26 02:48:02 +02002325 if (*(args[1]) == 0) {
2326 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2327 return -1;
2328 }
2329
2330 preg = calloc(1, sizeof(regex_t));
2331 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2332 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2333 return -1;
2334 }
2335
2336 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2337 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002338 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2339 regex_t *preg;
2340 if (curproxy == &defproxy) {
2341 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2342 return -1;
2343 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002344 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2345 return 0;
2346
Willy Tarreaub8750a82006-09-03 09:56:00 +02002347 if (*(args[1]) == 0) {
2348 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2349 return -1;
2350 }
2351
2352 preg = calloc(1, sizeof(regex_t));
2353 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2354 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2355 return -1;
2356 }
2357
2358 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2359 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2361 if (curproxy == &defproxy) {
2362 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2363 return -1;
2364 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002365 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2366 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002367
2368 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2369 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2370 return 0;
2371 }
2372
2373 if (*(args[1]) == 0) {
2374 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2375 return -1;
2376 }
2377
2378 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2379 }
2380 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2381 regex_t *preg;
2382
2383 if (*(args[1]) == 0 || *(args[2]) == 0) {
2384 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2385 file, linenum, args[0]);
2386 return -1;
2387 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002388 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2389 return 0;
2390
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 preg = calloc(1, sizeof(regex_t));
2392 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2393 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2394 return -1;
2395 }
2396
2397 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2398 if (err) {
2399 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2400 file, linenum, *err);
2401 return -1;
2402 }
2403 }
2404 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2405 regex_t *preg;
2406 if (curproxy == &defproxy) {
2407 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2408 return -1;
2409 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002410 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2411 return 0;
2412
Willy Tarreaubaaee002006-06-26 02:48:02 +02002413 if (*(args[1]) == 0) {
2414 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2415 return -1;
2416 }
2417
2418 preg = calloc(1, sizeof(regex_t));
2419 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2420 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2421 return -1;
2422 }
2423
2424 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2425 if (err) {
2426 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2427 file, linenum, *err);
2428 return -1;
2429 }
2430 }
2431 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2432 regex_t *preg;
2433 if (curproxy == &defproxy) {
2434 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2435 return -1;
2436 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002437 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2438 return 0;
2439
Willy Tarreaubaaee002006-06-26 02:48:02 +02002440 if (*(args[1]) == 0) {
2441 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2442 return -1;
2443 }
2444
2445 preg = calloc(1, sizeof(regex_t));
2446 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2447 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2448 return -1;
2449 }
2450
2451 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2452 if (err) {
2453 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2454 file, linenum, *err);
2455 return -1;
2456 }
2457 }
2458 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2459 regex_t *preg;
2460 if (curproxy == &defproxy) {
2461 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2462 return -1;
2463 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002464 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2465 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466
2467 if (*(args[1]) == 0 || *(args[2]) == 0) {
2468 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2469 file, linenum, args[0]);
2470 return -1;
2471 }
2472
2473 preg = calloc(1, sizeof(regex_t));
2474 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2475 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2476 return -1;
2477 }
2478
2479 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2480 if (err) {
2481 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2482 file, linenum, *err);
2483 return -1;
2484 }
2485 }
2486 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2487 regex_t *preg;
2488 if (curproxy == &defproxy) {
2489 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2490 return -1;
2491 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002492 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2493 return 0;
2494
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 if (*(args[1]) == 0) {
2496 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2497 return -1;
2498 }
2499
2500 preg = calloc(1, sizeof(regex_t));
2501 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2502 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2503 return -1;
2504 }
2505
2506 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2507 if (err) {
2508 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2509 file, linenum, *err);
2510 return -1;
2511 }
2512 }
2513 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2514 regex_t *preg;
2515 if (curproxy == &defproxy) {
2516 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2517 return -1;
2518 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002519 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2520 return 0;
2521
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522 if (*(args[1]) == 0) {
2523 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2524 return -1;
2525 }
2526
2527 preg = calloc(1, sizeof(regex_t));
2528 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2529 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2530 return -1;
2531 }
2532
2533 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2534 if (err) {
2535 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2536 file, linenum, *err);
2537 return -1;
2538 }
2539 }
2540 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2541 if (curproxy == &defproxy) {
2542 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2543 return -1;
2544 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002545 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2546 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547
2548 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2549 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2550 return 0;
2551 }
2552
2553 if (*(args[1]) == 0) {
2554 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2555 return -1;
2556 }
2557
2558 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2559 }
2560 else if (!strcmp(args[0], "errorloc") ||
2561 !strcmp(args[0], "errorloc302") ||
2562 !strcmp(args[0], "errorloc303")) { /* error location */
2563 int errnum, errlen;
2564 char *err;
2565
Willy Tarreau977b8e42006-12-29 14:19:17 +01002566 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2567 return 0;
2568
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002570 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 return -1;
2572 }
2573
2574 errnum = atol(args[1]);
2575 if (!strcmp(args[0], "errorloc303")) {
2576 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2577 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2578 } else {
2579 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2580 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2581 }
2582
Willy Tarreau0f772532006-12-23 20:51:41 +01002583 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2584 if (http_err_codes[rc] == errnum) {
2585 if (curproxy->errmsg[rc].str)
2586 free(curproxy->errmsg[rc].str);
2587 curproxy->errmsg[rc].str = err;
2588 curproxy->errmsg[rc].len = errlen;
2589 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002592
2593 if (rc >= HTTP_ERR_SIZE) {
2594 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2595 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 free(err);
2597 }
2598 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002599 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2600 int errnum, errlen, fd;
2601 char *err;
2602 struct stat stat;
2603
2604 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2605 return 0;
2606
2607 if (*(args[2]) == 0) {
2608 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2609 return -1;
2610 }
2611
2612 fd = open(args[2], O_RDONLY);
2613 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2614 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2615 file, linenum, args[2], args[1]);
2616 if (fd >= 0)
2617 close(fd);
2618 return -1;
2619 }
2620
2621 if (stat.st_size <= BUFSIZE) {
2622 errlen = stat.st_size;
2623 } else {
2624 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2625 file, linenum, args[2], BUFSIZE);
2626 errlen = BUFSIZE;
2627 }
2628
2629 err = malloc(errlen); /* malloc() must succeed during parsing */
2630 errnum = read(fd, err, errlen);
2631 if (errnum != errlen) {
2632 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2633 file, linenum, args[2], args[1]);
2634 close(fd);
2635 free(err);
2636 return -1;
2637 }
2638 close(fd);
2639
2640 errnum = atol(args[1]);
2641 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2642 if (http_err_codes[rc] == errnum) {
2643 if (curproxy->errmsg[rc].str)
2644 free(curproxy->errmsg[rc].str);
2645 curproxy->errmsg[rc].str = err;
2646 curproxy->errmsg[rc].len = errlen;
2647 break;
2648 }
2649 }
2650
2651 if (rc >= HTTP_ERR_SIZE) {
2652 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2653 file, linenum, errnum);
2654 free(err);
2655 }
2656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002658 struct cfg_kw_list *kwl;
2659 int index;
2660
2661 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2662 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2663 if (kwl->kw[index].section != CFG_LISTEN)
2664 continue;
2665 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2666 /* prepare error message just in case */
2667 snprintf(trash, sizeof(trash),
2668 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002669 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2670 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002671 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2672 return -1;
2673 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002674 else if (rc > 0) {
2675 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2676 return 0;
2677 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002678 return 0;
2679 }
2680 }
2681 }
2682
Willy Tarreau6daf3432008-01-22 16:44:08 +01002683 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 return -1;
2685 }
2686 return 0;
2687}
2688
2689
2690/*
2691 * This function reads and parses the configuration file given in the argument.
2692 * returns 0 if OK, -1 if error.
2693 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002694int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002696 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002697 FILE *f;
2698 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 int confsect = CFG_NONE;
2701
2702 struct proxy *curproxy = NULL;
2703 struct server *newsrv = NULL;
2704
2705 if ((f=fopen(file,"r")) == NULL)
2706 return -1;
2707
2708 init_default_instance();
2709
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002710 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002711 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002712 char *end;
2713 char *args[MAX_LINE_ARGS + 1];
2714 char *line = thisline;
2715
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716 linenum++;
2717
2718 end = line + strlen(line);
2719
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002720 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2721 /* Check if we reached the limit and the last char is not \n.
2722 * Watch out for the last line without the terminating '\n'!
2723 */
2724 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2725 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002726 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002727 }
2728
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002730 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 line++;
2732
2733 arg = 0;
2734 args[arg] = line;
2735
2736 while (*line && arg < MAX_LINE_ARGS) {
2737 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2738 * C equivalent value. Other combinations left unchanged (eg: \1).
2739 */
2740 if (*line == '\\') {
2741 int skip = 0;
2742 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2743 *line = line[1];
2744 skip = 1;
2745 }
2746 else if (line[1] == 'r') {
2747 *line = '\r';
2748 skip = 1;
2749 }
2750 else if (line[1] == 'n') {
2751 *line = '\n';
2752 skip = 1;
2753 }
2754 else if (line[1] == 't') {
2755 *line = '\t';
2756 skip = 1;
2757 }
2758 else if (line[1] == 'x') {
2759 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2760 unsigned char hex1, hex2;
2761 hex1 = toupper(line[2]) - '0';
2762 hex2 = toupper(line[3]) - '0';
2763 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2764 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2765 *line = (hex1<<4) + hex2;
2766 skip = 3;
2767 }
2768 else {
2769 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002770 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002771 }
2772 }
2773 if (skip) {
2774 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2775 end -= skip;
2776 }
2777 line++;
2778 }
2779 else if (*line == '#' || *line == '\n' || *line == '\r') {
2780 /* end of string, end of loop */
2781 *line = 0;
2782 break;
2783 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002784 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002786 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002787 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002788 line++;
2789 args[++arg] = line;
2790 }
2791 else {
2792 line++;
2793 }
2794 }
2795
2796 /* empty line */
2797 if (!**args)
2798 continue;
2799
Willy Tarreau540abe42007-05-02 20:50:16 +02002800 /* zero out remaining args and ensure that at least one entry
2801 * is zeroed out.
2802 */
2803 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804 args[arg] = line;
2805 }
2806
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002807 if (!strcmp(args[0], "no")) {
2808 inv = 1;
2809 for (arg=0; *args[arg+1]; arg++)
2810 args[arg] = args[arg+1]; // shift args after inversion
2811 }
2812
2813 if (inv && strcmp(args[0], "option")) {
2814 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002815 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002816 }
2817
Willy Tarreau977b8e42006-12-29 14:19:17 +01002818 if (!strcmp(args[0], "listen") ||
2819 !strcmp(args[0], "frontend") ||
2820 !strcmp(args[0], "backend") ||
2821 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002822 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823 confsect = CFG_LISTEN;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002824 if (cursection)
2825 free(cursection);
2826 cursection = strdup(args[0]);
2827 }
2828 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002829 confsect = CFG_GLOBAL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002830 if (cursection)
2831 free(cursection);
2832 cursection = strdup(args[0]);
2833 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834 /* else it's a section keyword */
2835
2836 switch (confsect) {
2837 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002838 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002839 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 break;
2841 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002842 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002843 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002844 break;
2845 default:
2846 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002847 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002848 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01002850 if (cursection)
2851 free(cursection);
2852 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002853 fclose(f);
2854
2855 /*
2856 * Now, check for the integrity of all that we have collected.
2857 */
2858
2859 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002860 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861
2862 if ((curproxy = proxy) == NULL) {
2863 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2864 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002865 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002866 }
2867
2868 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002869 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002870 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002871
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 if (curproxy->state == PR_STSTOPPED) {
2873 curproxy = curproxy->next;
2874 continue;
2875 }
2876
Willy Tarreau977b8e42006-12-29 14:19:17 +01002877 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2878 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 +01002879 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002880 cfgerr++;
2881 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002882 else if (curproxy->cap & PR_CAP_BE &&
2883 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002884 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002885 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002886 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2887 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 +01002888 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002889 cfgerr++;
2890 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002891
Willy Tarreau31682232007-11-29 15:38:04 +01002892 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002893 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002894 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002895 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 cfgerr++;
2897 }
2898#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2899 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002900 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002901 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002902 cfgerr++;
2903 }
2904#endif
2905 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002906 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002907 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002908 }
2909 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002910
2911 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002913 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002914 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002917 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002918 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 }
2920 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002921 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002922 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002923 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002924 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002925 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002926 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002927 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002928 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002929 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2930 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002931
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002932 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002933 file, proxy_type_str(curproxy), curproxy->id);
2934 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002935 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002936
2937 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2938 if ((newsrv = curproxy->srv) != NULL) {
2939 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2940 file, proxy_type_str(curproxy), curproxy->id);
2941 }
2942 }
2943
2944 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002945 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2946 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2947 file, curproxy->id);
2948 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002949 }
2950 }
2951
Willy Tarreau82936582007-11-30 15:20:09 +01002952 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2953 curproxy->options &= ~PR_O_DISABLE404;
2954 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2955 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2956 }
2957
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002958 /* if a default backend was specified, let's find it */
2959 if (curproxy->defbe.name) {
2960 struct proxy *target;
2961
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002962 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2963 if (!target) {
2964 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2965 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002966 cfgerr++;
2967 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002968 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2969 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002970 } else {
2971 free(curproxy->defbe.name);
2972 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973 }
2974 }
2975
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002976 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002977 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2978 /* map jump target for ACT_SETBE in req_rep chain */
2979 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002980 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002981 struct proxy *target;
2982
Willy Tarreaua496b602006-12-17 23:15:24 +01002983 if (exp->action != ACT_SETBE)
2984 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002985
2986 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2987 if (!target) {
2988 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2989 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002990 cfgerr++;
2991 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002992 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2993 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002994 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002995 } else {
2996 free((void *)exp->replace);
2997 exp->replace = (const char *)target;
2998 }
2999 }
3000 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003001
3002 /* find the target proxy for 'use_backend' rules */
3003 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003004 struct proxy *target;
3005
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003006 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003007
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003008 if (!target) {
3009 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3010 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003011 cfgerr++;
3012 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003013 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3014 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003015 cfgerr++;
3016 } else {
3017 free((void *)rule->be.name);
3018 rule->be.backend = target;
3019 }
3020 }
3021
Willy Tarreau2738a142006-07-08 17:28:09 +02003022 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003023 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003024 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003025 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003026 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003027 " | While not properly invalid, you will certainly encounter various problems\n"
3028 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003029 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003030 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003031 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003032
Willy Tarreau1fa31262007-12-03 00:36:16 +01003033 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3034 * We must still support older configurations, so let's find out whether those
3035 * parameters have been set or must be copied from contimeouts.
3036 */
3037 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003038 if (!curproxy->timeout.tarpit ||
3039 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003040 /* tarpit timeout not set. We search in the following order:
3041 * default.tarpit, curr.connect, default.connect.
3042 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003043 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003044 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003045 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003046 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003047 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003048 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003049 }
3050 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003051 (!curproxy->timeout.queue ||
3052 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003053 /* queue timeout not set. We search in the following order:
3054 * default.queue, curr.connect, default.connect.
3055 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003056 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003057 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003058 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003059 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003060 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003061 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003062 }
3063 }
3064
Willy Tarreauf3c69202006-07-09 16:42:34 +02003065 if (curproxy->options & PR_O_SSL3_CHK) {
3066 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3067 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3068 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3069 }
3070
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003071 /* The small pools required for the capture lists */
3072 if (curproxy->nb_req_cap)
3073 curproxy->req_cap_pool = create_pool("ptrcap",
3074 curproxy->nb_req_cap * sizeof(char *),
3075 MEM_F_SHARED);
3076 if (curproxy->nb_rsp_cap)
3077 curproxy->rsp_cap_pool = create_pool("ptrcap",
3078 curproxy->nb_rsp_cap * sizeof(char *),
3079 MEM_F_SHARED);
3080
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003081 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3082 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3083 MEM_F_SHARED);
3084
Willy Tarreau86034312006-12-29 00:10:33 +01003085 /* for backwards compatibility with "listen" instances, if
3086 * fullconn is not set but maxconn is set, then maxconn
3087 * is used.
3088 */
3089 if (!curproxy->fullconn)
3090 curproxy->fullconn = curproxy->maxconn;
3091
Willy Tarreaubaaee002006-06-26 02:48:02 +02003092 /* first, we will invert the servers list order */
3093 newsrv = NULL;
3094 while (curproxy->srv) {
3095 struct server *next;
3096
3097 next = curproxy->srv->next;
3098 curproxy->srv->next = newsrv;
3099 newsrv = curproxy->srv;
3100 if (!next)
3101 break;
3102 curproxy->srv = next;
3103 }
3104
Willy Tarreau20697042007-11-15 23:26:18 +01003105 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003106 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107
Willy Tarreaub625a082007-11-26 01:15:43 +01003108 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003109 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003110 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003111 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3112 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003113 else
3114 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115
3116 if (curproxy->options & PR_O_LOGASAP)
3117 curproxy->to_log &= ~LW_BYTES;
3118
Willy Tarreaubaaee002006-06-26 02:48:02 +02003119 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003120 * ensure that we're not cross-dressing a TCP server into HTTP.
3121 */
3122 newsrv = curproxy->srv;
3123 while (newsrv != NULL) {
3124 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3125 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3126 file, proxy_type_str(curproxy), curproxy->id, linenum);
3127 goto err;
3128 }
3129 newsrv = newsrv->next;
3130 }
3131
3132 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 * If this server supports a maxconn parameter, it needs a dedicated
3134 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003135 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 */
3137 newsrv = curproxy->srv;
3138 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003139 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003140 /* Only 'minconn' was specified, or it was higher than or equal
3141 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3142 * this will avoid further useless expensive computations.
3143 */
3144 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003145 } else if (newsrv->maxconn && !newsrv->minconn) {
3146 /* minconn was not specified, so we set it to maxconn */
3147 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003148 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3149 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003150 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003151 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 }
3153
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003154 if (newsrv->trackit) {
3155 struct proxy *px;
3156 struct server *srv;
3157 char *pname, *sname;
3158
3159 pname = newsrv->trackit;
3160 sname = strrchr(pname, '/');
3161
3162 if (sname)
3163 *sname++ = '\0';
3164 else {
3165 sname = pname;
3166 pname = NULL;
3167 }
3168
3169 if (pname) {
3170 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3171 if (!px) {
3172 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3173 file, proxy_type_str(curproxy), curproxy->id,
3174 newsrv->id, pname);
3175 return -1;
3176 }
3177 } else
3178 px = curproxy;
3179
3180 srv = findserver(px, sname);
3181 if (!srv) {
3182 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3183 file, proxy_type_str(curproxy), curproxy->id,
3184 newsrv->id, sname);
3185 return -1;
3186 }
3187
3188 if (!(srv->state & SRV_CHECKED)) {
3189 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3190 "tracing as it does not have checks enabled.\n",
3191 file, proxy_type_str(curproxy), curproxy->id,
3192 newsrv->id, px->id, srv->id);
3193 return -1;
3194 }
3195
3196 if (curproxy != px &&
3197 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3198 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3199 "tracing: disable-on-404 option inconsistency.\n",
3200 file, proxy_type_str(curproxy), curproxy->id,
3201 newsrv->id, px->id, srv->id);
3202 return -1;
3203 }
3204
3205 newsrv->tracked = srv;
3206 newsrv->tracknext = srv->tracknext;
3207 srv->tracknext = newsrv;
3208
3209 free(newsrv->trackit);
3210 }
3211
Willy Tarreaubaaee002006-06-26 02:48:02 +02003212 newsrv = newsrv->next;
3213 }
3214
Willy Tarreaue6b98942007-10-29 01:09:36 +01003215 /* adjust this proxy's listeners */
3216 listener = curproxy->listen;
3217 while (listener) {
3218 if (curproxy->options & PR_O_TCP_NOLING)
3219 listener->options |= LI_O_NOLINGER;
3220 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003221 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003222 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003223 listener->accept = event_accept;
3224 listener->private = curproxy;
3225
3226 listener = listener->next;
3227 }
3228
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 curproxy = curproxy->next;
3230 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003231
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 if (cfgerr > 0) {
3233 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003234 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003236
3237 /*
3238 * Recount currently required checks.
3239 */
3240
3241 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3242 int optnum;
3243
3244 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3245 if (!(curproxy->options & cfg_opts[optnum].val))
3246 continue;
3247
3248 global.last_checks |= cfg_opts[optnum].checks;
3249 }
3250 }
3251
Willy Tarreau6daf3432008-01-22 16:44:08 +01003252 if (cursection)
3253 free(cursection);
3254 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003255 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003256
3257 err:
3258 if (cursection)
3259 free(cursection);
3260 cursection = NULL;
3261 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003262}
3263
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003264/*
3265 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3266 * parsing sessions.
3267 */
3268void cfg_register_keywords(struct cfg_kw_list *kwl)
3269{
3270 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3271}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003273/*
3274 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3275 */
3276void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3277{
3278 LIST_DEL(&kwl->list);
3279 LIST_INIT(&kwl->list);
3280}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281
3282/*
3283 * Local variables:
3284 * c-indent-level: 8
3285 * c-basic-offset: 8
3286 * End:
3287 */