blob: 90611cdaa83843c8bf666b53c76505e88e526079 [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 Tarreauee991362007-05-14 14:37:50 +0200974 if (val > 0)
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100975 __tv_from_ms(&curproxy->timeout.appsession, val);
Willy Tarreauee991362007-05-14 14:37:50 +0200976 else
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100977 tv_eternity(&curproxy->timeout.appsession);
Willy Tarreauee991362007-05-14 14:37:50 +0200978
Willy Tarreau51041c72007-09-09 21:56:53 +0200979 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
980 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200981 return -1;
982 }
983 } /* Url App Session */
984 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100985 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
986 return 0;
987
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
989 // if (curproxy == &defproxy) {
990 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
991 // return -1;
992 // }
993
994 if (curproxy->capture_name != NULL) {
995 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
996 // file, linenum, args[0]);
997 // return 0;
998 free(curproxy->capture_name);
999 }
1000
1001 if (*(args[4]) == 0) {
1002 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1003 file, linenum, args[0]);
1004 return -1;
1005 }
1006 curproxy->capture_name = strdup(args[2]);
1007 curproxy->capture_namelen = strlen(curproxy->capture_name);
1008 curproxy->capture_len = atol(args[4]);
1009 if (curproxy->capture_len >= CAPTURE_LEN) {
1010 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1011 file, linenum, CAPTURE_LEN - 1);
1012 curproxy->capture_len = CAPTURE_LEN - 1;
1013 }
1014 curproxy->to_log |= LW_COOKIE;
1015 }
1016 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1017 struct cap_hdr *hdr;
1018
1019 if (curproxy == &defproxy) {
1020 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1021 return -1;
1022 }
1023
1024 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1025 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1026 file, linenum, args[0], args[1]);
1027 return -1;
1028 }
1029
1030 hdr = calloc(sizeof(struct cap_hdr), 1);
1031 hdr->next = curproxy->req_cap;
1032 hdr->name = strdup(args[3]);
1033 hdr->namelen = strlen(args[3]);
1034 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001035 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036 hdr->index = curproxy->nb_req_cap++;
1037 curproxy->req_cap = hdr;
1038 curproxy->to_log |= LW_REQHDR;
1039 }
1040 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1041 struct cap_hdr *hdr;
1042
1043 if (curproxy == &defproxy) {
1044 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1045 return -1;
1046 }
1047
1048 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1049 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1050 file, linenum, args[0], args[1]);
1051 return -1;
1052 }
1053 hdr = calloc(sizeof(struct cap_hdr), 1);
1054 hdr->next = curproxy->rsp_cap;
1055 hdr->name = strdup(args[3]);
1056 hdr->namelen = strlen(args[3]);
1057 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001058 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059 hdr->index = curproxy->nb_rsp_cap++;
1060 curproxy->rsp_cap = hdr;
1061 curproxy->to_log |= LW_RSPHDR;
1062 }
1063 else {
1064 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1065 file, linenum, args[0]);
1066 return -1;
1067 }
1068 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001069 else if (!strcmp(args[0], "contimeout") || !strcmp(args[0], "clitimeout") ||
1070 !strcmp(args[0], "srvtimeout") || !strcmp(args[0], "timeout")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001071
Willy Tarreaue219db72007-12-03 01:30:13 +01001072 /* either we have {con|srv|cli}timeout <value> or we have the
1073 * new form: timeout <type> <value>. The parser needs the word
1074 * preceeding the value.
1075 */
1076 const char **start_arg = (const char **)args;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001077
Willy Tarreaue219db72007-12-03 01:30:13 +01001078 if (strcmp(args[0], "timeout") == 0)
1079 start_arg++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001080
Willy Tarreaue219db72007-12-03 01:30:13 +01001081 snprintf(trash, sizeof(trash), "error near '%s'", args[0]);
1082 rc = proxy_parse_timeout(start_arg, curproxy, &defproxy, trash, sizeof(trash));
1083 if (rc < 0) {
1084 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001085 return -1;
1086 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001087 if (rc > 0)
1088 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 }
1090 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001091 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1092 return 0;
1093
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 if (*(args[1]) == 0) {
1095 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1096 file, linenum, args[0]);
1097 return -1;
1098 }
1099 curproxy->conn_retries = atol(args[1]);
1100 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001101 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1102 int pol = ACL_COND_NONE;
1103 struct acl_cond *cond;
1104
1105 if (!strcmp(args[1], "if"))
1106 pol = ACL_COND_IF;
1107 else if (!strcmp(args[1], "unless"))
1108 pol = ACL_COND_UNLESS;
1109
1110 if (pol == ACL_COND_NONE) {
1111 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1112 file, linenum, args[0]);
1113 return -1;
1114 }
1115
1116 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1117 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1118 file, linenum);
1119 return -1;
1120 }
1121 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1122 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001123 else if (!strcmp(args[0], "redirect")) {
1124 int pol = ACL_COND_NONE;
1125 struct acl_cond *cond;
1126 struct redirect_rule *rule;
1127 int cur_arg;
1128 int type = REDIRECT_TYPE_NONE;
1129 int code = 302;
1130 char *destination = NULL;
1131
1132 cur_arg = 1;
1133 while (*(args[cur_arg])) {
1134 if (!strcmp(args[cur_arg], "location")) {
1135 if (!*args[cur_arg + 1]) {
1136 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1137 file, linenum, args[0], args[cur_arg]);
1138 return -1;
1139 }
1140
1141 type = REDIRECT_TYPE_LOCATION;
1142 cur_arg++;
1143 destination = args[cur_arg];
1144 }
1145 else if (!strcmp(args[cur_arg], "prefix")) {
1146 if (!*args[cur_arg + 1]) {
1147 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1148 file, linenum, args[0], args[cur_arg]);
1149 return -1;
1150 }
1151
1152 type = REDIRECT_TYPE_PREFIX;
1153 cur_arg++;
1154 destination = args[cur_arg];
1155 }
1156 else if (!strcmp(args[cur_arg],"code")) {
1157 if (!*args[cur_arg + 1]) {
1158 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1159 file, linenum, args[0]);
1160 return -1;
1161 }
1162 cur_arg++;
1163 code = atol(args[cur_arg]);
1164 if (code < 301 || code > 303) {
1165 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1166 file, linenum, args[0], code);
1167 return -1;
1168 }
1169 }
1170 else if (!strcmp(args[cur_arg], "if")) {
1171 pol = ACL_COND_IF;
1172 cur_arg++;
1173 break;
1174 }
1175 else if (!strcmp(args[cur_arg], "unless")) {
1176 pol = ACL_COND_UNLESS;
1177 cur_arg++;
1178 break;
1179 }
1180 else {
1181 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1182 file, linenum, args[0], args[cur_arg]);
1183 return -1;
1184 }
1185 cur_arg++;
1186 }
1187
1188 if (type == REDIRECT_TYPE_NONE) {
1189 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1190 file, linenum, args[0]);
1191 return -1;
1192 }
1193
1194 if (pol == ACL_COND_NONE) {
1195 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1196 file, linenum, args[0]);
1197 return -1;
1198 }
1199
1200 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1201 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1202 file, linenum, args[0]);
1203 return -1;
1204 }
1205
1206 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1207 rule->cond = cond;
1208 rule->rdr_str = strdup(destination);
1209 rule->rdr_len = strlen(destination);
1210 rule->type = type;
1211 rule->code = code;
1212 LIST_INIT(&rule->list);
1213 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1214 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001215 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1216 int pol = ACL_COND_NONE;
1217 struct acl_cond *cond;
1218 struct switching_rule *rule;
1219
1220 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1221 return 0;
1222
1223 if (*(args[1]) == 0) {
1224 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1225 return -1;
1226 }
1227
1228 if (!strcmp(args[2], "if"))
1229 pol = ACL_COND_IF;
1230 else if (!strcmp(args[2], "unless"))
1231 pol = ACL_COND_UNLESS;
1232
1233 if (pol == ACL_COND_NONE) {
1234 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1235 file, linenum, args[0]);
1236 return -1;
1237 }
1238
1239 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1240 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1241 file, linenum);
1242 return -1;
1243 }
1244
1245 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1246 rule->cond = cond;
1247 rule->be.name = strdup(args[1]);
1248 LIST_INIT(&rule->list);
1249 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001251 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001252 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1253 return 0;
1254
Willy Tarreaubaaee002006-06-26 02:48:02 +02001255 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1256 curproxy->uri_auth = NULL; /* we must detach from the default config */
1257
1258 if (*(args[1]) == 0) {
1259 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1260 return -1;
1261 } else if (!strcmp(args[1], "uri")) {
1262 if (*(args[2]) == 0) {
1263 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1264 return -1;
1265 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1266 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1267 return -1;
1268 }
1269 } else if (!strcmp(args[1], "realm")) {
1270 if (*(args[2]) == 0) {
1271 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1272 return -1;
1273 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1274 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1275 return -1;
1276 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001277 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001278 unsigned interval;
1279
1280 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1281 if (err) {
1282 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1283 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001284 return -1;
1285 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1286 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1287 return -1;
1288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001289 } else if (!strcmp(args[1], "auth")) {
1290 if (*(args[2]) == 0) {
1291 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1292 return -1;
1293 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1294 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1295 return -1;
1296 }
1297 } else if (!strcmp(args[1], "scope")) {
1298 if (*(args[2]) == 0) {
1299 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1300 return -1;
1301 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1302 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1303 return -1;
1304 }
1305 } else if (!strcmp(args[1], "enable")) {
1306 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1307 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1308 return -1;
1309 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001310 } else if (!strcmp(args[1], "hide-version")) {
1311 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1312 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1313 return -1;
1314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001316 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001317 file, linenum, args[0]);
1318 return -1;
1319 }
1320 }
1321 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001322 int optnum;
1323
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001324 if (*(args[1]) == '\0') {
1325 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1326 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001327 return -1;
1328 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001329
1330 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1331 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1332 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1333 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001334
1335 if (!inv)
1336 curproxy->options |= cfg_opts[optnum].val;
1337 else
1338 curproxy->options &= ~cfg_opts[optnum].val;
1339
Willy Tarreau13943ab2006-12-31 00:24:10 +01001340 return 0;
1341 }
1342 }
1343
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001344 if (inv) {
1345 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1346 file, linenum, args[1]);
1347 return -1;
1348 }
1349
Willy Tarreau13943ab2006-12-31 00:24:10 +01001350 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001351 /* generate a complete HTTP log */
1352 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1353 else if (!strcmp(args[1], "tcplog"))
1354 /* generate a detailed TCP log */
1355 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001356 else if (!strcmp(args[1], "tcpka")) {
1357 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001358 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1359 return 0;
1360
1361 if (curproxy->cap & PR_CAP_FE)
1362 curproxy->options |= PR_O_TCP_CLI_KA;
1363 if (curproxy->cap & PR_CAP_BE)
1364 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365 }
1366 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001367 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1368 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001369 /* use HTTP request to check servers' health */
1370 if (curproxy->check_req != NULL) {
1371 free(curproxy->check_req);
1372 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001373 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001374 curproxy->options &= ~PR_O_SMTP_CHK;
1375 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 if (!*args[2]) { /* no argument */
1377 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1378 curproxy->check_len = strlen(DEF_CHECK_REQ);
1379 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001380 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001381 curproxy->check_req = (char *)malloc(reqlen);
1382 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1383 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1384 } else { /* more arguments : METHOD URI [HTTP_VER] */
1385 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1386 if (*args[4])
1387 reqlen += strlen(args[4]);
1388 else
1389 reqlen += strlen("HTTP/1.0");
1390
1391 curproxy->check_req = (char *)malloc(reqlen);
1392 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1393 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1394 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001395 }
1396 else if (!strcmp(args[1], "ssl-hello-chk")) {
1397 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001398 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1399 return 0;
1400
Willy Tarreauf3c69202006-07-09 16:42:34 +02001401 if (curproxy->check_req != NULL) {
1402 free(curproxy->check_req);
1403 }
1404 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001405 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001406 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001407 }
Willy Tarreau23677902007-05-08 23:50:35 +02001408 else if (!strcmp(args[1], "smtpchk")) {
1409 /* use SMTP request to check servers' health */
1410 if (curproxy->check_req != NULL) {
1411 free(curproxy->check_req);
1412 }
1413 curproxy->options &= ~PR_O_HTTP_CHK;
1414 curproxy->options &= ~PR_O_SSL3_CHK;
1415 curproxy->options |= PR_O_SMTP_CHK;
1416
1417 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1418 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1419 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1420 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1421 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1422 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1423 curproxy->check_req = (char *)malloc(reqlen);
1424 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1425 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1426 } else {
1427 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1428 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1429 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1430 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1431 }
1432 }
1433 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001434 else if (!strcmp(args[1], "forwardfor")) {
1435 /* insert x-forwarded-for field, but not for the
1436 * IP address listed as an except.
1437 */
1438 if (*(args[2])) {
1439 if (!strcmp(args[2], "except")) {
1440 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1441 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1442 file, linenum, args[0]);
1443 return -1;
1444 }
1445 /* flush useless bits */
1446 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1447 } else {
1448 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1449 file, linenum, args[0]);
1450 return -1;
1451 }
1452 }
1453 curproxy->options |= PR_O_FWDFOR;
1454 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455 else {
1456 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1457 return -1;
1458 }
1459 return 0;
1460 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001461 else if (!strcmp(args[0], "default_backend")) {
1462 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1463 return 0;
1464
1465 if (*(args[1]) == 0) {
1466 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1467 return -1;
1468 }
1469 if (curproxy->defbe.name)
1470 free(curproxy->defbe.name);
1471 curproxy->defbe.name = strdup(args[1]);
1472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001474 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1475 return 0;
1476
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001477 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1478 file, linenum, args[0]);
1479
Willy Tarreaubaaee002006-06-26 02:48:02 +02001480 /* enable reconnections to dispatch */
1481 curproxy->options |= PR_O_REDISP;
1482 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001483 else if (!strcmp(args[0], "http-check")) {
1484 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1485 return 0;
1486
1487 if (strcmp(args[1], "disable-on-404") == 0) {
1488 /* enable a graceful server shutdown on an HTTP 404 response */
1489 curproxy->options |= PR_O_DISABLE404;
1490 }
1491 else {
1492 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1493 return -1;
1494 }
1495 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001496 else if (!strcmp(args[0], "monitor")) {
1497 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1498 return 0;
1499
1500 if (strcmp(args[1], "fail") == 0) {
1501 /* add a condition to fail monitor requests */
1502 int pol = ACL_COND_NONE;
1503 struct acl_cond *cond;
1504
1505 if (!strcmp(args[2], "if"))
1506 pol = ACL_COND_IF;
1507 else if (!strcmp(args[2], "unless"))
1508 pol = ACL_COND_UNLESS;
1509
1510 if (pol == ACL_COND_NONE) {
1511 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1512 file, linenum, args[0], args[1]);
1513 return -1;
1514 }
1515
1516 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1517 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1518 file, linenum, args[0], args[1]);
1519 return -1;
1520 }
1521 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1522 }
1523 else {
1524 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1525 return -1;
1526 }
1527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001528#ifdef TPROXY
1529 else if (!strcmp(args[0], "transparent")) {
1530 /* enable transparent proxy connections */
1531 curproxy->options |= PR_O_TRANSP;
1532 }
1533#endif
1534 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001535 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1536 return 0;
1537
Willy Tarreaubaaee002006-06-26 02:48:02 +02001538 if (*(args[1]) == 0) {
1539 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1540 return -1;
1541 }
1542 curproxy->maxconn = atol(args[1]);
1543 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001544 else if (!strcmp(args[0], "backlog")) { /* backlog */
1545 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1546 return 0;
1547
1548 if (*(args[1]) == 0) {
1549 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1550 return -1;
1551 }
1552 curproxy->backlog = atol(args[1]);
1553 }
Willy Tarreau86034312006-12-29 00:10:33 +01001554 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001555 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1556 return 0;
1557
Willy Tarreau86034312006-12-29 00:10:33 +01001558 if (*(args[1]) == 0) {
1559 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1560 return -1;
1561 }
1562 curproxy->fullconn = atol(args[1]);
1563 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1565 if (*(args[1]) == 0) {
1566 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1567 return -1;
1568 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001569 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1570 if (err) {
1571 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1572 file, linenum, *err);
1573 return -1;
1574 }
1575 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001576 }
1577 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1578 if (curproxy == &defproxy) {
1579 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1580 return -1;
1581 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001582 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1583 return 0;
1584
Willy Tarreaubaaee002006-06-26 02:48:02 +02001585 if (strchr(args[1], ':') == NULL) {
1586 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1587 return -1;
1588 }
1589 curproxy->dispatch_addr = *str2sa(args[1]);
1590 }
1591 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001592 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1593 return 0;
1594
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001595 memcpy(trash, "error near 'balance'", 19);
1596 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1597 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1598 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001599 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600 }
1601 else if (!strcmp(args[0], "server")) { /* server address */
1602 int cur_arg;
1603 char *rport;
1604 char *raddr;
1605 short realport;
1606 int do_check;
1607
1608 if (curproxy == &defproxy) {
1609 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1610 return -1;
1611 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001612 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1613 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614
1615 if (!*args[2]) {
1616 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1617 file, linenum, args[0]);
1618 return -1;
1619 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001620
1621 err = invalid_char(args[1]);
1622 if (err) {
1623 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1624 file, linenum, *err, args[1]);
1625 return -1;
1626 }
1627
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1629 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1630 return -1;
1631 }
1632
1633 /* the servers are linked backwards first */
1634 newsrv->next = curproxy->srv;
1635 curproxy->srv = newsrv;
1636 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001637 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638
1639 LIST_INIT(&newsrv->pendconns);
1640 do_check = 0;
1641 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001642 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001643 newsrv->id = strdup(args[1]);
1644
1645 /* several ways to check the port component :
1646 * - IP => port=+0, relative
1647 * - IP: => port=+0, relative
1648 * - IP:N => port=N, absolute
1649 * - IP:+N => port=+N, relative
1650 * - IP:-N => port=-N, relative
1651 */
1652 raddr = strdup(args[2]);
1653 rport = strchr(raddr, ':');
1654 if (rport) {
1655 *rport++ = 0;
1656 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001657 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 newsrv->state |= SRV_MAPPORTS;
1659 } else {
1660 realport = 0;
1661 newsrv->state |= SRV_MAPPORTS;
1662 }
1663
1664 newsrv->addr = *str2sa(raddr);
1665 newsrv->addr.sin_port = htons(realport);
1666 free(raddr);
1667
1668 newsrv->curfd = -1; /* no health-check in progress */
1669 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001670 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1671 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001672 newsrv->rise = DEF_RISETIME;
1673 newsrv->fall = DEF_FALLTIME;
1674 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001675 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001676 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001677 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001678
Willy Tarreaubaaee002006-06-26 02:48:02 +02001679 cur_arg = 3;
1680 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001681 if (!strcmp(args[cur_arg], "id")) {
1682 struct server *target;
1683
1684 if (!*args[cur_arg + 1]) {
1685 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1686 file, linenum, args[cur_arg]);
1687 return -1;
1688 }
1689
1690 newsrv->puid = atol(args[cur_arg + 1]);
1691
1692 if (newsrv->puid< 1001) {
1693 Alert("parsing [%s:%d]: custom id has to be > 1000",
1694 file, linenum);
1695 return -1;
1696 }
1697
1698 for (target = proxy->srv; target; target = target->next)
1699 if (newsrv != target && newsrv->puid == target->puid) {
1700 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1701 file, linenum, newsrv->id, target->id);
1702 return -1;
1703 }
1704 cur_arg += 2;
1705 }
1706 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001707 newsrv->cookie = strdup(args[cur_arg + 1]);
1708 newsrv->cklen = strlen(args[cur_arg + 1]);
1709 cur_arg += 2;
1710 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001711 else if (!strcmp(args[cur_arg], "redir")) {
1712 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1713 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1714 cur_arg += 2;
1715 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001716 else if (!strcmp(args[cur_arg], "rise")) {
1717 newsrv->rise = atol(args[cur_arg + 1]);
1718 newsrv->health = newsrv->rise;
1719 cur_arg += 2;
1720 }
1721 else if (!strcmp(args[cur_arg], "fall")) {
1722 newsrv->fall = atol(args[cur_arg + 1]);
1723 cur_arg += 2;
1724 }
1725 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001726 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1727 if (err) {
1728 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1729 file, linenum, *err, newsrv->id);
1730 return -1;
1731 }
1732 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001733 cur_arg += 2;
1734 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001735 else if (!strcmp(args[cur_arg], "fastinter")) {
1736 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1737 if (err) {
1738 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1739 file, linenum, *err, newsrv->id);
1740 return -1;
1741 }
1742 newsrv->fastinter = val;
1743 cur_arg += 2;
1744 }
1745 else if (!strcmp(args[cur_arg], "downinter")) {
1746 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1747 if (err) {
1748 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1749 file, linenum, *err, newsrv->id);
1750 return -1;
1751 }
1752 newsrv->downinter = val;
1753 cur_arg += 2;
1754 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001755 else if (!strcmp(args[cur_arg], "addr")) {
1756 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001757 cur_arg += 2;
1758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001759 else if (!strcmp(args[cur_arg], "port")) {
1760 newsrv->check_port = atol(args[cur_arg + 1]);
1761 cur_arg += 2;
1762 }
1763 else if (!strcmp(args[cur_arg], "backup")) {
1764 newsrv->state |= SRV_BACKUP;
1765 cur_arg ++;
1766 }
1767 else if (!strcmp(args[cur_arg], "weight")) {
1768 int w;
1769 w = atol(args[cur_arg + 1]);
1770 if (w < 1 || w > 256) {
1771 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1772 file, linenum, newsrv->id, w);
1773 return -1;
1774 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001775 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776 cur_arg += 2;
1777 }
1778 else if (!strcmp(args[cur_arg], "minconn")) {
1779 newsrv->minconn = atol(args[cur_arg + 1]);
1780 cur_arg += 2;
1781 }
1782 else if (!strcmp(args[cur_arg], "maxconn")) {
1783 newsrv->maxconn = atol(args[cur_arg + 1]);
1784 cur_arg += 2;
1785 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001786 else if (!strcmp(args[cur_arg], "maxqueue")) {
1787 newsrv->maxqueue = atol(args[cur_arg + 1]);
1788 cur_arg += 2;
1789 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001790 else if (!strcmp(args[cur_arg], "slowstart")) {
1791 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001792 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001793 if (err) {
1794 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1795 file, linenum, *err, newsrv->id);
1796 return -1;
1797 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001798 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001799 cur_arg += 2;
1800 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001801 else if (!strcmp(args[cur_arg], "track")) {
1802
1803 if (!*args[cur_arg + 1]) {
1804 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1805 file, linenum);
1806 return -1;
1807 }
1808
1809 newsrv->trackit = strdup(args[cur_arg + 1]);
1810
1811 cur_arg += 2;
1812 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001813 else if (!strcmp(args[cur_arg], "check")) {
1814 global.maxsock++;
1815 do_check = 1;
1816 cur_arg += 1;
1817 }
1818 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1819 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001820#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001821 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1822 file, linenum, "source", "usesrc");
1823#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001824 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1825 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001826#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001827 return -1;
1828 }
1829 newsrv->state |= SRV_BIND_SRC;
1830 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1831 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001832 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001833#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1834#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001835 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001836 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1837 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001838 return -1;
1839 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001840#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001841 if (!*args[cur_arg + 1]) {
1842 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1843 file, linenum, "usesrc");
1844 return -1;
1845 }
1846 if (!strcmp(args[cur_arg + 1], "client")) {
1847 newsrv->state |= SRV_TPROXY_CLI;
1848 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1849 newsrv->state |= SRV_TPROXY_CIP;
1850 } else {
1851 newsrv->state |= SRV_TPROXY_ADDR;
1852 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1853 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001854 global.last_checks |= LSTCHK_NETADM;
1855#if !defined(CONFIG_HAP_LINUX_TPROXY)
1856 global.last_checks |= LSTCHK_CTTPROXY;
1857#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001858 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001859#else /* no TPROXY support */
1860 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001861 file, linenum, "usesrc");
1862 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001863#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001864 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001865 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001866 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1867 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1868 file, linenum, "usesrc", "source");
1869 return -1;
1870 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001872 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 +02001873 file, linenum, newsrv->id);
1874 return -1;
1875 }
1876 }
1877
1878 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001879 if (newsrv->trackit) {
1880 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1881 file, linenum);
1882 return -1;
1883 }
1884
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001885 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1886 newsrv->check_port = newsrv->check_addr.sin_port;
1887
Willy Tarreaubaaee002006-06-26 02:48:02 +02001888 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1889 newsrv->check_port = realport; /* by default */
1890 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001891 /* not yet valid, because no port was set on
1892 * the server either. We'll check if we have
1893 * a known port on the first listener.
1894 */
1895 struct listener *l;
1896 l = curproxy->listen;
1897 if (l) {
1898 int port;
1899 port = (l->addr.ss_family == AF_INET6)
1900 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1901 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1902 newsrv->check_port = port;
1903 }
1904 }
1905 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1907 file, linenum, newsrv->id);
1908 return -1;
1909 }
1910 newsrv->state |= SRV_CHECKED;
1911 }
1912
1913 if (newsrv->state & SRV_BACKUP)
1914 curproxy->srv_bck++;
1915 else
1916 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001917
1918 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 }
1920 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001921 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001922 int facility;
1923
1924 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1925 curproxy->logfac1 = global.logfac1;
1926 curproxy->logsrv1 = global.logsrv1;
1927 curproxy->loglev1 = global.loglev1;
1928 curproxy->logfac2 = global.logfac2;
1929 curproxy->logsrv2 = global.logsrv2;
1930 curproxy->loglev2 = global.loglev2;
1931 }
1932 else if (*(args[1]) && *(args[2])) {
1933 int level;
1934
1935 facility = get_log_facility(args[2]);
1936 if (facility < 0) {
1937 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1938 exit(1);
1939 }
1940
1941 level = 7; /* max syslog level = debug */
1942 if (*(args[3])) {
1943 level = get_log_level(args[3]);
1944 if (level < 0) {
1945 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1946 exit(1);
1947 }
1948 }
1949
Robert Tsai81ae1952007-12-05 10:47:29 +01001950 if (args[1][0] == '/') {
1951 logsrv.u.addr.sa_family = AF_UNIX;
1952 logsrv.u.un = *str2sun(args[1]);
1953 } else {
1954 logsrv.u.addr.sa_family = AF_INET;
1955 logsrv.u.in = *str2sa(args[1]);
1956 if (!logsrv.u.in.sin_port) {
1957 logsrv.u.in.sin_port =
1958 htons(SYSLOG_PORT);
1959 }
1960 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001961
1962 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001963 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001964 curproxy->logfac1 = facility;
1965 curproxy->loglev1 = level;
1966 }
1967 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001968 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001969 curproxy->logfac2 = facility;
1970 curproxy->loglev2 = level;
1971 }
1972 else {
1973 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1974 return -1;
1975 }
1976 }
1977 else {
1978 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1979 file, linenum);
1980 return -1;
1981 }
1982 }
1983 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001984 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1985 return 0;
1986
Willy Tarreaubaaee002006-06-26 02:48:02 +02001987 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001988#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001989 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1990 file, linenum, "source", "usesrc");
1991#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001992 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1993 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001994#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001995 return -1;
1996 }
1997
1998 curproxy->source_addr = *str2sa(args[1]);
1999 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01002000 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002001#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2002#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002003 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2004 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2005 file, linenum, "usesrc");
2006 return -1;
2007 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002008#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002009 if (!*args[3]) {
2010 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2011 file, linenum, "usesrc");
2012 return -1;
2013 }
2014
2015 if (!strcmp(args[3], "client")) {
2016 curproxy->options |= PR_O_TPXY_CLI;
2017 } else if (!strcmp(args[3], "clientip")) {
2018 curproxy->options |= PR_O_TPXY_CIP;
2019 } else {
2020 curproxy->options |= PR_O_TPXY_ADDR;
2021 curproxy->tproxy_addr = *str2sa(args[3]);
2022 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002023 global.last_checks |= LSTCHK_NETADM;
2024#if !defined(CONFIG_HAP_LINUX_TPROXY)
2025 global.last_checks |= LSTCHK_CTTPROXY;
2026#endif
2027#else /* no TPROXY support */
2028 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002029 file, linenum, "usesrc");
2030 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002031#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002032 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002033 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002034 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2035 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2036 file, linenum, "usesrc", "source");
2037 return -1;
2038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002039 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2040 regex_t *preg;
2041 if (curproxy == &defproxy) {
2042 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2043 return -1;
2044 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002045 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2046 return 0;
2047
Willy Tarreaubaaee002006-06-26 02:48:02 +02002048 if (*(args[1]) == 0 || *(args[2]) == 0) {
2049 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2050 file, linenum, args[0]);
2051 return -1;
2052 }
2053
2054 preg = calloc(1, sizeof(regex_t));
2055 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2056 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2057 return -1;
2058 }
2059
2060 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2061 if (err) {
2062 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2063 file, linenum, *err);
2064 return -1;
2065 }
2066 }
2067 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2068 regex_t *preg;
2069 if (curproxy == &defproxy) {
2070 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2071 return -1;
2072 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002073 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2074 return 0;
2075
Willy Tarreaubaaee002006-06-26 02:48:02 +02002076 if (*(args[1]) == 0) {
2077 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2078 return -1;
2079 }
2080
2081 preg = calloc(1, sizeof(regex_t));
2082 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2083 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2084 return -1;
2085 }
2086
2087 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2088 }
2089 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2090 regex_t *preg;
2091 if (curproxy == &defproxy) {
2092 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2093 return -1;
2094 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002095 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2096 return 0;
2097
Willy Tarreaubaaee002006-06-26 02:48:02 +02002098 if (*(args[1]) == 0) {
2099 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2100 return -1;
2101 }
2102
2103 preg = calloc(1, sizeof(regex_t));
2104 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2105 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2106 return -1;
2107 }
2108
2109 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2110 }
2111 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2112 regex_t *preg;
2113 if (curproxy == &defproxy) {
2114 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2115 return -1;
2116 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002117 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2118 return 0;
2119
Willy Tarreaubaaee002006-06-26 02:48:02 +02002120 if (*(args[1]) == 0) {
2121 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2122 return -1;
2123 }
2124
2125 preg = calloc(1, sizeof(regex_t));
2126 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2127 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2128 return -1;
2129 }
2130
2131 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2132 }
2133 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2134 regex_t *preg;
2135 if (curproxy == &defproxy) {
2136 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2137 return -1;
2138 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002139 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2140 return 0;
2141
Willy Tarreaubaaee002006-06-26 02:48:02 +02002142 if (*(args[1]) == 0) {
2143 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2144 return -1;
2145 }
2146
2147 preg = calloc(1, sizeof(regex_t));
2148 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2149 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2150 return -1;
2151 }
2152
2153 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2154 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002155 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2156 regex_t *preg;
2157 if (curproxy == &defproxy) {
2158 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2159 return -1;
2160 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002161 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2162 return 0;
2163
Willy Tarreaub8750a82006-09-03 09:56:00 +02002164 if (*(args[1]) == 0) {
2165 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2166 return -1;
2167 }
2168
2169 preg = calloc(1, sizeof(regex_t));
2170 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2171 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2172 return -1;
2173 }
2174
2175 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2176 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002177 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2178 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002179 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002180 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2181 return -1;
2182 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002183 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2184 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002185
Willy Tarreau977b8e42006-12-29 14:19:17 +01002186 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002187 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2188 file, linenum, args[0]);
2189 return -1;
2190 }
2191
2192 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002193 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002194 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2195 }
2196
2197 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2198 }
2199 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2200 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002201 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002202 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2203 return -1;
2204 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002205 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2206 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002207
Willy Tarreau977b8e42006-12-29 14:19:17 +01002208 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002209 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2210 file, linenum, args[0]);
2211 return -1;
2212 }
2213
2214 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002215 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002216 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2217 }
2218
2219 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002221 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2222 regex_t *preg;
2223 if (curproxy == &defproxy) {
2224 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2225 return -1;
2226 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002227 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2228 return 0;
2229
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230 if (*(args[1]) == 0 || *(args[2]) == 0) {
2231 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2232 file, linenum, args[0]);
2233 return -1;
2234 }
2235
2236 preg = calloc(1, sizeof(regex_t));
2237 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2238 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2239 return -1;
2240 }
2241
2242 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2243 if (err) {
2244 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2245 file, linenum, *err);
2246 return -1;
2247 }
2248 }
2249 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2250 regex_t *preg;
2251 if (curproxy == &defproxy) {
2252 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2253 return -1;
2254 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002255 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2256 return 0;
2257
Willy Tarreaubaaee002006-06-26 02:48:02 +02002258 if (*(args[1]) == 0) {
2259 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2260 return -1;
2261 }
2262
2263 preg = calloc(1, sizeof(regex_t));
2264 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2265 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2266 return -1;
2267 }
2268
2269 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2270 }
2271 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2272 regex_t *preg;
2273 if (curproxy == &defproxy) {
2274 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2275 return -1;
2276 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002277 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2278 return 0;
2279
Willy Tarreaubaaee002006-06-26 02:48:02 +02002280 if (*(args[1]) == 0) {
2281 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2282 return -1;
2283 }
2284
2285 preg = calloc(1, sizeof(regex_t));
2286 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2287 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2288 return -1;
2289 }
2290
2291 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2292 }
2293 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2294 regex_t *preg;
2295 if (curproxy == &defproxy) {
2296 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2297 return -1;
2298 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002299 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2300 return 0;
2301
Willy Tarreaubaaee002006-06-26 02:48:02 +02002302 if (*(args[1]) == 0) {
2303 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2304 return -1;
2305 }
2306
2307 preg = calloc(1, sizeof(regex_t));
2308 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2309 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2310 return -1;
2311 }
2312
2313 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2314 }
2315 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2316 regex_t *preg;
2317 if (curproxy == &defproxy) {
2318 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2319 return -1;
2320 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002321 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2322 return 0;
2323
Willy Tarreaubaaee002006-06-26 02:48:02 +02002324 if (*(args[1]) == 0) {
2325 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2326 return -1;
2327 }
2328
2329 preg = calloc(1, sizeof(regex_t));
2330 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2331 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2332 return -1;
2333 }
2334
2335 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2336 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002337 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2338 regex_t *preg;
2339 if (curproxy == &defproxy) {
2340 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2341 return -1;
2342 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002343 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2344 return 0;
2345
Willy Tarreaub8750a82006-09-03 09:56:00 +02002346 if (*(args[1]) == 0) {
2347 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2348 return -1;
2349 }
2350
2351 preg = calloc(1, sizeof(regex_t));
2352 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2353 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2354 return -1;
2355 }
2356
2357 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2358 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2360 if (curproxy == &defproxy) {
2361 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2362 return -1;
2363 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002364 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2365 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366
2367 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2368 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2369 return 0;
2370 }
2371
2372 if (*(args[1]) == 0) {
2373 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2374 return -1;
2375 }
2376
2377 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2378 }
2379 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2380 regex_t *preg;
2381
2382 if (*(args[1]) == 0 || *(args[2]) == 0) {
2383 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2384 file, linenum, args[0]);
2385 return -1;
2386 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002387 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2388 return 0;
2389
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 preg = calloc(1, sizeof(regex_t));
2391 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2392 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2393 return -1;
2394 }
2395
2396 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2397 if (err) {
2398 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2399 file, linenum, *err);
2400 return -1;
2401 }
2402 }
2403 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2404 regex_t *preg;
2405 if (curproxy == &defproxy) {
2406 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2407 return -1;
2408 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002409 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2410 return 0;
2411
Willy Tarreaubaaee002006-06-26 02:48:02 +02002412 if (*(args[1]) == 0) {
2413 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2414 return -1;
2415 }
2416
2417 preg = calloc(1, sizeof(regex_t));
2418 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2419 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2420 return -1;
2421 }
2422
2423 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2424 if (err) {
2425 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2426 file, linenum, *err);
2427 return -1;
2428 }
2429 }
2430 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2431 regex_t *preg;
2432 if (curproxy == &defproxy) {
2433 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2434 return -1;
2435 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002436 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2437 return 0;
2438
Willy Tarreaubaaee002006-06-26 02:48:02 +02002439 if (*(args[1]) == 0) {
2440 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2441 return -1;
2442 }
2443
2444 preg = calloc(1, sizeof(regex_t));
2445 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2446 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2447 return -1;
2448 }
2449
2450 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2451 if (err) {
2452 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2453 file, linenum, *err);
2454 return -1;
2455 }
2456 }
2457 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2458 regex_t *preg;
2459 if (curproxy == &defproxy) {
2460 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2461 return -1;
2462 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002463 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2464 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002465
2466 if (*(args[1]) == 0 || *(args[2]) == 0) {
2467 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2468 file, linenum, args[0]);
2469 return -1;
2470 }
2471
2472 preg = calloc(1, sizeof(regex_t));
2473 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2474 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2475 return -1;
2476 }
2477
2478 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2479 if (err) {
2480 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2481 file, linenum, *err);
2482 return -1;
2483 }
2484 }
2485 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2486 regex_t *preg;
2487 if (curproxy == &defproxy) {
2488 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2489 return -1;
2490 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002491 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2492 return 0;
2493
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494 if (*(args[1]) == 0) {
2495 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2496 return -1;
2497 }
2498
2499 preg = calloc(1, sizeof(regex_t));
2500 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2501 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2502 return -1;
2503 }
2504
2505 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2506 if (err) {
2507 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2508 file, linenum, *err);
2509 return -1;
2510 }
2511 }
2512 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2513 regex_t *preg;
2514 if (curproxy == &defproxy) {
2515 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2516 return -1;
2517 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002518 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2519 return 0;
2520
Willy Tarreaubaaee002006-06-26 02:48:02 +02002521 if (*(args[1]) == 0) {
2522 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2523 return -1;
2524 }
2525
2526 preg = calloc(1, sizeof(regex_t));
2527 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2528 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2529 return -1;
2530 }
2531
2532 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2533 if (err) {
2534 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2535 file, linenum, *err);
2536 return -1;
2537 }
2538 }
2539 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2540 if (curproxy == &defproxy) {
2541 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2542 return -1;
2543 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002544 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2545 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002546
2547 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2548 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2549 return 0;
2550 }
2551
2552 if (*(args[1]) == 0) {
2553 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2554 return -1;
2555 }
2556
2557 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2558 }
2559 else if (!strcmp(args[0], "errorloc") ||
2560 !strcmp(args[0], "errorloc302") ||
2561 !strcmp(args[0], "errorloc303")) { /* error location */
2562 int errnum, errlen;
2563 char *err;
2564
Willy Tarreau977b8e42006-12-29 14:19:17 +01002565 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2566 return 0;
2567
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002569 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 return -1;
2571 }
2572
2573 errnum = atol(args[1]);
2574 if (!strcmp(args[0], "errorloc303")) {
2575 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2576 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2577 } else {
2578 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2579 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2580 }
2581
Willy Tarreau0f772532006-12-23 20:51:41 +01002582 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2583 if (http_err_codes[rc] == errnum) {
2584 if (curproxy->errmsg[rc].str)
2585 free(curproxy->errmsg[rc].str);
2586 curproxy->errmsg[rc].str = err;
2587 curproxy->errmsg[rc].len = errlen;
2588 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002591
2592 if (rc >= HTTP_ERR_SIZE) {
2593 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2594 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 free(err);
2596 }
2597 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002598 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2599 int errnum, errlen, fd;
2600 char *err;
2601 struct stat stat;
2602
2603 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2604 return 0;
2605
2606 if (*(args[2]) == 0) {
2607 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2608 return -1;
2609 }
2610
2611 fd = open(args[2], O_RDONLY);
2612 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2613 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2614 file, linenum, args[2], args[1]);
2615 if (fd >= 0)
2616 close(fd);
2617 return -1;
2618 }
2619
2620 if (stat.st_size <= BUFSIZE) {
2621 errlen = stat.st_size;
2622 } else {
2623 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2624 file, linenum, args[2], BUFSIZE);
2625 errlen = BUFSIZE;
2626 }
2627
2628 err = malloc(errlen); /* malloc() must succeed during parsing */
2629 errnum = read(fd, err, errlen);
2630 if (errnum != errlen) {
2631 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2632 file, linenum, args[2], args[1]);
2633 close(fd);
2634 free(err);
2635 return -1;
2636 }
2637 close(fd);
2638
2639 errnum = atol(args[1]);
2640 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2641 if (http_err_codes[rc] == errnum) {
2642 if (curproxy->errmsg[rc].str)
2643 free(curproxy->errmsg[rc].str);
2644 curproxy->errmsg[rc].str = err;
2645 curproxy->errmsg[rc].len = errlen;
2646 break;
2647 }
2648 }
2649
2650 if (rc >= HTTP_ERR_SIZE) {
2651 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2652 file, linenum, errnum);
2653 free(err);
2654 }
2655 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002656 else {
Willy Tarreau6daf3432008-01-22 16:44:08 +01002657 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002658 return -1;
2659 }
2660 return 0;
2661}
2662
2663
2664/*
2665 * This function reads and parses the configuration file given in the argument.
2666 * returns 0 if OK, -1 if error.
2667 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002668int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002669{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002670 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002671 FILE *f;
2672 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002674 int confsect = CFG_NONE;
2675
2676 struct proxy *curproxy = NULL;
2677 struct server *newsrv = NULL;
2678
2679 if ((f=fopen(file,"r")) == NULL)
2680 return -1;
2681
2682 init_default_instance();
2683
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002684 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002685 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002686 char *end;
2687 char *args[MAX_LINE_ARGS + 1];
2688 char *line = thisline;
2689
Willy Tarreaubaaee002006-06-26 02:48:02 +02002690 linenum++;
2691
2692 end = line + strlen(line);
2693
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002694 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2695 /* Check if we reached the limit and the last char is not \n.
2696 * Watch out for the last line without the terminating '\n'!
2697 */
2698 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2699 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002700 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002701 }
2702
Willy Tarreaubaaee002006-06-26 02:48:02 +02002703 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002704 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 line++;
2706
2707 arg = 0;
2708 args[arg] = line;
2709
2710 while (*line && arg < MAX_LINE_ARGS) {
2711 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2712 * C equivalent value. Other combinations left unchanged (eg: \1).
2713 */
2714 if (*line == '\\') {
2715 int skip = 0;
2716 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2717 *line = line[1];
2718 skip = 1;
2719 }
2720 else if (line[1] == 'r') {
2721 *line = '\r';
2722 skip = 1;
2723 }
2724 else if (line[1] == 'n') {
2725 *line = '\n';
2726 skip = 1;
2727 }
2728 else if (line[1] == 't') {
2729 *line = '\t';
2730 skip = 1;
2731 }
2732 else if (line[1] == 'x') {
2733 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2734 unsigned char hex1, hex2;
2735 hex1 = toupper(line[2]) - '0';
2736 hex2 = toupper(line[3]) - '0';
2737 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2738 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2739 *line = (hex1<<4) + hex2;
2740 skip = 3;
2741 }
2742 else {
2743 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002744 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002745 }
2746 }
2747 if (skip) {
2748 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2749 end -= skip;
2750 }
2751 line++;
2752 }
2753 else if (*line == '#' || *line == '\n' || *line == '\r') {
2754 /* end of string, end of loop */
2755 *line = 0;
2756 break;
2757 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002758 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002760 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002761 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002762 line++;
2763 args[++arg] = line;
2764 }
2765 else {
2766 line++;
2767 }
2768 }
2769
2770 /* empty line */
2771 if (!**args)
2772 continue;
2773
Willy Tarreau540abe42007-05-02 20:50:16 +02002774 /* zero out remaining args and ensure that at least one entry
2775 * is zeroed out.
2776 */
2777 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002778 args[arg] = line;
2779 }
2780
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002781 if (!strcmp(args[0], "no")) {
2782 inv = 1;
2783 for (arg=0; *args[arg+1]; arg++)
2784 args[arg] = args[arg+1]; // shift args after inversion
2785 }
2786
2787 if (inv && strcmp(args[0], "option")) {
2788 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002789 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002790 }
2791
Willy Tarreau977b8e42006-12-29 14:19:17 +01002792 if (!strcmp(args[0], "listen") ||
2793 !strcmp(args[0], "frontend") ||
2794 !strcmp(args[0], "backend") ||
2795 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002796 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002797 confsect = CFG_LISTEN;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002798 if (cursection)
2799 free(cursection);
2800 cursection = strdup(args[0]);
2801 }
2802 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002803 confsect = CFG_GLOBAL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002804 if (cursection)
2805 free(cursection);
2806 cursection = strdup(args[0]);
2807 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808 /* else it's a section keyword */
2809
2810 switch (confsect) {
2811 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002812 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002813 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002814 break;
2815 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002816 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002817 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002818 break;
2819 default:
2820 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002821 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002822 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01002824 if (cursection)
2825 free(cursection);
2826 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002827 fclose(f);
2828
2829 /*
2830 * Now, check for the integrity of all that we have collected.
2831 */
2832
2833 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002834 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002835
2836 if ((curproxy = proxy) == NULL) {
2837 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2838 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002839 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 }
2841
2842 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002843 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002844 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002845
Willy Tarreaubaaee002006-06-26 02:48:02 +02002846 if (curproxy->state == PR_STSTOPPED) {
2847 curproxy = curproxy->next;
2848 continue;
2849 }
2850
Willy Tarreau977b8e42006-12-29 14:19:17 +01002851 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2852 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 +01002853 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002854 cfgerr++;
2855 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002856 else if (curproxy->cap & PR_CAP_BE &&
2857 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002858 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002859 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002860 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2861 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 +01002862 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002863 cfgerr++;
2864 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002865
Willy Tarreau31682232007-11-29 15:38:04 +01002866 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002867 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002868 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002869 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 cfgerr++;
2871 }
2872#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2873 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002874 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002875 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002876 cfgerr++;
2877 }
2878#endif
2879 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002880 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002881 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882 }
2883 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002884
2885 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002887 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002888 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002891 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002892 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002893 }
2894 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002895 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002896 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002898 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002899 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002900 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002901 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002902 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002903 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2904 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002905
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002906 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002907 file, proxy_type_str(curproxy), curproxy->id);
2908 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002909 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002910
2911 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2912 if ((newsrv = curproxy->srv) != NULL) {
2913 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2914 file, proxy_type_str(curproxy), curproxy->id);
2915 }
2916 }
2917
2918 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2920 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2921 file, curproxy->id);
2922 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002923 }
2924 }
2925
Willy Tarreau82936582007-11-30 15:20:09 +01002926 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2927 curproxy->options &= ~PR_O_DISABLE404;
2928 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2929 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2930 }
2931
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002932 /* if a default backend was specified, let's find it */
2933 if (curproxy->defbe.name) {
2934 struct proxy *target;
2935
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002936 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2937 if (!target) {
2938 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2939 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002940 cfgerr++;
2941 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002942 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2943 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002944 } else {
2945 free(curproxy->defbe.name);
2946 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947 }
2948 }
2949
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002950 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002951 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2952 /* map jump target for ACT_SETBE in req_rep chain */
2953 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002954 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002955 struct proxy *target;
2956
Willy Tarreaua496b602006-12-17 23:15:24 +01002957 if (exp->action != ACT_SETBE)
2958 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002959
2960 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2961 if (!target) {
2962 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2963 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002964 cfgerr++;
2965 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002966 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2967 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002968 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002969 } else {
2970 free((void *)exp->replace);
2971 exp->replace = (const char *)target;
2972 }
2973 }
2974 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002975
2976 /* find the target proxy for 'use_backend' rules */
2977 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002978 struct proxy *target;
2979
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002980 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002981
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002982 if (!target) {
2983 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2984 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002985 cfgerr++;
2986 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002987 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2988 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002989 cfgerr++;
2990 } else {
2991 free((void *)rule->be.name);
2992 rule->be.backend = target;
2993 }
2994 }
2995
Willy Tarreau2738a142006-07-08 17:28:09 +02002996 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002997 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->timeout.client)) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02002998 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002999 (!tv_isset(&curproxy->timeout.connect) || !tv_isset(&curproxy->timeout.server))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003000 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003001 " | While not properly invalid, you will certainly encounter various problems\n"
3002 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003003 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003004 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003005 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003006
Willy Tarreau1fa31262007-12-03 00:36:16 +01003007 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3008 * We must still support older configurations, so let's find out whether those
3009 * parameters have been set or must be copied from contimeouts.
3010 */
3011 if (curproxy != &defproxy) {
Willy Tarreau51c9bde2008-01-06 13:40:03 +01003012 if (!tv_isset(&curproxy->timeout.tarpit) ||
3013 __tv_iseq(&curproxy->timeout.tarpit, &defproxy.timeout.tarpit)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003014 /* tarpit timeout not set. We search in the following order:
3015 * default.tarpit, curr.connect, default.connect.
3016 */
3017 if (tv_isset(&defproxy.timeout.tarpit))
3018 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003019 else if (tv_isset(&curproxy->timeout.connect))
3020 curproxy->timeout.tarpit = curproxy->timeout.connect;
3021 else if (tv_isset(&defproxy.timeout.connect))
3022 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003023 }
3024 if ((curproxy->cap & PR_CAP_BE) &&
3025 (!tv_isset(&curproxy->timeout.queue) ||
3026 __tv_iseq(&curproxy->timeout.queue, &defproxy.timeout.queue))) {
3027 /* queue timeout not set. We search in the following order:
3028 * default.queue, curr.connect, default.connect.
3029 */
3030 if (tv_isset(&defproxy.timeout.queue))
3031 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003032 else if (tv_isset(&curproxy->timeout.connect))
3033 curproxy->timeout.queue = curproxy->timeout.connect;
3034 else if (tv_isset(&defproxy.timeout.connect))
3035 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003036 }
3037 }
3038
Willy Tarreauf3c69202006-07-09 16:42:34 +02003039 if (curproxy->options & PR_O_SSL3_CHK) {
3040 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3041 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3042 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3043 }
3044
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003045 /* The small pools required for the capture lists */
3046 if (curproxy->nb_req_cap)
3047 curproxy->req_cap_pool = create_pool("ptrcap",
3048 curproxy->nb_req_cap * sizeof(char *),
3049 MEM_F_SHARED);
3050 if (curproxy->nb_rsp_cap)
3051 curproxy->rsp_cap_pool = create_pool("ptrcap",
3052 curproxy->nb_rsp_cap * sizeof(char *),
3053 MEM_F_SHARED);
3054
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003055 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3056 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3057 MEM_F_SHARED);
3058
Willy Tarreau86034312006-12-29 00:10:33 +01003059 /* for backwards compatibility with "listen" instances, if
3060 * fullconn is not set but maxconn is set, then maxconn
3061 * is used.
3062 */
3063 if (!curproxy->fullconn)
3064 curproxy->fullconn = curproxy->maxconn;
3065
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 /* first, we will invert the servers list order */
3067 newsrv = NULL;
3068 while (curproxy->srv) {
3069 struct server *next;
3070
3071 next = curproxy->srv->next;
3072 curproxy->srv->next = newsrv;
3073 newsrv = curproxy->srv;
3074 if (!next)
3075 break;
3076 curproxy->srv = next;
3077 }
3078
Willy Tarreau20697042007-11-15 23:26:18 +01003079 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003080 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081
Willy Tarreaub625a082007-11-26 01:15:43 +01003082 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003083 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003084 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003085 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3086 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003087 else
3088 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089
3090 if (curproxy->options & PR_O_LOGASAP)
3091 curproxy->to_log &= ~LW_BYTES;
3092
Willy Tarreaubaaee002006-06-26 02:48:02 +02003093 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003094 * ensure that we're not cross-dressing a TCP server into HTTP.
3095 */
3096 newsrv = curproxy->srv;
3097 while (newsrv != NULL) {
3098 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3099 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3100 file, proxy_type_str(curproxy), curproxy->id, linenum);
3101 goto err;
3102 }
3103 newsrv = newsrv->next;
3104 }
3105
3106 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 * If this server supports a maxconn parameter, it needs a dedicated
3108 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003109 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 */
3111 newsrv = curproxy->srv;
3112 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003113 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003114 /* Only 'minconn' was specified, or it was higher than or equal
3115 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3116 * this will avoid further useless expensive computations.
3117 */
3118 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003119 } else if (newsrv->maxconn && !newsrv->minconn) {
3120 /* minconn was not specified, so we set it to maxconn */
3121 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003122 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3123 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003124 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003125 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 }
3127
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003128 if (newsrv->trackit) {
3129 struct proxy *px;
3130 struct server *srv;
3131 char *pname, *sname;
3132
3133 pname = newsrv->trackit;
3134 sname = strrchr(pname, '/');
3135
3136 if (sname)
3137 *sname++ = '\0';
3138 else {
3139 sname = pname;
3140 pname = NULL;
3141 }
3142
3143 if (pname) {
3144 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3145 if (!px) {
3146 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3147 file, proxy_type_str(curproxy), curproxy->id,
3148 newsrv->id, pname);
3149 return -1;
3150 }
3151 } else
3152 px = curproxy;
3153
3154 srv = findserver(px, sname);
3155 if (!srv) {
3156 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3157 file, proxy_type_str(curproxy), curproxy->id,
3158 newsrv->id, sname);
3159 return -1;
3160 }
3161
3162 if (!(srv->state & SRV_CHECKED)) {
3163 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3164 "tracing as it does not have checks enabled.\n",
3165 file, proxy_type_str(curproxy), curproxy->id,
3166 newsrv->id, px->id, srv->id);
3167 return -1;
3168 }
3169
3170 if (curproxy != px &&
3171 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3172 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3173 "tracing: disable-on-404 option inconsistency.\n",
3174 file, proxy_type_str(curproxy), curproxy->id,
3175 newsrv->id, px->id, srv->id);
3176 return -1;
3177 }
3178
3179 newsrv->tracked = srv;
3180 newsrv->tracknext = srv->tracknext;
3181 srv->tracknext = newsrv;
3182
3183 free(newsrv->trackit);
3184 }
3185
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 newsrv = newsrv->next;
3187 }
3188
Willy Tarreaue6b98942007-10-29 01:09:36 +01003189 /* adjust this proxy's listeners */
3190 listener = curproxy->listen;
3191 while (listener) {
3192 if (curproxy->options & PR_O_TCP_NOLING)
3193 listener->options |= LI_O_NOLINGER;
3194 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003195 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003196 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003197 listener->accept = event_accept;
3198 listener->private = curproxy;
3199
3200 listener = listener->next;
3201 }
3202
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 curproxy = curproxy->next;
3204 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003205
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 if (cfgerr > 0) {
3207 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003208 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003210
3211 /*
3212 * Recount currently required checks.
3213 */
3214
3215 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3216 int optnum;
3217
3218 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3219 if (!(curproxy->options & cfg_opts[optnum].val))
3220 continue;
3221
3222 global.last_checks |= cfg_opts[optnum].checks;
3223 }
3224 }
3225
Willy Tarreau6daf3432008-01-22 16:44:08 +01003226 if (cursection)
3227 free(cursection);
3228 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003229 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003230
3231 err:
3232 if (cursection)
3233 free(cursection);
3234 cursection = NULL;
3235 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003236}
3237
3238
3239
3240/*
3241 * Local variables:
3242 * c-indent-level: 8
3243 * c-basic-offset: 8
3244 * End:
3245 */