blob: 8afc69c9c75463bdb352ff7486846ff2afd505ec [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
124/*
125 * converts <str> to a list of listeners which are dynamically allocated.
126 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
127 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
128 * - <port> is a numerical port from 1 to 65535 ;
129 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
130 * This can be repeated as many times as necessary, separated by a coma.
131 * The <tail> argument is a pointer to a current list which should be appended
132 * to the tail of the new list. The pointer to the new list is returned.
133 */
134static struct listener *str2listener(char *str, struct listener *tail)
135{
136 struct listener *l;
137 char *c, *next, *range, *dupstr;
138 int port, end;
139
140 next = dupstr = strdup(str);
141
142 while (next && *next) {
143 struct sockaddr_storage ss;
144
145 str = next;
146 /* 1) look for the end of the first address */
147 if ((next = strrchr(str, ',')) != NULL) {
148 *next++ = 0;
149 }
150
151 /* 2) look for the addr/port delimiter, it's the last colon. */
152 if ((range = strrchr(str, ':')) == NULL) {
153 Alert("Missing port number: '%s'\n", str);
154 goto fail;
155 }
156
157 *range++ = 0;
158
159 if (strrchr(str, ':') != NULL) {
160 /* IPv6 address contains ':' */
161 memset(&ss, 0, sizeof(ss));
162 ss.ss_family = AF_INET6;
163
164 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
165 Alert("Invalid server address: '%s'\n", str);
166 goto fail;
167 }
168 }
169 else {
170 memset(&ss, 0, sizeof(ss));
171 ss.ss_family = AF_INET;
172
173 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
174 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
175 }
176 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
177 struct hostent *he;
178
179 if ((he = gethostbyname(str)) == NULL) {
180 Alert("Invalid server name: '%s'\n", str);
181 goto fail;
182 }
183 else
184 ((struct sockaddr_in *)&ss)->sin_addr =
185 *(struct in_addr *) *(he->h_addr_list);
186 }
187 }
188
189 /* 3) look for the port-end delimiter */
190 if ((c = strchr(range, '-')) != NULL) {
191 *c++ = 0;
192 end = atol(c);
193 }
194 else {
195 end = atol(range);
196 }
197
198 port = atol(range);
199
200 if (port < 1 || port > 65535) {
201 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
202 goto fail;
203 }
204
205 if (end < 1 || end > 65535) {
206 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
207 goto fail;
208 }
209
210 for (; port <= end; port++) {
211 l = (struct listener *)calloc(1, sizeof(struct listener));
212 l->next = tail;
213 tail = l;
214
215 l->fd = -1;
216 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100217 l->state = LI_INIT;
218
219 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100221 tcpv6_add_listener(l);
222 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100224 tcpv4_add_listener(l);
225 }
226 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 } /* end for(port) */
228 } /* end while(next) */
229 free(dupstr);
230 return tail;
231 fail:
232 free(dupstr);
233 return NULL;
234}
235
Willy Tarreau977b8e42006-12-29 14:19:17 +0100236/*
237 * Sends a warning if proxy <proxy> does not have at least one of the
238 * capabilities in <cap>. An optionnal <hint> may be added at the end
239 * of the warning to help the user. Returns 1 if a warning was emitted
240 * or 0 if the condition is valid.
241 */
242int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
243{
244 char *msg;
245
246 switch (cap) {
247 case PR_CAP_BE: msg = "no backend"; break;
248 case PR_CAP_FE: msg = "no frontend"; break;
249 case PR_CAP_RS: msg = "no ruleset"; break;
250 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
251 default: msg = "not enough"; break;
252 }
253
254 if (!(proxy->cap & cap)) {
255 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100256 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100257 return 1;
258 }
259 return 0;
260}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261
262/*
263 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
264 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100265int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266{
267
268 if (!strcmp(args[0], "global")) { /* new section */
269 /* no option, nothing special to do */
270 return 0;
271 }
272 else if (!strcmp(args[0], "daemon")) {
273 global.mode |= MODE_DAEMON;
274 }
275 else if (!strcmp(args[0], "debug")) {
276 global.mode |= MODE_DEBUG;
277 }
278 else if (!strcmp(args[0], "noepoll")) {
279 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
280 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200281 else if (!strcmp(args[0], "nosepoll")) {
282 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
283 }
284 else if (!strcmp(args[0], "nokqueue")) {
285 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
286 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200287 else if (!strcmp(args[0], "nopoll")) {
288 cfg_polling_mechanism &= ~POLL_USE_POLL;
289 }
290 else if (!strcmp(args[0], "quiet")) {
291 global.mode |= MODE_QUIET;
292 }
293 else if (!strcmp(args[0], "stats")) {
Willy Tarreaufbee7132007-10-18 13:53:22 +0200294 memcpy(trash, "error near 'stats'", 19);
295 if (stats_parse_global((const char **)args + 1, trash, sizeof(trash)) < 0) {
296 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
297 return -1;
298 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200300 else if (!strcmp(args[0], "tune.maxpollevents")) {
301 if (global.tune.maxpollevents != 0) {
302 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
303 return 0;
304 }
305 if (*(args[1]) == 0) {
306 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
307 return -1;
308 }
309 global.tune.maxpollevents = atol(args[1]);
310 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100311 else if (!strcmp(args[0], "tune.maxaccept")) {
312 if (global.tune.maxaccept != 0) {
313 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
314 return 0;
315 }
316 if (*(args[1]) == 0) {
317 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
318 return -1;
319 }
320 global.tune.maxaccept = atol(args[1]);
321 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200322 else if (!strcmp(args[0], "uid")) {
323 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200324 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200325 return 0;
326 }
327 if (*(args[1]) == 0) {
328 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
329 return -1;
330 }
331 global.uid = atol(args[1]);
332 }
333 else if (!strcmp(args[0], "gid")) {
334 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200335 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200336 return 0;
337 }
338 if (*(args[1]) == 0) {
339 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
340 return -1;
341 }
342 global.gid = atol(args[1]);
343 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200344 /* user/group name handling */
345 else if (!strcmp(args[0], "user")) {
346 struct passwd *ha_user;
347 if (global.uid != 0) {
348 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
349 return 0;
350 }
351 errno = 0;
352 ha_user = getpwnam(args[1]);
353 if (ha_user != NULL) {
354 global.uid = (int)ha_user->pw_uid;
355 }
356 else {
357 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
358 exit(1);
359 }
360 }
361 else if (!strcmp(args[0], "group")) {
362 struct group *ha_group;
363 if (global.gid != 0) {
364 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
365 return 0;
366 }
367 errno = 0;
368 ha_group = getgrnam(args[1]);
369 if (ha_group != NULL) {
370 global.gid = (int)ha_group->gr_gid;
371 }
372 else {
373 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
374 exit(1);
375 }
376 }
377 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200378 else if (!strcmp(args[0], "nbproc")) {
379 if (global.nbproc != 0) {
380 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
381 return 0;
382 }
383 if (*(args[1]) == 0) {
384 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
385 return -1;
386 }
387 global.nbproc = atol(args[1]);
388 }
389 else if (!strcmp(args[0], "maxconn")) {
390 if (global.maxconn != 0) {
391 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
392 return 0;
393 }
394 if (*(args[1]) == 0) {
395 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
396 return -1;
397 }
398 global.maxconn = atol(args[1]);
399#ifdef SYSTEM_MAXCONN
400 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
401 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);
402 global.maxconn = DEFAULT_MAXCONN;
403 }
404#endif /* SYSTEM_MAXCONN */
405 }
406 else if (!strcmp(args[0], "ulimit-n")) {
407 if (global.rlimit_nofile != 0) {
408 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
409 return 0;
410 }
411 if (*(args[1]) == 0) {
412 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
413 return -1;
414 }
415 global.rlimit_nofile = atol(args[1]);
416 }
417 else if (!strcmp(args[0], "chroot")) {
418 if (global.chroot != NULL) {
419 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
420 return 0;
421 }
422 if (*(args[1]) == 0) {
423 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
424 return -1;
425 }
426 global.chroot = strdup(args[1]);
427 }
428 else if (!strcmp(args[0], "pidfile")) {
429 if (global.pidfile != NULL) {
430 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
431 return 0;
432 }
433 if (*(args[1]) == 0) {
434 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
435 return -1;
436 }
437 global.pidfile = strdup(args[1]);
438 }
439 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100440 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200441 int facility, level;
442
443 if (*(args[1]) == 0 || *(args[2]) == 0) {
444 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
445 return -1;
446 }
447
448 facility = get_log_facility(args[2]);
449 if (facility < 0) {
450 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
451 exit(1);
452 }
453
454 level = 7; /* max syslog level = debug */
455 if (*(args[3])) {
456 level = get_log_level(args[3]);
457 if (level < 0) {
458 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
459 exit(1);
460 }
461 }
462
Robert Tsai81ae1952007-12-05 10:47:29 +0100463 if (args[1][0] == '/') {
464 logsrv.u.addr.sa_family = AF_UNIX;
465 logsrv.u.un = *str2sun(args[1]);
466 } else {
467 logsrv.u.addr.sa_family = AF_INET;
468 logsrv.u.in = *str2sa(args[1]);
469 if (!logsrv.u.in.sin_port)
470 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200472
473 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100474 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 global.logfac1 = facility;
476 global.loglev1 = level;
477 }
478 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100479 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200480 global.logfac2 = facility;
481 global.loglev2 = level;
482 }
483 else {
484 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
485 return -1;
486 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200487 }
488 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
489 if (global.spread_checks != 0) {
490 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
491 return 0;
492 }
493 if (*(args[1]) == 0) {
494 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
495 return -1;
496 }
497 global.spread_checks = atol(args[1]);
498 if (global.spread_checks < 0 || global.spread_checks > 50) {
499 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
500 return -1;
501 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200502 }
503 else {
504 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
505 return -1;
506 }
507 return 0;
508}
509
510
511static void init_default_instance()
512{
513 memset(&defproxy, 0, sizeof(defproxy));
514 defproxy.mode = PR_MODE_TCP;
515 defproxy.state = PR_STNEW;
516 defproxy.maxconn = cfg_maxpconn;
517 defproxy.conn_retries = CONN_RETRIES;
518 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100519 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520}
521
522/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100523 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
524 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200525 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100526int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527{
528 static struct proxy *curproxy = NULL;
529 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200530 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100531 int rc;
532 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200533
Willy Tarreau977b8e42006-12-29 14:19:17 +0100534 if (!strcmp(args[0], "listen"))
535 rc = PR_CAP_LISTEN;
536 else if (!strcmp(args[0], "frontend"))
537 rc = PR_CAP_FE | PR_CAP_RS;
538 else if (!strcmp(args[0], "backend"))
539 rc = PR_CAP_BE | PR_CAP_RS;
540 else if (!strcmp(args[0], "ruleset"))
541 rc = PR_CAP_RS;
542 else
543 rc = PR_CAP_NONE;
544
545 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 if (!*args[1]) {
547 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
548 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
549 file, linenum, args[0]);
550 return -1;
551 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200552
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100553 err = invalid_char(args[1]);
554 if (err) {
555 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
556 file, linenum, *err, args[0], args[1]);
557 return -1;
558 }
559
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200560 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
561 /*
562 * If there are two proxies with the same name only following
563 * combinations are allowed:
564 *
565 * listen backend frontend ruleset
566 * listen - - - -
567 * backend - - OK -
568 * frontend - OK - -
569 * ruleset - - - -
570 */
571
572 if (!strcmp(curproxy->id, args[1]) &&
573 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
574 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100575 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
576 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200577 }
578 }
579
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
581 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
582 return -1;
583 }
584
585 curproxy->next = proxy;
586 proxy = curproxy;
587 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200588 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200589 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200590 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100591 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200592 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200593
Willy Tarreauee991362007-05-14 14:37:50 +0200594 /* Timeouts are defined as -1, so we cannot use the zeroed area
595 * as a default value.
596 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100597 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200598
599 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100601 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602
603 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100604 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200605 curproxy->listen = str2listener(args[2], curproxy->listen);
606 if (!curproxy->listen)
607 return -1;
608 global.maxsock++;
609 }
610
611 /* set default values */
612 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100614 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200615 curproxy->except_net = defproxy.except_net;
616 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617
Willy Tarreau977b8e42006-12-29 14:19:17 +0100618 if (curproxy->cap & PR_CAP_FE) {
619 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100620 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100621
622 /* initialize error relocations */
623 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
624 if (defproxy.errmsg[rc].str)
625 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
626 }
627
628 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630
Willy Tarreau977b8e42006-12-29 14:19:17 +0100631 if (curproxy->cap & PR_CAP_BE) {
632 curproxy->fullconn = defproxy.fullconn;
633 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634
Willy Tarreau977b8e42006-12-29 14:19:17 +0100635 if (defproxy.check_req)
636 curproxy->check_req = strdup(defproxy.check_req);
637 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200638
Willy Tarreau977b8e42006-12-29 14:19:17 +0100639 if (defproxy.cookie_name)
640 curproxy->cookie_name = strdup(defproxy.cookie_name);
641 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100642
643 if (defproxy.url_param_name)
644 curproxy->url_param_name = strdup(defproxy.url_param_name);
645 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647
Willy Tarreau977b8e42006-12-29 14:19:17 +0100648 if (curproxy->cap & PR_CAP_RS) {
649 if (defproxy.capture_name)
650 curproxy->capture_name = strdup(defproxy.capture_name);
651 curproxy->capture_namelen = defproxy.capture_namelen;
652 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100653 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200654
Willy Tarreau977b8e42006-12-29 14:19:17 +0100655 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100656 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100657 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100658 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100659 curproxy->uri_auth = defproxy.uri_auth;
660 curproxy->mon_net = defproxy.mon_net;
661 curproxy->mon_mask = defproxy.mon_mask;
662 if (defproxy.monitor_uri)
663 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
664 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100665 if (defproxy.defbe.name)
666 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100667 }
668
669 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100670 curproxy->timeout.connect = defproxy.timeout.connect;
671 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100672 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100673 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100674 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100675 curproxy->source_addr = defproxy.source_addr;
676 }
677
Willy Tarreaubaaee002006-06-26 02:48:02 +0200678 curproxy->mode = defproxy.mode;
679 curproxy->logfac1 = defproxy.logfac1;
680 curproxy->logsrv1 = defproxy.logsrv1;
681 curproxy->loglev1 = defproxy.loglev1;
682 curproxy->logfac2 = defproxy.logfac2;
683 curproxy->logsrv2 = defproxy.logsrv2;
684 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100686 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
687 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200688
Willy Tarreaubaaee002006-06-26 02:48:02 +0200689 return 0;
690 }
691 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
692 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100693 /* FIXME-20070101: we should do this too at the end of the
694 * config parsing to free all default values.
695 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696 if (defproxy.check_req) free(defproxy.check_req);
697 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100698 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200699 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200700 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100701 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100702
703 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
704 if (defproxy.errmsg[rc].len)
705 free(defproxy.errmsg[rc].str);
706 }
707
Willy Tarreaubaaee002006-06-26 02:48:02 +0200708 /* we cannot free uri_auth because it might already be used */
709 init_default_instance();
710 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100711 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200712 return 0;
713 }
714 else if (curproxy == NULL) {
715 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
716 return -1;
717 }
718
Willy Tarreau977b8e42006-12-29 14:19:17 +0100719
720 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100722 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200723 if (curproxy == &defproxy) {
724 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
725 return -1;
726 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100727 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
728 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729
730 if (strchr(args[1], ':') == NULL) {
731 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
732 file, linenum, args[0]);
733 return -1;
734 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100735
736 last_listen = curproxy->listen;
737 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200738 if (!curproxy->listen)
739 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100740 if (*args[2]) {
741#ifdef CONFIG_HAP_LINUX_TPROXY
742 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
743 struct listener *l;
744
745 for (l = curproxy->listen; l != last_listen; l = l->next)
746 l->options |= LI_O_FOREIGN;
747 }
748 else {
749 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
750 file, linenum, args[0]);
751 return -1;
752 }
753#else
754 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
755 file, linenum, args[0]);
756 return -1;
757#endif
758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200759 global.maxsock++;
760 return 0;
761 }
762 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
763 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
764 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
765 file, linenum, args[0]);
766 return -1;
767 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100768 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
769 return 0;
770
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 /* flush useless bits */
772 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
773 return 0;
774 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200775 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100776 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
777 return 0;
778
Willy Tarreau1c47f852006-07-09 08:22:27 +0200779 if (!*args[1]) {
780 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
781 file, linenum, args[0]);
782 return -1;
783 }
784
785 if (curproxy->monitor_uri != NULL)
786 free(curproxy->monitor_uri);
787
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100788 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200789 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100790 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200791 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
792
793 return 0;
794 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200795 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
796 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
797 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
798 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
799 else {
800 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
801 return -1;
802 }
803 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100804 else if (!strcmp(args[0], "id")) {
805 struct proxy *target;
806
807 if (curproxy == &defproxy) {
808 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
809 file, linenum, args[0]);
810 return -1;
811 }
812
813 if (!*args[1]) {
814 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
815 file, linenum, args[0]);
816 return -1;
817 }
818
819 curproxy->uuid = atol(args[1]);
820
821 if (curproxy->uuid < 1001) {
822 Alert("parsing [%s:%d]: custom id has to be > 1000",
823 file, linenum);
824 return -1;
825 }
826
827 for (target = proxy; target; target = target->next)
828 if (curproxy != target && curproxy->uuid == target->uuid) {
829 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
830 file, linenum, curproxy->id, target->id);
831 return -1;
832 }
833 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
835 curproxy->state = PR_STSTOPPED;
836 }
837 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
838 curproxy->state = PR_STNEW;
839 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200840 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100841 err = invalid_char(args[1]);
842 if (err) {
843 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
844 file, linenum, *err, args[1]);
845 return -1;
846 }
847
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200848 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
849 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
850 file, linenum, args[1]);
851 return -1;
852 }
853 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200854 else if (!strcmp(args[0], "cookie")) { /* cookie name */
855 int cur_arg;
856 // if (curproxy == &defproxy) {
857 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
858 // return -1;
859 // }
860
Willy Tarreau977b8e42006-12-29 14:19:17 +0100861 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
862 return 0;
863
Willy Tarreaubaaee002006-06-26 02:48:02 +0200864 if (curproxy->cookie_name != NULL) {
865 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
866 // file, linenum);
867 // return 0;
868 free(curproxy->cookie_name);
869 }
870
871 if (*(args[1]) == 0) {
872 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
873 file, linenum, args[0]);
874 return -1;
875 }
876 curproxy->cookie_name = strdup(args[1]);
877 curproxy->cookie_len = strlen(curproxy->cookie_name);
878
879 cur_arg = 2;
880 while (*(args[cur_arg])) {
881 if (!strcmp(args[cur_arg], "rewrite")) {
882 curproxy->options |= PR_O_COOK_RW;
883 }
884 else if (!strcmp(args[cur_arg], "indirect")) {
885 curproxy->options |= PR_O_COOK_IND;
886 }
887 else if (!strcmp(args[cur_arg], "insert")) {
888 curproxy->options |= PR_O_COOK_INS;
889 }
890 else if (!strcmp(args[cur_arg], "nocache")) {
891 curproxy->options |= PR_O_COOK_NOC;
892 }
893 else if (!strcmp(args[cur_arg], "postonly")) {
894 curproxy->options |= PR_O_COOK_POST;
895 }
896 else if (!strcmp(args[cur_arg], "prefix")) {
897 curproxy->options |= PR_O_COOK_PFX;
898 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200899 else if (!strcmp(args[cur_arg], "domain")) {
900 if (!*args[cur_arg + 1]) {
901 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
902 file, linenum, args[cur_arg]);
903 return -1;
904 }
905
906 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
907 /* rfc2109, 4.3.2 Rejecting Cookies */
908 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
909 " dots or does not start with a dot.\n",
910 file, linenum, args[cur_arg + 1]);
911 return -1;
912 }
913
914 err = invalid_domainchar(args[cur_arg + 1]);
915 if (err) {
916 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
917 file, linenum, *err, args[cur_arg + 1]);
918 return -1;
919 }
920
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +0200921 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200922 cur_arg++;
923 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200925 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 file, linenum, args[0]);
927 return -1;
928 }
929 cur_arg++;
930 }
931 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
932 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
933 file, linenum);
934 return -1;
935 }
936
937 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
938 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
939 file, linenum);
940 return -1;
941 }
942 }/* end else if (!strcmp(args[0], "cookie")) */
943 else if (!strcmp(args[0], "appsession")) { /* cookie name */
944 // if (curproxy == &defproxy) {
945 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
946 // return -1;
947 // }
948
Willy Tarreau977b8e42006-12-29 14:19:17 +0100949 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
950 return 0;
951
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 if (curproxy->appsession_name != NULL) {
953 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
954 // file, linenum);
955 // return 0;
956 free(curproxy->appsession_name);
957 }
958
959 if (*(args[5]) == 0) {
960 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
961 file, linenum, args[0]);
962 return -1;
963 }
964 have_appsession = 1;
965 curproxy->appsession_name = strdup(args[1]);
966 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
967 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100968 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
969 if (err) {
970 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
971 file, linenum, *err, args[0]);
972 return -1;
973 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200974 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +0200975
Willy Tarreau51041c72007-09-09 21:56:53 +0200976 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
977 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978 return -1;
979 }
980 } /* Url App Session */
981 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100982 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
983 return 0;
984
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
986 // if (curproxy == &defproxy) {
987 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
988 // return -1;
989 // }
990
991 if (curproxy->capture_name != NULL) {
992 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
993 // file, linenum, args[0]);
994 // return 0;
995 free(curproxy->capture_name);
996 }
997
998 if (*(args[4]) == 0) {
999 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1000 file, linenum, args[0]);
1001 return -1;
1002 }
1003 curproxy->capture_name = strdup(args[2]);
1004 curproxy->capture_namelen = strlen(curproxy->capture_name);
1005 curproxy->capture_len = atol(args[4]);
1006 if (curproxy->capture_len >= CAPTURE_LEN) {
1007 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1008 file, linenum, CAPTURE_LEN - 1);
1009 curproxy->capture_len = CAPTURE_LEN - 1;
1010 }
1011 curproxy->to_log |= LW_COOKIE;
1012 }
1013 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1014 struct cap_hdr *hdr;
1015
1016 if (curproxy == &defproxy) {
1017 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1018 return -1;
1019 }
1020
1021 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1022 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1023 file, linenum, args[0], args[1]);
1024 return -1;
1025 }
1026
1027 hdr = calloc(sizeof(struct cap_hdr), 1);
1028 hdr->next = curproxy->req_cap;
1029 hdr->name = strdup(args[3]);
1030 hdr->namelen = strlen(args[3]);
1031 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001032 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001033 hdr->index = curproxy->nb_req_cap++;
1034 curproxy->req_cap = hdr;
1035 curproxy->to_log |= LW_REQHDR;
1036 }
1037 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1038 struct cap_hdr *hdr;
1039
1040 if (curproxy == &defproxy) {
1041 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1042 return -1;
1043 }
1044
1045 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1046 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1047 file, linenum, args[0], args[1]);
1048 return -1;
1049 }
1050 hdr = calloc(sizeof(struct cap_hdr), 1);
1051 hdr->next = curproxy->rsp_cap;
1052 hdr->name = strdup(args[3]);
1053 hdr->namelen = strlen(args[3]);
1054 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001055 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 hdr->index = curproxy->nb_rsp_cap++;
1057 curproxy->rsp_cap = hdr;
1058 curproxy->to_log |= LW_RSPHDR;
1059 }
1060 else {
1061 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1062 file, linenum, args[0]);
1063 return -1;
1064 }
1065 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001066 else if (!strcmp(args[0], "contimeout") || !strcmp(args[0], "clitimeout") ||
1067 !strcmp(args[0], "srvtimeout") || !strcmp(args[0], "timeout")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001068
Willy Tarreaue219db72007-12-03 01:30:13 +01001069 /* either we have {con|srv|cli}timeout <value> or we have the
1070 * new form: timeout <type> <value>. The parser needs the word
1071 * preceeding the value.
1072 */
1073 const char **start_arg = (const char **)args;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001074
Willy Tarreaue219db72007-12-03 01:30:13 +01001075 if (strcmp(args[0], "timeout") == 0)
1076 start_arg++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001077
Willy Tarreaue219db72007-12-03 01:30:13 +01001078 snprintf(trash, sizeof(trash), "error near '%s'", args[0]);
1079 rc = proxy_parse_timeout(start_arg, curproxy, &defproxy, trash, sizeof(trash));
1080 if (rc < 0) {
1081 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001082 return -1;
1083 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001084 if (rc > 0)
1085 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001086 }
1087 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001088 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1089 return 0;
1090
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 if (*(args[1]) == 0) {
1092 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1093 file, linenum, args[0]);
1094 return -1;
1095 }
1096 curproxy->conn_retries = atol(args[1]);
1097 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001098 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1099 int pol = ACL_COND_NONE;
1100 struct acl_cond *cond;
1101
1102 if (!strcmp(args[1], "if"))
1103 pol = ACL_COND_IF;
1104 else if (!strcmp(args[1], "unless"))
1105 pol = ACL_COND_UNLESS;
1106
1107 if (pol == ACL_COND_NONE) {
1108 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1109 file, linenum, args[0]);
1110 return -1;
1111 }
1112
1113 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1114 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1115 file, linenum);
1116 return -1;
1117 }
1118 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1119 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001120 else if (!strcmp(args[0], "redirect")) {
1121 int pol = ACL_COND_NONE;
1122 struct acl_cond *cond;
1123 struct redirect_rule *rule;
1124 int cur_arg;
1125 int type = REDIRECT_TYPE_NONE;
1126 int code = 302;
1127 char *destination = NULL;
1128
1129 cur_arg = 1;
1130 while (*(args[cur_arg])) {
1131 if (!strcmp(args[cur_arg], "location")) {
1132 if (!*args[cur_arg + 1]) {
1133 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1134 file, linenum, args[0], args[cur_arg]);
1135 return -1;
1136 }
1137
1138 type = REDIRECT_TYPE_LOCATION;
1139 cur_arg++;
1140 destination = args[cur_arg];
1141 }
1142 else if (!strcmp(args[cur_arg], "prefix")) {
1143 if (!*args[cur_arg + 1]) {
1144 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1145 file, linenum, args[0], args[cur_arg]);
1146 return -1;
1147 }
1148
1149 type = REDIRECT_TYPE_PREFIX;
1150 cur_arg++;
1151 destination = args[cur_arg];
1152 }
1153 else if (!strcmp(args[cur_arg],"code")) {
1154 if (!*args[cur_arg + 1]) {
1155 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1156 file, linenum, args[0]);
1157 return -1;
1158 }
1159 cur_arg++;
1160 code = atol(args[cur_arg]);
1161 if (code < 301 || code > 303) {
1162 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1163 file, linenum, args[0], code);
1164 return -1;
1165 }
1166 }
1167 else if (!strcmp(args[cur_arg], "if")) {
1168 pol = ACL_COND_IF;
1169 cur_arg++;
1170 break;
1171 }
1172 else if (!strcmp(args[cur_arg], "unless")) {
1173 pol = ACL_COND_UNLESS;
1174 cur_arg++;
1175 break;
1176 }
1177 else {
1178 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1179 file, linenum, args[0], args[cur_arg]);
1180 return -1;
1181 }
1182 cur_arg++;
1183 }
1184
1185 if (type == REDIRECT_TYPE_NONE) {
1186 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1187 file, linenum, args[0]);
1188 return -1;
1189 }
1190
1191 if (pol == ACL_COND_NONE) {
1192 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1193 file, linenum, args[0]);
1194 return -1;
1195 }
1196
1197 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1198 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1199 file, linenum, args[0]);
1200 return -1;
1201 }
1202
1203 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1204 rule->cond = cond;
1205 rule->rdr_str = strdup(destination);
1206 rule->rdr_len = strlen(destination);
1207 rule->type = type;
1208 rule->code = code;
1209 LIST_INIT(&rule->list);
1210 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1211 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001212 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1213 int pol = ACL_COND_NONE;
1214 struct acl_cond *cond;
1215 struct switching_rule *rule;
1216
1217 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1218 return 0;
1219
1220 if (*(args[1]) == 0) {
1221 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1222 return -1;
1223 }
1224
1225 if (!strcmp(args[2], "if"))
1226 pol = ACL_COND_IF;
1227 else if (!strcmp(args[2], "unless"))
1228 pol = ACL_COND_UNLESS;
1229
1230 if (pol == ACL_COND_NONE) {
1231 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1232 file, linenum, args[0]);
1233 return -1;
1234 }
1235
1236 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1237 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1238 file, linenum);
1239 return -1;
1240 }
1241
1242 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1243 rule->cond = cond;
1244 rule->be.name = strdup(args[1]);
1245 LIST_INIT(&rule->list);
1246 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001248 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001249 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1250 return 0;
1251
Willy Tarreaubaaee002006-06-26 02:48:02 +02001252 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1253 curproxy->uri_auth = NULL; /* we must detach from the default config */
1254
1255 if (*(args[1]) == 0) {
1256 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1257 return -1;
1258 } else if (!strcmp(args[1], "uri")) {
1259 if (*(args[2]) == 0) {
1260 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1261 return -1;
1262 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1263 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1264 return -1;
1265 }
1266 } else if (!strcmp(args[1], "realm")) {
1267 if (*(args[2]) == 0) {
1268 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1269 return -1;
1270 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1271 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1272 return -1;
1273 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001274 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001275 unsigned interval;
1276
1277 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1278 if (err) {
1279 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1280 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001281 return -1;
1282 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1283 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1284 return -1;
1285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001286 } else if (!strcmp(args[1], "auth")) {
1287 if (*(args[2]) == 0) {
1288 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1289 return -1;
1290 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1291 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1292 return -1;
1293 }
1294 } else if (!strcmp(args[1], "scope")) {
1295 if (*(args[2]) == 0) {
1296 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1297 return -1;
1298 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1299 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1300 return -1;
1301 }
1302 } else if (!strcmp(args[1], "enable")) {
1303 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1304 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1305 return -1;
1306 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001307 } else if (!strcmp(args[1], "hide-version")) {
1308 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1309 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1310 return -1;
1311 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001312 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001313 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001314 file, linenum, args[0]);
1315 return -1;
1316 }
1317 }
1318 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001319 int optnum;
1320
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001321 if (*(args[1]) == '\0') {
1322 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1323 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001324 return -1;
1325 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001326
1327 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1328 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1329 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1330 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001331
1332 if (!inv)
1333 curproxy->options |= cfg_opts[optnum].val;
1334 else
1335 curproxy->options &= ~cfg_opts[optnum].val;
1336
Willy Tarreau13943ab2006-12-31 00:24:10 +01001337 return 0;
1338 }
1339 }
1340
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001341 if (inv) {
1342 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1343 file, linenum, args[1]);
1344 return -1;
1345 }
1346
Willy Tarreau13943ab2006-12-31 00:24:10 +01001347 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001348 /* generate a complete HTTP log */
1349 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1350 else if (!strcmp(args[1], "tcplog"))
1351 /* generate a detailed TCP log */
1352 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 else if (!strcmp(args[1], "tcpka")) {
1354 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001355 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1356 return 0;
1357
1358 if (curproxy->cap & PR_CAP_FE)
1359 curproxy->options |= PR_O_TCP_CLI_KA;
1360 if (curproxy->cap & PR_CAP_BE)
1361 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 }
1363 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001364 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1365 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001366 /* use HTTP request to check servers' health */
1367 if (curproxy->check_req != NULL) {
1368 free(curproxy->check_req);
1369 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001370 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001371 curproxy->options &= ~PR_O_SMTP_CHK;
1372 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001373 if (!*args[2]) { /* no argument */
1374 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1375 curproxy->check_len = strlen(DEF_CHECK_REQ);
1376 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001377 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378 curproxy->check_req = (char *)malloc(reqlen);
1379 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1380 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1381 } else { /* more arguments : METHOD URI [HTTP_VER] */
1382 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1383 if (*args[4])
1384 reqlen += strlen(args[4]);
1385 else
1386 reqlen += strlen("HTTP/1.0");
1387
1388 curproxy->check_req = (char *)malloc(reqlen);
1389 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1390 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1391 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001392 }
1393 else if (!strcmp(args[1], "ssl-hello-chk")) {
1394 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001395 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1396 return 0;
1397
Willy Tarreauf3c69202006-07-09 16:42:34 +02001398 if (curproxy->check_req != NULL) {
1399 free(curproxy->check_req);
1400 }
1401 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001402 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001403 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001404 }
Willy Tarreau23677902007-05-08 23:50:35 +02001405 else if (!strcmp(args[1], "smtpchk")) {
1406 /* use SMTP request to check servers' health */
1407 if (curproxy->check_req != NULL) {
1408 free(curproxy->check_req);
1409 }
1410 curproxy->options &= ~PR_O_HTTP_CHK;
1411 curproxy->options &= ~PR_O_SSL3_CHK;
1412 curproxy->options |= PR_O_SMTP_CHK;
1413
1414 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1415 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1416 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1417 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1418 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1419 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1420 curproxy->check_req = (char *)malloc(reqlen);
1421 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1422 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1423 } else {
1424 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1425 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1426 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1427 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1428 }
1429 }
1430 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001431 else if (!strcmp(args[1], "forwardfor")) {
1432 /* insert x-forwarded-for field, but not for the
1433 * IP address listed as an except.
1434 */
1435 if (*(args[2])) {
1436 if (!strcmp(args[2], "except")) {
1437 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1438 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1439 file, linenum, args[0]);
1440 return -1;
1441 }
1442 /* flush useless bits */
1443 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1444 } else {
1445 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1446 file, linenum, args[0]);
1447 return -1;
1448 }
1449 }
1450 curproxy->options |= PR_O_FWDFOR;
1451 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001452 else {
1453 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1454 return -1;
1455 }
1456 return 0;
1457 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001458 else if (!strcmp(args[0], "default_backend")) {
1459 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1460 return 0;
1461
1462 if (*(args[1]) == 0) {
1463 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1464 return -1;
1465 }
1466 if (curproxy->defbe.name)
1467 free(curproxy->defbe.name);
1468 curproxy->defbe.name = strdup(args[1]);
1469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001471 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1472 return 0;
1473
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001474 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1475 file, linenum, args[0]);
1476
Willy Tarreaubaaee002006-06-26 02:48:02 +02001477 /* enable reconnections to dispatch */
1478 curproxy->options |= PR_O_REDISP;
1479 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001480 else if (!strcmp(args[0], "http-check")) {
1481 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1482 return 0;
1483
1484 if (strcmp(args[1], "disable-on-404") == 0) {
1485 /* enable a graceful server shutdown on an HTTP 404 response */
1486 curproxy->options |= PR_O_DISABLE404;
1487 }
1488 else {
1489 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1490 return -1;
1491 }
1492 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001493 else if (!strcmp(args[0], "monitor")) {
1494 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1495 return 0;
1496
1497 if (strcmp(args[1], "fail") == 0) {
1498 /* add a condition to fail monitor requests */
1499 int pol = ACL_COND_NONE;
1500 struct acl_cond *cond;
1501
1502 if (!strcmp(args[2], "if"))
1503 pol = ACL_COND_IF;
1504 else if (!strcmp(args[2], "unless"))
1505 pol = ACL_COND_UNLESS;
1506
1507 if (pol == ACL_COND_NONE) {
1508 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1509 file, linenum, args[0], args[1]);
1510 return -1;
1511 }
1512
1513 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1514 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1515 file, linenum, args[0], args[1]);
1516 return -1;
1517 }
1518 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1519 }
1520 else {
1521 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1522 return -1;
1523 }
1524 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001525#ifdef TPROXY
1526 else if (!strcmp(args[0], "transparent")) {
1527 /* enable transparent proxy connections */
1528 curproxy->options |= PR_O_TRANSP;
1529 }
1530#endif
1531 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001532 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1533 return 0;
1534
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535 if (*(args[1]) == 0) {
1536 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1537 return -1;
1538 }
1539 curproxy->maxconn = atol(args[1]);
1540 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001541 else if (!strcmp(args[0], "backlog")) { /* backlog */
1542 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1543 return 0;
1544
1545 if (*(args[1]) == 0) {
1546 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1547 return -1;
1548 }
1549 curproxy->backlog = atol(args[1]);
1550 }
Willy Tarreau86034312006-12-29 00:10:33 +01001551 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001552 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1553 return 0;
1554
Willy Tarreau86034312006-12-29 00:10:33 +01001555 if (*(args[1]) == 0) {
1556 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1557 return -1;
1558 }
1559 curproxy->fullconn = atol(args[1]);
1560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1562 if (*(args[1]) == 0) {
1563 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1564 return -1;
1565 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001566 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1567 if (err) {
1568 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1569 file, linenum, *err);
1570 return -1;
1571 }
1572 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001573 }
1574 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1575 if (curproxy == &defproxy) {
1576 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1577 return -1;
1578 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001579 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1580 return 0;
1581
Willy Tarreaubaaee002006-06-26 02:48:02 +02001582 if (strchr(args[1], ':') == NULL) {
1583 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1584 return -1;
1585 }
1586 curproxy->dispatch_addr = *str2sa(args[1]);
1587 }
1588 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001589 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1590 return 0;
1591
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001592 memcpy(trash, "error near 'balance'", 19);
1593 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1594 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1595 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001596 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 }
1598 else if (!strcmp(args[0], "server")) { /* server address */
1599 int cur_arg;
1600 char *rport;
1601 char *raddr;
1602 short realport;
1603 int do_check;
1604
1605 if (curproxy == &defproxy) {
1606 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1607 return -1;
1608 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001609 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1610 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611
1612 if (!*args[2]) {
1613 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1614 file, linenum, args[0]);
1615 return -1;
1616 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001617
1618 err = invalid_char(args[1]);
1619 if (err) {
1620 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1621 file, linenum, *err, args[1]);
1622 return -1;
1623 }
1624
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1626 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1627 return -1;
1628 }
1629
1630 /* the servers are linked backwards first */
1631 newsrv->next = curproxy->srv;
1632 curproxy->srv = newsrv;
1633 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001634 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635
1636 LIST_INIT(&newsrv->pendconns);
1637 do_check = 0;
1638 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001639 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640 newsrv->id = strdup(args[1]);
1641
1642 /* several ways to check the port component :
1643 * - IP => port=+0, relative
1644 * - IP: => port=+0, relative
1645 * - IP:N => port=N, absolute
1646 * - IP:+N => port=+N, relative
1647 * - IP:-N => port=-N, relative
1648 */
1649 raddr = strdup(args[2]);
1650 rport = strchr(raddr, ':');
1651 if (rport) {
1652 *rport++ = 0;
1653 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001654 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 newsrv->state |= SRV_MAPPORTS;
1656 } else {
1657 realport = 0;
1658 newsrv->state |= SRV_MAPPORTS;
1659 }
1660
1661 newsrv->addr = *str2sa(raddr);
1662 newsrv->addr.sin_port = htons(realport);
1663 free(raddr);
1664
1665 newsrv->curfd = -1; /* no health-check in progress */
1666 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001667 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1668 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001669 newsrv->rise = DEF_RISETIME;
1670 newsrv->fall = DEF_FALLTIME;
1671 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001672 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001673 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001674 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001675
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 cur_arg = 3;
1677 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001678 if (!strcmp(args[cur_arg], "id")) {
1679 struct server *target;
1680
1681 if (!*args[cur_arg + 1]) {
1682 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1683 file, linenum, args[cur_arg]);
1684 return -1;
1685 }
1686
1687 newsrv->puid = atol(args[cur_arg + 1]);
1688
1689 if (newsrv->puid< 1001) {
1690 Alert("parsing [%s:%d]: custom id has to be > 1000",
1691 file, linenum);
1692 return -1;
1693 }
1694
1695 for (target = proxy->srv; target; target = target->next)
1696 if (newsrv != target && newsrv->puid == target->puid) {
1697 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1698 file, linenum, newsrv->id, target->id);
1699 return -1;
1700 }
1701 cur_arg += 2;
1702 }
1703 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001704 newsrv->cookie = strdup(args[cur_arg + 1]);
1705 newsrv->cklen = strlen(args[cur_arg + 1]);
1706 cur_arg += 2;
1707 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001708 else if (!strcmp(args[cur_arg], "redir")) {
1709 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1710 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1711 cur_arg += 2;
1712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 else if (!strcmp(args[cur_arg], "rise")) {
1714 newsrv->rise = atol(args[cur_arg + 1]);
1715 newsrv->health = newsrv->rise;
1716 cur_arg += 2;
1717 }
1718 else if (!strcmp(args[cur_arg], "fall")) {
1719 newsrv->fall = atol(args[cur_arg + 1]);
1720 cur_arg += 2;
1721 }
1722 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001723 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1724 if (err) {
1725 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1726 file, linenum, *err, newsrv->id);
1727 return -1;
1728 }
1729 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001730 cur_arg += 2;
1731 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001732 else if (!strcmp(args[cur_arg], "fastinter")) {
1733 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1734 if (err) {
1735 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1736 file, linenum, *err, newsrv->id);
1737 return -1;
1738 }
1739 newsrv->fastinter = val;
1740 cur_arg += 2;
1741 }
1742 else if (!strcmp(args[cur_arg], "downinter")) {
1743 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1744 if (err) {
1745 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1746 file, linenum, *err, newsrv->id);
1747 return -1;
1748 }
1749 newsrv->downinter = val;
1750 cur_arg += 2;
1751 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001752 else if (!strcmp(args[cur_arg], "addr")) {
1753 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001754 cur_arg += 2;
1755 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001756 else if (!strcmp(args[cur_arg], "port")) {
1757 newsrv->check_port = atol(args[cur_arg + 1]);
1758 cur_arg += 2;
1759 }
1760 else if (!strcmp(args[cur_arg], "backup")) {
1761 newsrv->state |= SRV_BACKUP;
1762 cur_arg ++;
1763 }
1764 else if (!strcmp(args[cur_arg], "weight")) {
1765 int w;
1766 w = atol(args[cur_arg + 1]);
1767 if (w < 1 || w > 256) {
1768 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1769 file, linenum, newsrv->id, w);
1770 return -1;
1771 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001772 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773 cur_arg += 2;
1774 }
1775 else if (!strcmp(args[cur_arg], "minconn")) {
1776 newsrv->minconn = atol(args[cur_arg + 1]);
1777 cur_arg += 2;
1778 }
1779 else if (!strcmp(args[cur_arg], "maxconn")) {
1780 newsrv->maxconn = atol(args[cur_arg + 1]);
1781 cur_arg += 2;
1782 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001783 else if (!strcmp(args[cur_arg], "maxqueue")) {
1784 newsrv->maxqueue = atol(args[cur_arg + 1]);
1785 cur_arg += 2;
1786 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001787 else if (!strcmp(args[cur_arg], "slowstart")) {
1788 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001789 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001790 if (err) {
1791 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1792 file, linenum, *err, newsrv->id);
1793 return -1;
1794 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001795 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001796 cur_arg += 2;
1797 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001798 else if (!strcmp(args[cur_arg], "track")) {
1799
1800 if (!*args[cur_arg + 1]) {
1801 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1802 file, linenum);
1803 return -1;
1804 }
1805
1806 newsrv->trackit = strdup(args[cur_arg + 1]);
1807
1808 cur_arg += 2;
1809 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001810 else if (!strcmp(args[cur_arg], "check")) {
1811 global.maxsock++;
1812 do_check = 1;
1813 cur_arg += 1;
1814 }
1815 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1816 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001817#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001818 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1819 file, linenum, "source", "usesrc");
1820#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001821 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1822 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001823#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001824 return -1;
1825 }
1826 newsrv->state |= SRV_BIND_SRC;
1827 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1828 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001829 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001830#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1831#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001832 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001833 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1834 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001835 return -1;
1836 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001837#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001838 if (!*args[cur_arg + 1]) {
1839 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1840 file, linenum, "usesrc");
1841 return -1;
1842 }
1843 if (!strcmp(args[cur_arg + 1], "client")) {
1844 newsrv->state |= SRV_TPROXY_CLI;
1845 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1846 newsrv->state |= SRV_TPROXY_CIP;
1847 } else {
1848 newsrv->state |= SRV_TPROXY_ADDR;
1849 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1850 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001851 global.last_checks |= LSTCHK_NETADM;
1852#if !defined(CONFIG_HAP_LINUX_TPROXY)
1853 global.last_checks |= LSTCHK_CTTPROXY;
1854#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001855 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001856#else /* no TPROXY support */
1857 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001858 file, linenum, "usesrc");
1859 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001860#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001862 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001863 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1864 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1865 file, linenum, "usesrc", "source");
1866 return -1;
1867 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001869 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 +02001870 file, linenum, newsrv->id);
1871 return -1;
1872 }
1873 }
1874
1875 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001876 if (newsrv->trackit) {
1877 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1878 file, linenum);
1879 return -1;
1880 }
1881
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001882 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1883 newsrv->check_port = newsrv->check_addr.sin_port;
1884
Willy Tarreaubaaee002006-06-26 02:48:02 +02001885 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1886 newsrv->check_port = realport; /* by default */
1887 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001888 /* not yet valid, because no port was set on
1889 * the server either. We'll check if we have
1890 * a known port on the first listener.
1891 */
1892 struct listener *l;
1893 l = curproxy->listen;
1894 if (l) {
1895 int port;
1896 port = (l->addr.ss_family == AF_INET6)
1897 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1898 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1899 newsrv->check_port = port;
1900 }
1901 }
1902 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001903 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1904 file, linenum, newsrv->id);
1905 return -1;
1906 }
1907 newsrv->state |= SRV_CHECKED;
1908 }
1909
1910 if (newsrv->state & SRV_BACKUP)
1911 curproxy->srv_bck++;
1912 else
1913 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001914
1915 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001916 }
1917 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001918 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 int facility;
1920
1921 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1922 curproxy->logfac1 = global.logfac1;
1923 curproxy->logsrv1 = global.logsrv1;
1924 curproxy->loglev1 = global.loglev1;
1925 curproxy->logfac2 = global.logfac2;
1926 curproxy->logsrv2 = global.logsrv2;
1927 curproxy->loglev2 = global.loglev2;
1928 }
1929 else if (*(args[1]) && *(args[2])) {
1930 int level;
1931
1932 facility = get_log_facility(args[2]);
1933 if (facility < 0) {
1934 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1935 exit(1);
1936 }
1937
1938 level = 7; /* max syslog level = debug */
1939 if (*(args[3])) {
1940 level = get_log_level(args[3]);
1941 if (level < 0) {
1942 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1943 exit(1);
1944 }
1945 }
1946
Robert Tsai81ae1952007-12-05 10:47:29 +01001947 if (args[1][0] == '/') {
1948 logsrv.u.addr.sa_family = AF_UNIX;
1949 logsrv.u.un = *str2sun(args[1]);
1950 } else {
1951 logsrv.u.addr.sa_family = AF_INET;
1952 logsrv.u.in = *str2sa(args[1]);
1953 if (!logsrv.u.in.sin_port) {
1954 logsrv.u.in.sin_port =
1955 htons(SYSLOG_PORT);
1956 }
1957 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001958
1959 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001960 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001961 curproxy->logfac1 = facility;
1962 curproxy->loglev1 = level;
1963 }
1964 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001965 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966 curproxy->logfac2 = facility;
1967 curproxy->loglev2 = level;
1968 }
1969 else {
1970 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1971 return -1;
1972 }
1973 }
1974 else {
1975 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1976 file, linenum);
1977 return -1;
1978 }
1979 }
1980 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001981 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1982 return 0;
1983
Willy Tarreaubaaee002006-06-26 02:48:02 +02001984 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001985#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001986 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1987 file, linenum, "source", "usesrc");
1988#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001989 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1990 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001991#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001992 return -1;
1993 }
1994
1995 curproxy->source_addr = *str2sa(args[1]);
1996 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001997 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001998#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1999#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002000 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2001 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2002 file, linenum, "usesrc");
2003 return -1;
2004 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002005#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002006 if (!*args[3]) {
2007 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2008 file, linenum, "usesrc");
2009 return -1;
2010 }
2011
2012 if (!strcmp(args[3], "client")) {
2013 curproxy->options |= PR_O_TPXY_CLI;
2014 } else if (!strcmp(args[3], "clientip")) {
2015 curproxy->options |= PR_O_TPXY_CIP;
2016 } else {
2017 curproxy->options |= PR_O_TPXY_ADDR;
2018 curproxy->tproxy_addr = *str2sa(args[3]);
2019 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002020 global.last_checks |= LSTCHK_NETADM;
2021#if !defined(CONFIG_HAP_LINUX_TPROXY)
2022 global.last_checks |= LSTCHK_CTTPROXY;
2023#endif
2024#else /* no TPROXY support */
2025 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002026 file, linenum, "usesrc");
2027 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002028#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002029 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002030 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002031 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2032 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2033 file, linenum, "usesrc", "source");
2034 return -1;
2035 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002036 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2037 regex_t *preg;
2038 if (curproxy == &defproxy) {
2039 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2040 return -1;
2041 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002042 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2043 return 0;
2044
Willy Tarreaubaaee002006-06-26 02:48:02 +02002045 if (*(args[1]) == 0 || *(args[2]) == 0) {
2046 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2047 file, linenum, args[0]);
2048 return -1;
2049 }
2050
2051 preg = calloc(1, sizeof(regex_t));
2052 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2053 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2054 return -1;
2055 }
2056
2057 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2058 if (err) {
2059 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2060 file, linenum, *err);
2061 return -1;
2062 }
2063 }
2064 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2065 regex_t *preg;
2066 if (curproxy == &defproxy) {
2067 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2068 return -1;
2069 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002070 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2071 return 0;
2072
Willy Tarreaubaaee002006-06-26 02:48:02 +02002073 if (*(args[1]) == 0) {
2074 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2075 return -1;
2076 }
2077
2078 preg = calloc(1, sizeof(regex_t));
2079 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2080 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2081 return -1;
2082 }
2083
2084 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2085 }
2086 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2087 regex_t *preg;
2088 if (curproxy == &defproxy) {
2089 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2090 return -1;
2091 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002092 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2093 return 0;
2094
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 if (*(args[1]) == 0) {
2096 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2097 return -1;
2098 }
2099
2100 preg = calloc(1, sizeof(regex_t));
2101 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2102 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2103 return -1;
2104 }
2105
2106 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2107 }
2108 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2109 regex_t *preg;
2110 if (curproxy == &defproxy) {
2111 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2112 return -1;
2113 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002114 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2115 return 0;
2116
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 if (*(args[1]) == 0) {
2118 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2119 return -1;
2120 }
2121
2122 preg = calloc(1, sizeof(regex_t));
2123 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2124 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2125 return -1;
2126 }
2127
2128 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2129 }
2130 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2131 regex_t *preg;
2132 if (curproxy == &defproxy) {
2133 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2134 return -1;
2135 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002136 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2137 return 0;
2138
Willy Tarreaubaaee002006-06-26 02:48:02 +02002139 if (*(args[1]) == 0) {
2140 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2141 return -1;
2142 }
2143
2144 preg = calloc(1, sizeof(regex_t));
2145 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2146 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2147 return -1;
2148 }
2149
2150 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2151 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002152 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2153 regex_t *preg;
2154 if (curproxy == &defproxy) {
2155 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2156 return -1;
2157 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002158 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2159 return 0;
2160
Willy Tarreaub8750a82006-09-03 09:56:00 +02002161 if (*(args[1]) == 0) {
2162 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2163 return -1;
2164 }
2165
2166 preg = calloc(1, sizeof(regex_t));
2167 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2168 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2169 return -1;
2170 }
2171
2172 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2173 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002174 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2175 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002176 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002177 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2178 return -1;
2179 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002180 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2181 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002182
Willy Tarreau977b8e42006-12-29 14:19:17 +01002183 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002184 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2185 file, linenum, args[0]);
2186 return -1;
2187 }
2188
2189 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002190 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002191 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2192 }
2193
2194 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2195 }
2196 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2197 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002198 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002199 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2200 return -1;
2201 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002202 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2203 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002204
Willy Tarreau977b8e42006-12-29 14:19:17 +01002205 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002206 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2207 file, linenum, args[0]);
2208 return -1;
2209 }
2210
2211 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002212 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002213 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2214 }
2215
2216 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2219 regex_t *preg;
2220 if (curproxy == &defproxy) {
2221 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2222 return -1;
2223 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002224 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2225 return 0;
2226
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227 if (*(args[1]) == 0 || *(args[2]) == 0) {
2228 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2229 file, linenum, args[0]);
2230 return -1;
2231 }
2232
2233 preg = calloc(1, sizeof(regex_t));
2234 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2235 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2236 return -1;
2237 }
2238
2239 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2240 if (err) {
2241 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2242 file, linenum, *err);
2243 return -1;
2244 }
2245 }
2246 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2247 regex_t *preg;
2248 if (curproxy == &defproxy) {
2249 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2250 return -1;
2251 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002252 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2253 return 0;
2254
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 if (*(args[1]) == 0) {
2256 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2257 return -1;
2258 }
2259
2260 preg = calloc(1, sizeof(regex_t));
2261 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2262 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2263 return -1;
2264 }
2265
2266 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2267 }
2268 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2269 regex_t *preg;
2270 if (curproxy == &defproxy) {
2271 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2272 return -1;
2273 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002274 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2275 return 0;
2276
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277 if (*(args[1]) == 0) {
2278 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2279 return -1;
2280 }
2281
2282 preg = calloc(1, sizeof(regex_t));
2283 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2284 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2285 return -1;
2286 }
2287
2288 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2289 }
2290 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2291 regex_t *preg;
2292 if (curproxy == &defproxy) {
2293 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2294 return -1;
2295 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002296 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2297 return 0;
2298
Willy Tarreaubaaee002006-06-26 02:48:02 +02002299 if (*(args[1]) == 0) {
2300 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2301 return -1;
2302 }
2303
2304 preg = calloc(1, sizeof(regex_t));
2305 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2306 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2307 return -1;
2308 }
2309
2310 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2311 }
2312 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2313 regex_t *preg;
2314 if (curproxy == &defproxy) {
2315 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2316 return -1;
2317 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002318 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2319 return 0;
2320
Willy Tarreaubaaee002006-06-26 02:48:02 +02002321 if (*(args[1]) == 0) {
2322 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2323 return -1;
2324 }
2325
2326 preg = calloc(1, sizeof(regex_t));
2327 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2328 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2329 return -1;
2330 }
2331
2332 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2333 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002334 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2335 regex_t *preg;
2336 if (curproxy == &defproxy) {
2337 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2338 return -1;
2339 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002340 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2341 return 0;
2342
Willy Tarreaub8750a82006-09-03 09:56:00 +02002343 if (*(args[1]) == 0) {
2344 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2345 return -1;
2346 }
2347
2348 preg = calloc(1, sizeof(regex_t));
2349 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2350 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2351 return -1;
2352 }
2353
2354 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2355 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2357 if (curproxy == &defproxy) {
2358 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2359 return -1;
2360 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002361 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2362 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363
2364 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2365 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2366 return 0;
2367 }
2368
2369 if (*(args[1]) == 0) {
2370 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2371 return -1;
2372 }
2373
2374 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2375 }
2376 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2377 regex_t *preg;
2378
2379 if (*(args[1]) == 0 || *(args[2]) == 0) {
2380 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2381 file, linenum, args[0]);
2382 return -1;
2383 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002384 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2385 return 0;
2386
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387 preg = calloc(1, sizeof(regex_t));
2388 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2389 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2390 return -1;
2391 }
2392
2393 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2394 if (err) {
2395 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2396 file, linenum, *err);
2397 return -1;
2398 }
2399 }
2400 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2401 regex_t *preg;
2402 if (curproxy == &defproxy) {
2403 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2404 return -1;
2405 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002406 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2407 return 0;
2408
Willy Tarreaubaaee002006-06-26 02:48:02 +02002409 if (*(args[1]) == 0) {
2410 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2411 return -1;
2412 }
2413
2414 preg = calloc(1, sizeof(regex_t));
2415 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2416 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2417 return -1;
2418 }
2419
2420 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2421 if (err) {
2422 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2423 file, linenum, *err);
2424 return -1;
2425 }
2426 }
2427 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2428 regex_t *preg;
2429 if (curproxy == &defproxy) {
2430 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2431 return -1;
2432 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002433 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2434 return 0;
2435
Willy Tarreaubaaee002006-06-26 02:48:02 +02002436 if (*(args[1]) == 0) {
2437 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2438 return -1;
2439 }
2440
2441 preg = calloc(1, sizeof(regex_t));
2442 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2443 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2444 return -1;
2445 }
2446
2447 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2448 if (err) {
2449 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2450 file, linenum, *err);
2451 return -1;
2452 }
2453 }
2454 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2455 regex_t *preg;
2456 if (curproxy == &defproxy) {
2457 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2458 return -1;
2459 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002460 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2461 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002462
2463 if (*(args[1]) == 0 || *(args[2]) == 0) {
2464 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2465 file, linenum, args[0]);
2466 return -1;
2467 }
2468
2469 preg = calloc(1, sizeof(regex_t));
2470 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2471 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2472 return -1;
2473 }
2474
2475 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2476 if (err) {
2477 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2478 file, linenum, *err);
2479 return -1;
2480 }
2481 }
2482 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2483 regex_t *preg;
2484 if (curproxy == &defproxy) {
2485 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2486 return -1;
2487 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002488 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2489 return 0;
2490
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491 if (*(args[1]) == 0) {
2492 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2493 return -1;
2494 }
2495
2496 preg = calloc(1, sizeof(regex_t));
2497 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2498 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2499 return -1;
2500 }
2501
2502 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2503 if (err) {
2504 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2505 file, linenum, *err);
2506 return -1;
2507 }
2508 }
2509 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2510 regex_t *preg;
2511 if (curproxy == &defproxy) {
2512 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2513 return -1;
2514 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002515 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2516 return 0;
2517
Willy Tarreaubaaee002006-06-26 02:48:02 +02002518 if (*(args[1]) == 0) {
2519 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2520 return -1;
2521 }
2522
2523 preg = calloc(1, sizeof(regex_t));
2524 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2525 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2526 return -1;
2527 }
2528
2529 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2530 if (err) {
2531 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2532 file, linenum, *err);
2533 return -1;
2534 }
2535 }
2536 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2537 if (curproxy == &defproxy) {
2538 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2539 return -1;
2540 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002541 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2542 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543
2544 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2545 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2546 return 0;
2547 }
2548
2549 if (*(args[1]) == 0) {
2550 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2551 return -1;
2552 }
2553
2554 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2555 }
2556 else if (!strcmp(args[0], "errorloc") ||
2557 !strcmp(args[0], "errorloc302") ||
2558 !strcmp(args[0], "errorloc303")) { /* error location */
2559 int errnum, errlen;
2560 char *err;
2561
Willy Tarreau977b8e42006-12-29 14:19:17 +01002562 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2563 return 0;
2564
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002566 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 return -1;
2568 }
2569
2570 errnum = atol(args[1]);
2571 if (!strcmp(args[0], "errorloc303")) {
2572 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2573 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2574 } else {
2575 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2576 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2577 }
2578
Willy Tarreau0f772532006-12-23 20:51:41 +01002579 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2580 if (http_err_codes[rc] == errnum) {
2581 if (curproxy->errmsg[rc].str)
2582 free(curproxy->errmsg[rc].str);
2583 curproxy->errmsg[rc].str = err;
2584 curproxy->errmsg[rc].len = errlen;
2585 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002588
2589 if (rc >= HTTP_ERR_SIZE) {
2590 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2591 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 free(err);
2593 }
2594 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002595 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2596 int errnum, errlen, fd;
2597 char *err;
2598 struct stat stat;
2599
2600 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2601 return 0;
2602
2603 if (*(args[2]) == 0) {
2604 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2605 return -1;
2606 }
2607
2608 fd = open(args[2], O_RDONLY);
2609 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2610 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2611 file, linenum, args[2], args[1]);
2612 if (fd >= 0)
2613 close(fd);
2614 return -1;
2615 }
2616
2617 if (stat.st_size <= BUFSIZE) {
2618 errlen = stat.st_size;
2619 } else {
2620 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2621 file, linenum, args[2], BUFSIZE);
2622 errlen = BUFSIZE;
2623 }
2624
2625 err = malloc(errlen); /* malloc() must succeed during parsing */
2626 errnum = read(fd, err, errlen);
2627 if (errnum != errlen) {
2628 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2629 file, linenum, args[2], args[1]);
2630 close(fd);
2631 free(err);
2632 return -1;
2633 }
2634 close(fd);
2635
2636 errnum = atol(args[1]);
2637 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2638 if (http_err_codes[rc] == errnum) {
2639 if (curproxy->errmsg[rc].str)
2640 free(curproxy->errmsg[rc].str);
2641 curproxy->errmsg[rc].str = err;
2642 curproxy->errmsg[rc].len = errlen;
2643 break;
2644 }
2645 }
2646
2647 if (rc >= HTTP_ERR_SIZE) {
2648 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2649 file, linenum, errnum);
2650 free(err);
2651 }
2652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002653 else {
Willy Tarreau6daf3432008-01-22 16:44:08 +01002654 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002655 return -1;
2656 }
2657 return 0;
2658}
2659
2660
2661/*
2662 * This function reads and parses the configuration file given in the argument.
2663 * returns 0 if OK, -1 if error.
2664 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002665int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002667 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668 FILE *f;
2669 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002670 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002671 int confsect = CFG_NONE;
2672
2673 struct proxy *curproxy = NULL;
2674 struct server *newsrv = NULL;
2675
2676 if ((f=fopen(file,"r")) == NULL)
2677 return -1;
2678
2679 init_default_instance();
2680
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002681 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002682 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002683 char *end;
2684 char *args[MAX_LINE_ARGS + 1];
2685 char *line = thisline;
2686
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 linenum++;
2688
2689 end = line + strlen(line);
2690
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002691 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2692 /* Check if we reached the limit and the last char is not \n.
2693 * Watch out for the last line without the terminating '\n'!
2694 */
2695 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2696 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002697 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002698 }
2699
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002701 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702 line++;
2703
2704 arg = 0;
2705 args[arg] = line;
2706
2707 while (*line && arg < MAX_LINE_ARGS) {
2708 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2709 * C equivalent value. Other combinations left unchanged (eg: \1).
2710 */
2711 if (*line == '\\') {
2712 int skip = 0;
2713 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2714 *line = line[1];
2715 skip = 1;
2716 }
2717 else if (line[1] == 'r') {
2718 *line = '\r';
2719 skip = 1;
2720 }
2721 else if (line[1] == 'n') {
2722 *line = '\n';
2723 skip = 1;
2724 }
2725 else if (line[1] == 't') {
2726 *line = '\t';
2727 skip = 1;
2728 }
2729 else if (line[1] == 'x') {
2730 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2731 unsigned char hex1, hex2;
2732 hex1 = toupper(line[2]) - '0';
2733 hex2 = toupper(line[3]) - '0';
2734 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2735 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2736 *line = (hex1<<4) + hex2;
2737 skip = 3;
2738 }
2739 else {
2740 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002741 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 }
2743 }
2744 if (skip) {
2745 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2746 end -= skip;
2747 }
2748 line++;
2749 }
2750 else if (*line == '#' || *line == '\n' || *line == '\r') {
2751 /* end of string, end of loop */
2752 *line = 0;
2753 break;
2754 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002755 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002757 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002758 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 line++;
2760 args[++arg] = line;
2761 }
2762 else {
2763 line++;
2764 }
2765 }
2766
2767 /* empty line */
2768 if (!**args)
2769 continue;
2770
Willy Tarreau540abe42007-05-02 20:50:16 +02002771 /* zero out remaining args and ensure that at least one entry
2772 * is zeroed out.
2773 */
2774 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 args[arg] = line;
2776 }
2777
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002778 if (!strcmp(args[0], "no")) {
2779 inv = 1;
2780 for (arg=0; *args[arg+1]; arg++)
2781 args[arg] = args[arg+1]; // shift args after inversion
2782 }
2783
2784 if (inv && strcmp(args[0], "option")) {
2785 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002786 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002787 }
2788
Willy Tarreau977b8e42006-12-29 14:19:17 +01002789 if (!strcmp(args[0], "listen") ||
2790 !strcmp(args[0], "frontend") ||
2791 !strcmp(args[0], "backend") ||
2792 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002793 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002794 confsect = CFG_LISTEN;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002795 if (cursection)
2796 free(cursection);
2797 cursection = strdup(args[0]);
2798 }
2799 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002800 confsect = CFG_GLOBAL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002801 if (cursection)
2802 free(cursection);
2803 cursection = strdup(args[0]);
2804 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002805 /* else it's a section keyword */
2806
2807 switch (confsect) {
2808 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002809 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002810 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002811 break;
2812 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002813 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002814 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815 break;
2816 default:
2817 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002818 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002820 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01002821 if (cursection)
2822 free(cursection);
2823 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002824 fclose(f);
2825
2826 /*
2827 * Now, check for the integrity of all that we have collected.
2828 */
2829
2830 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002831 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832
2833 if ((curproxy = proxy) == NULL) {
2834 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2835 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002836 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 }
2838
2839 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002840 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002841 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002842
Willy Tarreaubaaee002006-06-26 02:48:02 +02002843 if (curproxy->state == PR_STSTOPPED) {
2844 curproxy = curproxy->next;
2845 continue;
2846 }
2847
Willy Tarreau977b8e42006-12-29 14:19:17 +01002848 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2849 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 +01002850 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 cfgerr++;
2852 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002853 else if (curproxy->cap & PR_CAP_BE &&
2854 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002855 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002856 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002857 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2858 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 +01002859 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002860 cfgerr++;
2861 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002862
Willy Tarreau31682232007-11-29 15:38:04 +01002863 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002865 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002866 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002867 cfgerr++;
2868 }
2869#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2870 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002871 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002872 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873 cfgerr++;
2874 }
2875#endif
2876 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002877 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002878 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879 }
2880 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002881
2882 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002883 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002884 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002885 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002888 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002889 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 }
2891 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002892 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002893 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002894 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002895 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002896 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002897 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002898 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002899 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002900 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2901 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002902
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002903 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002904 file, proxy_type_str(curproxy), curproxy->id);
2905 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002906 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002907
2908 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2909 if ((newsrv = curproxy->srv) != NULL) {
2910 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2911 file, proxy_type_str(curproxy), curproxy->id);
2912 }
2913 }
2914
2915 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2917 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2918 file, curproxy->id);
2919 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002920 }
2921 }
2922
Willy Tarreau82936582007-11-30 15:20:09 +01002923 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2924 curproxy->options &= ~PR_O_DISABLE404;
2925 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2926 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2927 }
2928
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002929 /* if a default backend was specified, let's find it */
2930 if (curproxy->defbe.name) {
2931 struct proxy *target;
2932
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002933 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2934 if (!target) {
2935 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2936 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002937 cfgerr++;
2938 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002939 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2940 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002941 } else {
2942 free(curproxy->defbe.name);
2943 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002944 }
2945 }
2946
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002947 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002948 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2949 /* map jump target for ACT_SETBE in req_rep chain */
2950 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002951 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002952 struct proxy *target;
2953
Willy Tarreaua496b602006-12-17 23:15:24 +01002954 if (exp->action != ACT_SETBE)
2955 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002956
2957 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2958 if (!target) {
2959 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2960 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002961 cfgerr++;
2962 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002963 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2964 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002965 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002966 } else {
2967 free((void *)exp->replace);
2968 exp->replace = (const char *)target;
2969 }
2970 }
2971 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002972
2973 /* find the target proxy for 'use_backend' rules */
2974 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002975 struct proxy *target;
2976
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002977 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002978
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002979 if (!target) {
2980 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2981 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002982 cfgerr++;
2983 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002984 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2985 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002986 cfgerr++;
2987 } else {
2988 free((void *)rule->be.name);
2989 rule->be.backend = target;
2990 }
2991 }
2992
Willy Tarreau2738a142006-07-08 17:28:09 +02002993 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002994 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02002995 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002996 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002997 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002998 " | While not properly invalid, you will certainly encounter various problems\n"
2999 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003000 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003001 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003002 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003003
Willy Tarreau1fa31262007-12-03 00:36:16 +01003004 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3005 * We must still support older configurations, so let's find out whether those
3006 * parameters have been set or must be copied from contimeouts.
3007 */
3008 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003009 if (!curproxy->timeout.tarpit ||
3010 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003011 /* tarpit timeout not set. We search in the following order:
3012 * default.tarpit, curr.connect, default.connect.
3013 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003014 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003015 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003016 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003017 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003018 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003019 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003020 }
3021 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003022 (!curproxy->timeout.queue ||
3023 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003024 /* queue timeout not set. We search in the following order:
3025 * default.queue, curr.connect, default.connect.
3026 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003027 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003028 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003029 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003030 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003031 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003032 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003033 }
3034 }
3035
Willy Tarreauf3c69202006-07-09 16:42:34 +02003036 if (curproxy->options & PR_O_SSL3_CHK) {
3037 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3038 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3039 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3040 }
3041
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003042 /* The small pools required for the capture lists */
3043 if (curproxy->nb_req_cap)
3044 curproxy->req_cap_pool = create_pool("ptrcap",
3045 curproxy->nb_req_cap * sizeof(char *),
3046 MEM_F_SHARED);
3047 if (curproxy->nb_rsp_cap)
3048 curproxy->rsp_cap_pool = create_pool("ptrcap",
3049 curproxy->nb_rsp_cap * sizeof(char *),
3050 MEM_F_SHARED);
3051
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003052 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3053 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3054 MEM_F_SHARED);
3055
Willy Tarreau86034312006-12-29 00:10:33 +01003056 /* for backwards compatibility with "listen" instances, if
3057 * fullconn is not set but maxconn is set, then maxconn
3058 * is used.
3059 */
3060 if (!curproxy->fullconn)
3061 curproxy->fullconn = curproxy->maxconn;
3062
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 /* first, we will invert the servers list order */
3064 newsrv = NULL;
3065 while (curproxy->srv) {
3066 struct server *next;
3067
3068 next = curproxy->srv->next;
3069 curproxy->srv->next = newsrv;
3070 newsrv = curproxy->srv;
3071 if (!next)
3072 break;
3073 curproxy->srv = next;
3074 }
3075
Willy Tarreau20697042007-11-15 23:26:18 +01003076 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003077 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078
Willy Tarreaub625a082007-11-26 01:15:43 +01003079 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003080 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003081 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003082 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3083 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003084 else
3085 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086
3087 if (curproxy->options & PR_O_LOGASAP)
3088 curproxy->to_log &= ~LW_BYTES;
3089
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003091 * ensure that we're not cross-dressing a TCP server into HTTP.
3092 */
3093 newsrv = curproxy->srv;
3094 while (newsrv != NULL) {
3095 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3096 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3097 file, proxy_type_str(curproxy), curproxy->id, linenum);
3098 goto err;
3099 }
3100 newsrv = newsrv->next;
3101 }
3102
3103 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104 * If this server supports a maxconn parameter, it needs a dedicated
3105 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003106 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 */
3108 newsrv = curproxy->srv;
3109 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003110 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003111 /* Only 'minconn' was specified, or it was higher than or equal
3112 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3113 * this will avoid further useless expensive computations.
3114 */
3115 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003116 } else if (newsrv->maxconn && !newsrv->minconn) {
3117 /* minconn was not specified, so we set it to maxconn */
3118 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003119 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3120 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003121 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003122 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 }
3124
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003125 if (newsrv->trackit) {
3126 struct proxy *px;
3127 struct server *srv;
3128 char *pname, *sname;
3129
3130 pname = newsrv->trackit;
3131 sname = strrchr(pname, '/');
3132
3133 if (sname)
3134 *sname++ = '\0';
3135 else {
3136 sname = pname;
3137 pname = NULL;
3138 }
3139
3140 if (pname) {
3141 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3142 if (!px) {
3143 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3144 file, proxy_type_str(curproxy), curproxy->id,
3145 newsrv->id, pname);
3146 return -1;
3147 }
3148 } else
3149 px = curproxy;
3150
3151 srv = findserver(px, sname);
3152 if (!srv) {
3153 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3154 file, proxy_type_str(curproxy), curproxy->id,
3155 newsrv->id, sname);
3156 return -1;
3157 }
3158
3159 if (!(srv->state & SRV_CHECKED)) {
3160 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3161 "tracing as it does not have checks enabled.\n",
3162 file, proxy_type_str(curproxy), curproxy->id,
3163 newsrv->id, px->id, srv->id);
3164 return -1;
3165 }
3166
3167 if (curproxy != px &&
3168 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3169 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3170 "tracing: disable-on-404 option inconsistency.\n",
3171 file, proxy_type_str(curproxy), curproxy->id,
3172 newsrv->id, px->id, srv->id);
3173 return -1;
3174 }
3175
3176 newsrv->tracked = srv;
3177 newsrv->tracknext = srv->tracknext;
3178 srv->tracknext = newsrv;
3179
3180 free(newsrv->trackit);
3181 }
3182
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 newsrv = newsrv->next;
3184 }
3185
Willy Tarreaue6b98942007-10-29 01:09:36 +01003186 /* adjust this proxy's listeners */
3187 listener = curproxy->listen;
3188 while (listener) {
3189 if (curproxy->options & PR_O_TCP_NOLING)
3190 listener->options |= LI_O_NOLINGER;
3191 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003192 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003193 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003194 listener->accept = event_accept;
3195 listener->private = curproxy;
3196
3197 listener = listener->next;
3198 }
3199
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 curproxy = curproxy->next;
3201 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003202
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 if (cfgerr > 0) {
3204 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003205 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003207
3208 /*
3209 * Recount currently required checks.
3210 */
3211
3212 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3213 int optnum;
3214
3215 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3216 if (!(curproxy->options & cfg_opts[optnum].val))
3217 continue;
3218
3219 global.last_checks |= cfg_opts[optnum].checks;
3220 }
3221 }
3222
Willy Tarreau6daf3432008-01-22 16:44:08 +01003223 if (cursection)
3224 free(cursection);
3225 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003226 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003227
3228 err:
3229 if (cursection)
3230 free(cursection);
3231 cursection = NULL;
3232 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003233}
3234
3235
3236
3237/*
3238 * Local variables:
3239 * c-indent-level: 8
3240 * c-basic-offset: 8
3241 * End:
3242 */