blob: 9ca8ae64f46a3235645984e5b36ad2f11b4ae681 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau0b4ed902007-03-26 00:18:40 +02004 * Copyright 2000-2007 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 Tarreaub80c2302007-11-30 20:51:32 +0100590 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200591 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200592
Willy Tarreauee991362007-05-14 14:37:50 +0200593 /* Timeouts are defined as -1, so we cannot use the zeroed area
594 * as a default value.
595 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100596 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200597
598 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100600 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601
602 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100603 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604 curproxy->listen = str2listener(args[2], curproxy->listen);
605 if (!curproxy->listen)
606 return -1;
607 global.maxsock++;
608 }
609
610 /* set default values */
611 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100613 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200614 curproxy->except_net = defproxy.except_net;
615 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616
Willy Tarreau977b8e42006-12-29 14:19:17 +0100617 if (curproxy->cap & PR_CAP_FE) {
618 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100619 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100620
621 /* initialize error relocations */
622 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
623 if (defproxy.errmsg[rc].str)
624 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
625 }
626
627 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629
Willy Tarreau977b8e42006-12-29 14:19:17 +0100630 if (curproxy->cap & PR_CAP_BE) {
631 curproxy->fullconn = defproxy.fullconn;
632 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633
Willy Tarreau977b8e42006-12-29 14:19:17 +0100634 if (defproxy.check_req)
635 curproxy->check_req = strdup(defproxy.check_req);
636 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200637
Willy Tarreau977b8e42006-12-29 14:19:17 +0100638 if (defproxy.cookie_name)
639 curproxy->cookie_name = strdup(defproxy.cookie_name);
640 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100641
642 if (defproxy.url_param_name)
643 curproxy->url_param_name = strdup(defproxy.url_param_name);
644 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100645 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646
Willy Tarreau977b8e42006-12-29 14:19:17 +0100647 if (curproxy->cap & PR_CAP_RS) {
648 if (defproxy.capture_name)
649 curproxy->capture_name = strdup(defproxy.capture_name);
650 curproxy->capture_namelen = defproxy.capture_namelen;
651 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200653
Willy Tarreau977b8e42006-12-29 14:19:17 +0100654 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100655 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100656 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100657 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100658 curproxy->uri_auth = defproxy.uri_auth;
659 curproxy->mon_net = defproxy.mon_net;
660 curproxy->mon_mask = defproxy.mon_mask;
661 if (defproxy.monitor_uri)
662 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
663 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100664 if (defproxy.defbe.name)
665 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100666 }
667
668 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100669 curproxy->timeout.connect = defproxy.timeout.connect;
670 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100671 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100672 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100673 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100674 curproxy->source_addr = defproxy.source_addr;
675 }
676
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 curproxy->mode = defproxy.mode;
678 curproxy->logfac1 = defproxy.logfac1;
679 curproxy->logsrv1 = defproxy.logsrv1;
680 curproxy->loglev1 = defproxy.loglev1;
681 curproxy->logfac2 = defproxy.logfac2;
682 curproxy->logsrv2 = defproxy.logsrv2;
683 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200684 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100685 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
686 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200687
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 return 0;
689 }
690 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
691 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100692 /* FIXME-20070101: we should do this too at the end of the
693 * config parsing to free all default values.
694 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200695 if (defproxy.check_req) free(defproxy.check_req);
696 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100697 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200699 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100700 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100701
702 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
703 if (defproxy.errmsg[rc].len)
704 free(defproxy.errmsg[rc].str);
705 }
706
Willy Tarreaubaaee002006-06-26 02:48:02 +0200707 /* we cannot free uri_auth because it might already be used */
708 init_default_instance();
709 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100710 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 return 0;
712 }
713 else if (curproxy == NULL) {
714 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
715 return -1;
716 }
717
Willy Tarreau977b8e42006-12-29 14:19:17 +0100718
719 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200720 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100721 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200722 if (curproxy == &defproxy) {
723 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
724 return -1;
725 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100726 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
727 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200728
729 if (strchr(args[1], ':') == NULL) {
730 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
731 file, linenum, args[0]);
732 return -1;
733 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100734
735 last_listen = curproxy->listen;
736 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200737 if (!curproxy->listen)
738 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100739 if (*args[2]) {
740#ifdef CONFIG_HAP_LINUX_TPROXY
741 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
742 struct listener *l;
743
744 for (l = curproxy->listen; l != last_listen; l = l->next)
745 l->options |= LI_O_FOREIGN;
746 }
747 else {
748 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
749 file, linenum, args[0]);
750 return -1;
751 }
752#else
753 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
754 file, linenum, args[0]);
755 return -1;
756#endif
757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200758 global.maxsock++;
759 return 0;
760 }
761 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
762 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
763 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
764 file, linenum, args[0]);
765 return -1;
766 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100767 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
768 return 0;
769
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 /* flush useless bits */
771 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
772 return 0;
773 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200774 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100775 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
776 return 0;
777
Willy Tarreau1c47f852006-07-09 08:22:27 +0200778 if (!*args[1]) {
779 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
780 file, linenum, args[0]);
781 return -1;
782 }
783
784 if (curproxy->monitor_uri != NULL)
785 free(curproxy->monitor_uri);
786
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100787 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200788 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100789 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200790 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
791
792 return 0;
793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200794 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
795 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
796 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
797 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
798 else {
799 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
800 return -1;
801 }
802 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100803 else if (!strcmp(args[0], "id")) {
804 struct proxy *target;
805
806 if (curproxy == &defproxy) {
807 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
808 file, linenum, args[0]);
809 return -1;
810 }
811
812 if (!*args[1]) {
813 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
814 file, linenum, args[0]);
815 return -1;
816 }
817
818 curproxy->uuid = atol(args[1]);
819
820 if (curproxy->uuid < 1001) {
821 Alert("parsing [%s:%d]: custom id has to be > 1000",
822 file, linenum);
823 return -1;
824 }
825
826 for (target = proxy; target; target = target->next)
827 if (curproxy != target && curproxy->uuid == target->uuid) {
828 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
829 file, linenum, curproxy->id, target->id);
830 return -1;
831 }
832 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
834 curproxy->state = PR_STSTOPPED;
835 }
836 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
837 curproxy->state = PR_STNEW;
838 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200839 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100840 err = invalid_char(args[1]);
841 if (err) {
842 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
843 file, linenum, *err, args[1]);
844 return -1;
845 }
846
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200847 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
848 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
849 file, linenum, args[1]);
850 return -1;
851 }
852 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200853 else if (!strcmp(args[0], "cookie")) { /* cookie name */
854 int cur_arg;
855 // if (curproxy == &defproxy) {
856 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
857 // return -1;
858 // }
859
Willy Tarreau977b8e42006-12-29 14:19:17 +0100860 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
861 return 0;
862
Willy Tarreaubaaee002006-06-26 02:48:02 +0200863 if (curproxy->cookie_name != NULL) {
864 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
865 // file, linenum);
866 // return 0;
867 free(curproxy->cookie_name);
868 }
869
870 if (*(args[1]) == 0) {
871 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
872 file, linenum, args[0]);
873 return -1;
874 }
875 curproxy->cookie_name = strdup(args[1]);
876 curproxy->cookie_len = strlen(curproxy->cookie_name);
877
878 cur_arg = 2;
879 while (*(args[cur_arg])) {
880 if (!strcmp(args[cur_arg], "rewrite")) {
881 curproxy->options |= PR_O_COOK_RW;
882 }
883 else if (!strcmp(args[cur_arg], "indirect")) {
884 curproxy->options |= PR_O_COOK_IND;
885 }
886 else if (!strcmp(args[cur_arg], "insert")) {
887 curproxy->options |= PR_O_COOK_INS;
888 }
889 else if (!strcmp(args[cur_arg], "nocache")) {
890 curproxy->options |= PR_O_COOK_NOC;
891 }
892 else if (!strcmp(args[cur_arg], "postonly")) {
893 curproxy->options |= PR_O_COOK_POST;
894 }
895 else if (!strcmp(args[cur_arg], "prefix")) {
896 curproxy->options |= PR_O_COOK_PFX;
897 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200898 else if (!strcmp(args[cur_arg], "domain")) {
899 if (!*args[cur_arg + 1]) {
900 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
901 file, linenum, args[cur_arg]);
902 return -1;
903 }
904
905 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
906 /* rfc2109, 4.3.2 Rejecting Cookies */
907 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
908 " dots or does not start with a dot.\n",
909 file, linenum, args[cur_arg + 1]);
910 return -1;
911 }
912
913 err = invalid_domainchar(args[cur_arg + 1]);
914 if (err) {
915 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
916 file, linenum, *err, args[cur_arg + 1]);
917 return -1;
918 }
919
920 curproxy->cookiedomain = strdup(args[cur_arg + 1]);
921 cur_arg++;
922 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200924 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +0200925 file, linenum, args[0]);
926 return -1;
927 }
928 cur_arg++;
929 }
930 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
931 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
932 file, linenum);
933 return -1;
934 }
935
936 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
937 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
938 file, linenum);
939 return -1;
940 }
941 }/* end else if (!strcmp(args[0], "cookie")) */
942 else if (!strcmp(args[0], "appsession")) { /* cookie name */
943 // if (curproxy == &defproxy) {
944 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
945 // return -1;
946 // }
947
Willy Tarreau977b8e42006-12-29 14:19:17 +0100948 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
949 return 0;
950
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 if (curproxy->appsession_name != NULL) {
952 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
953 // file, linenum);
954 // return 0;
955 free(curproxy->appsession_name);
956 }
957
958 if (*(args[5]) == 0) {
959 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
960 file, linenum, args[0]);
961 return -1;
962 }
963 have_appsession = 1;
964 curproxy->appsession_name = strdup(args[1]);
965 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
966 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100967 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
968 if (err) {
969 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
970 file, linenum, *err, args[0]);
971 return -1;
972 }
Willy Tarreauee991362007-05-14 14:37:50 +0200973 if (val > 0)
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100974 __tv_from_ms(&curproxy->timeout.appsession, val);
Willy Tarreauee991362007-05-14 14:37:50 +0200975 else
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100976 tv_eternity(&curproxy->timeout.appsession);
Willy Tarreauee991362007-05-14 14:37:50 +0200977
Willy Tarreau51041c72007-09-09 21:56:53 +0200978 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
979 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 return -1;
981 }
982 } /* Url App Session */
983 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100984 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
985 return 0;
986
Willy Tarreaubaaee002006-06-26 02:48:02 +0200987 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
988 // if (curproxy == &defproxy) {
989 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
990 // return -1;
991 // }
992
993 if (curproxy->capture_name != NULL) {
994 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
995 // file, linenum, args[0]);
996 // return 0;
997 free(curproxy->capture_name);
998 }
999
1000 if (*(args[4]) == 0) {
1001 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1002 file, linenum, args[0]);
1003 return -1;
1004 }
1005 curproxy->capture_name = strdup(args[2]);
1006 curproxy->capture_namelen = strlen(curproxy->capture_name);
1007 curproxy->capture_len = atol(args[4]);
1008 if (curproxy->capture_len >= CAPTURE_LEN) {
1009 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1010 file, linenum, CAPTURE_LEN - 1);
1011 curproxy->capture_len = CAPTURE_LEN - 1;
1012 }
1013 curproxy->to_log |= LW_COOKIE;
1014 }
1015 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1016 struct cap_hdr *hdr;
1017
1018 if (curproxy == &defproxy) {
1019 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1020 return -1;
1021 }
1022
1023 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1024 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1025 file, linenum, args[0], args[1]);
1026 return -1;
1027 }
1028
1029 hdr = calloc(sizeof(struct cap_hdr), 1);
1030 hdr->next = curproxy->req_cap;
1031 hdr->name = strdup(args[3]);
1032 hdr->namelen = strlen(args[3]);
1033 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001034 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001035 hdr->index = curproxy->nb_req_cap++;
1036 curproxy->req_cap = hdr;
1037 curproxy->to_log |= LW_REQHDR;
1038 }
1039 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1040 struct cap_hdr *hdr;
1041
1042 if (curproxy == &defproxy) {
1043 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1044 return -1;
1045 }
1046
1047 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1048 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1049 file, linenum, args[0], args[1]);
1050 return -1;
1051 }
1052 hdr = calloc(sizeof(struct cap_hdr), 1);
1053 hdr->next = curproxy->rsp_cap;
1054 hdr->name = strdup(args[3]);
1055 hdr->namelen = strlen(args[3]);
1056 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001057 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 hdr->index = curproxy->nb_rsp_cap++;
1059 curproxy->rsp_cap = hdr;
1060 curproxy->to_log |= LW_RSPHDR;
1061 }
1062 else {
1063 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1064 file, linenum, args[0]);
1065 return -1;
1066 }
1067 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001068 else if (!strcmp(args[0], "contimeout") || !strcmp(args[0], "clitimeout") ||
1069 !strcmp(args[0], "srvtimeout") || !strcmp(args[0], "timeout")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001070
Willy Tarreaue219db72007-12-03 01:30:13 +01001071 /* either we have {con|srv|cli}timeout <value> or we have the
1072 * new form: timeout <type> <value>. The parser needs the word
1073 * preceeding the value.
1074 */
1075 const char **start_arg = (const char **)args;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001076
Willy Tarreaue219db72007-12-03 01:30:13 +01001077 if (strcmp(args[0], "timeout") == 0)
1078 start_arg++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001079
Willy Tarreaue219db72007-12-03 01:30:13 +01001080 snprintf(trash, sizeof(trash), "error near '%s'", args[0]);
1081 rc = proxy_parse_timeout(start_arg, curproxy, &defproxy, trash, sizeof(trash));
1082 if (rc < 0) {
1083 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001084 return -1;
1085 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001086 if (rc > 0)
1087 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 }
1089 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001090 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1091 return 0;
1092
Willy Tarreaubaaee002006-06-26 02:48:02 +02001093 if (*(args[1]) == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1095 file, linenum, args[0]);
1096 return -1;
1097 }
1098 curproxy->conn_retries = atol(args[1]);
1099 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001100 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1101 int pol = ACL_COND_NONE;
1102 struct acl_cond *cond;
1103
1104 if (!strcmp(args[1], "if"))
1105 pol = ACL_COND_IF;
1106 else if (!strcmp(args[1], "unless"))
1107 pol = ACL_COND_UNLESS;
1108
1109 if (pol == ACL_COND_NONE) {
1110 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1111 file, linenum, args[0]);
1112 return -1;
1113 }
1114
1115 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1116 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1117 file, linenum);
1118 return -1;
1119 }
1120 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1121 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001122 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1123 int pol = ACL_COND_NONE;
1124 struct acl_cond *cond;
1125 struct switching_rule *rule;
1126
1127 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1128 return 0;
1129
1130 if (*(args[1]) == 0) {
1131 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1132 return -1;
1133 }
1134
1135 if (!strcmp(args[2], "if"))
1136 pol = ACL_COND_IF;
1137 else if (!strcmp(args[2], "unless"))
1138 pol = ACL_COND_UNLESS;
1139
1140 if (pol == ACL_COND_NONE) {
1141 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1142 file, linenum, args[0]);
1143 return -1;
1144 }
1145
1146 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1147 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1148 file, linenum);
1149 return -1;
1150 }
1151
1152 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1153 rule->cond = cond;
1154 rule->be.name = strdup(args[1]);
1155 LIST_INIT(&rule->list);
1156 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1157 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001159 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1160 return 0;
1161
Willy Tarreaubaaee002006-06-26 02:48:02 +02001162 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1163 curproxy->uri_auth = NULL; /* we must detach from the default config */
1164
1165 if (*(args[1]) == 0) {
1166 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1167 return -1;
1168 } else if (!strcmp(args[1], "uri")) {
1169 if (*(args[2]) == 0) {
1170 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1171 return -1;
1172 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1173 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1174 return -1;
1175 }
1176 } else if (!strcmp(args[1], "realm")) {
1177 if (*(args[2]) == 0) {
1178 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1179 return -1;
1180 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1181 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1182 return -1;
1183 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001184 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001185 unsigned interval;
1186
1187 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1188 if (err) {
1189 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1190 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001191 return -1;
1192 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1193 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1194 return -1;
1195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001196 } else if (!strcmp(args[1], "auth")) {
1197 if (*(args[2]) == 0) {
1198 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1199 return -1;
1200 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1201 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1202 return -1;
1203 }
1204 } else if (!strcmp(args[1], "scope")) {
1205 if (*(args[2]) == 0) {
1206 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1207 return -1;
1208 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1209 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1210 return -1;
1211 }
1212 } else if (!strcmp(args[1], "enable")) {
1213 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1214 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1215 return -1;
1216 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001217 } else if (!strcmp(args[1], "hide-version")) {
1218 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1219 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1220 return -1;
1221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001222 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001223 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224 file, linenum, args[0]);
1225 return -1;
1226 }
1227 }
1228 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001229 int optnum;
1230
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001231 if (*(args[1]) == '\0') {
1232 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1233 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001234 return -1;
1235 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001236
1237 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1238 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1239 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1240 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001241
1242 if (!inv)
1243 curproxy->options |= cfg_opts[optnum].val;
1244 else
1245 curproxy->options &= ~cfg_opts[optnum].val;
1246
Willy Tarreau13943ab2006-12-31 00:24:10 +01001247 return 0;
1248 }
1249 }
1250
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001251 if (inv) {
1252 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1253 file, linenum, args[1]);
1254 return -1;
1255 }
1256
Willy Tarreau13943ab2006-12-31 00:24:10 +01001257 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 /* generate a complete HTTP log */
1259 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1260 else if (!strcmp(args[1], "tcplog"))
1261 /* generate a detailed TCP log */
1262 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001263 else if (!strcmp(args[1], "tcpka")) {
1264 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001265 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1266 return 0;
1267
1268 if (curproxy->cap & PR_CAP_FE)
1269 curproxy->options |= PR_O_TCP_CLI_KA;
1270 if (curproxy->cap & PR_CAP_BE)
1271 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001272 }
1273 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001274 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1275 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001276 /* use HTTP request to check servers' health */
1277 if (curproxy->check_req != NULL) {
1278 free(curproxy->check_req);
1279 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001280 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001281 curproxy->options &= ~PR_O_SMTP_CHK;
1282 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 if (!*args[2]) { /* no argument */
1284 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1285 curproxy->check_len = strlen(DEF_CHECK_REQ);
1286 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001287 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001288 curproxy->check_req = (char *)malloc(reqlen);
1289 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1290 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1291 } else { /* more arguments : METHOD URI [HTTP_VER] */
1292 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1293 if (*args[4])
1294 reqlen += strlen(args[4]);
1295 else
1296 reqlen += strlen("HTTP/1.0");
1297
1298 curproxy->check_req = (char *)malloc(reqlen);
1299 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1300 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1301 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001302 }
1303 else if (!strcmp(args[1], "ssl-hello-chk")) {
1304 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001305 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1306 return 0;
1307
Willy Tarreauf3c69202006-07-09 16:42:34 +02001308 if (curproxy->check_req != NULL) {
1309 free(curproxy->check_req);
1310 }
1311 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001312 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001313 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001314 }
Willy Tarreau23677902007-05-08 23:50:35 +02001315 else if (!strcmp(args[1], "smtpchk")) {
1316 /* use SMTP request to check servers' health */
1317 if (curproxy->check_req != NULL) {
1318 free(curproxy->check_req);
1319 }
1320 curproxy->options &= ~PR_O_HTTP_CHK;
1321 curproxy->options &= ~PR_O_SSL3_CHK;
1322 curproxy->options |= PR_O_SMTP_CHK;
1323
1324 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1325 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1326 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1327 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1328 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1329 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1330 curproxy->check_req = (char *)malloc(reqlen);
1331 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1332 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1333 } else {
1334 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1335 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1336 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1337 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1338 }
1339 }
1340 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001341 else if (!strcmp(args[1], "forwardfor")) {
1342 /* insert x-forwarded-for field, but not for the
1343 * IP address listed as an except.
1344 */
1345 if (*(args[2])) {
1346 if (!strcmp(args[2], "except")) {
1347 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1348 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1349 file, linenum, args[0]);
1350 return -1;
1351 }
1352 /* flush useless bits */
1353 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1354 } else {
1355 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1356 file, linenum, args[0]);
1357 return -1;
1358 }
1359 }
1360 curproxy->options |= PR_O_FWDFOR;
1361 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 else {
1363 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1364 return -1;
1365 }
1366 return 0;
1367 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001368 else if (!strcmp(args[0], "default_backend")) {
1369 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1370 return 0;
1371
1372 if (*(args[1]) == 0) {
1373 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1374 return -1;
1375 }
1376 if (curproxy->defbe.name)
1377 free(curproxy->defbe.name);
1378 curproxy->defbe.name = strdup(args[1]);
1379 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001381 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1382 return 0;
1383
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001384 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1385 file, linenum, args[0]);
1386
Willy Tarreaubaaee002006-06-26 02:48:02 +02001387 /* enable reconnections to dispatch */
1388 curproxy->options |= PR_O_REDISP;
1389 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001390 else if (!strcmp(args[0], "http-check")) {
1391 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1392 return 0;
1393
1394 if (strcmp(args[1], "disable-on-404") == 0) {
1395 /* enable a graceful server shutdown on an HTTP 404 response */
1396 curproxy->options |= PR_O_DISABLE404;
1397 }
1398 else {
1399 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1400 return -1;
1401 }
1402 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001403 else if (!strcmp(args[0], "monitor")) {
1404 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1405 return 0;
1406
1407 if (strcmp(args[1], "fail") == 0) {
1408 /* add a condition to fail monitor requests */
1409 int pol = ACL_COND_NONE;
1410 struct acl_cond *cond;
1411
1412 if (!strcmp(args[2], "if"))
1413 pol = ACL_COND_IF;
1414 else if (!strcmp(args[2], "unless"))
1415 pol = ACL_COND_UNLESS;
1416
1417 if (pol == ACL_COND_NONE) {
1418 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1419 file, linenum, args[0], args[1]);
1420 return -1;
1421 }
1422
1423 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1424 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1425 file, linenum, args[0], args[1]);
1426 return -1;
1427 }
1428 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1429 }
1430 else {
1431 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1432 return -1;
1433 }
1434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435#ifdef TPROXY
1436 else if (!strcmp(args[0], "transparent")) {
1437 /* enable transparent proxy connections */
1438 curproxy->options |= PR_O_TRANSP;
1439 }
1440#endif
1441 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001442 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1443 return 0;
1444
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445 if (*(args[1]) == 0) {
1446 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1447 return -1;
1448 }
1449 curproxy->maxconn = atol(args[1]);
1450 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001451 else if (!strcmp(args[0], "backlog")) { /* backlog */
1452 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1453 return 0;
1454
1455 if (*(args[1]) == 0) {
1456 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1457 return -1;
1458 }
1459 curproxy->backlog = atol(args[1]);
1460 }
Willy Tarreau86034312006-12-29 00:10:33 +01001461 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001462 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1463 return 0;
1464
Willy Tarreau86034312006-12-29 00:10:33 +01001465 if (*(args[1]) == 0) {
1466 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1467 return -1;
1468 }
1469 curproxy->fullconn = atol(args[1]);
1470 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001471 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1472 if (*(args[1]) == 0) {
1473 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1474 return -1;
1475 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001476 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1477 if (err) {
1478 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1479 file, linenum, *err);
1480 return -1;
1481 }
1482 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001483 }
1484 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1485 if (curproxy == &defproxy) {
1486 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1487 return -1;
1488 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001489 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1490 return 0;
1491
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492 if (strchr(args[1], ':') == NULL) {
1493 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1494 return -1;
1495 }
1496 curproxy->dispatch_addr = *str2sa(args[1]);
1497 }
1498 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001499 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1500 return 0;
1501
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001502 memcpy(trash, "error near 'balance'", 19);
1503 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1504 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1505 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001507 }
1508 else if (!strcmp(args[0], "server")) { /* server address */
1509 int cur_arg;
1510 char *rport;
1511 char *raddr;
1512 short realport;
1513 int do_check;
1514
1515 if (curproxy == &defproxy) {
1516 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1517 return -1;
1518 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001519 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1520 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001521
1522 if (!*args[2]) {
1523 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1524 file, linenum, args[0]);
1525 return -1;
1526 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001527
1528 err = invalid_char(args[1]);
1529 if (err) {
1530 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1531 file, linenum, *err, args[1]);
1532 return -1;
1533 }
1534
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1536 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1537 return -1;
1538 }
1539
1540 /* the servers are linked backwards first */
1541 newsrv->next = curproxy->srv;
1542 curproxy->srv = newsrv;
1543 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001544 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545
1546 LIST_INIT(&newsrv->pendconns);
1547 do_check = 0;
1548 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001549 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001550 newsrv->id = strdup(args[1]);
1551
1552 /* several ways to check the port component :
1553 * - IP => port=+0, relative
1554 * - IP: => port=+0, relative
1555 * - IP:N => port=N, absolute
1556 * - IP:+N => port=+N, relative
1557 * - IP:-N => port=-N, relative
1558 */
1559 raddr = strdup(args[2]);
1560 rport = strchr(raddr, ':');
1561 if (rport) {
1562 *rport++ = 0;
1563 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001564 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565 newsrv->state |= SRV_MAPPORTS;
1566 } else {
1567 realport = 0;
1568 newsrv->state |= SRV_MAPPORTS;
1569 }
1570
1571 newsrv->addr = *str2sa(raddr);
1572 newsrv->addr.sin_port = htons(realport);
1573 free(raddr);
1574
1575 newsrv->curfd = -1; /* no health-check in progress */
1576 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001577 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1578 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 newsrv->rise = DEF_RISETIME;
1580 newsrv->fall = DEF_FALLTIME;
1581 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001582 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001583 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001584 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001585
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 cur_arg = 3;
1587 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001588 if (!strcmp(args[cur_arg], "id")) {
1589 struct server *target;
1590
1591 if (!*args[cur_arg + 1]) {
1592 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1593 file, linenum, args[cur_arg]);
1594 return -1;
1595 }
1596
1597 newsrv->puid = atol(args[cur_arg + 1]);
1598
1599 if (newsrv->puid< 1001) {
1600 Alert("parsing [%s:%d]: custom id has to be > 1000",
1601 file, linenum);
1602 return -1;
1603 }
1604
1605 for (target = proxy->srv; target; target = target->next)
1606 if (newsrv != target && newsrv->puid == target->puid) {
1607 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1608 file, linenum, newsrv->id, target->id);
1609 return -1;
1610 }
1611 cur_arg += 2;
1612 }
1613 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614 newsrv->cookie = strdup(args[cur_arg + 1]);
1615 newsrv->cklen = strlen(args[cur_arg + 1]);
1616 cur_arg += 2;
1617 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001618 else if (!strcmp(args[cur_arg], "redir")) {
1619 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1620 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1621 cur_arg += 2;
1622 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 else if (!strcmp(args[cur_arg], "rise")) {
1624 newsrv->rise = atol(args[cur_arg + 1]);
1625 newsrv->health = newsrv->rise;
1626 cur_arg += 2;
1627 }
1628 else if (!strcmp(args[cur_arg], "fall")) {
1629 newsrv->fall = atol(args[cur_arg + 1]);
1630 cur_arg += 2;
1631 }
1632 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001633 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1634 if (err) {
1635 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1636 file, linenum, *err, newsrv->id);
1637 return -1;
1638 }
1639 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640 cur_arg += 2;
1641 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001642 else if (!strcmp(args[cur_arg], "fastinter")) {
1643 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1644 if (err) {
1645 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1646 file, linenum, *err, newsrv->id);
1647 return -1;
1648 }
1649 newsrv->fastinter = val;
1650 cur_arg += 2;
1651 }
1652 else if (!strcmp(args[cur_arg], "downinter")) {
1653 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1654 if (err) {
1655 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1656 file, linenum, *err, newsrv->id);
1657 return -1;
1658 }
1659 newsrv->downinter = val;
1660 cur_arg += 2;
1661 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001662 else if (!strcmp(args[cur_arg], "addr")) {
1663 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001664 cur_arg += 2;
1665 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001666 else if (!strcmp(args[cur_arg], "port")) {
1667 newsrv->check_port = atol(args[cur_arg + 1]);
1668 cur_arg += 2;
1669 }
1670 else if (!strcmp(args[cur_arg], "backup")) {
1671 newsrv->state |= SRV_BACKUP;
1672 cur_arg ++;
1673 }
1674 else if (!strcmp(args[cur_arg], "weight")) {
1675 int w;
1676 w = atol(args[cur_arg + 1]);
1677 if (w < 1 || w > 256) {
1678 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1679 file, linenum, newsrv->id, w);
1680 return -1;
1681 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001682 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 cur_arg += 2;
1684 }
1685 else if (!strcmp(args[cur_arg], "minconn")) {
1686 newsrv->minconn = atol(args[cur_arg + 1]);
1687 cur_arg += 2;
1688 }
1689 else if (!strcmp(args[cur_arg], "maxconn")) {
1690 newsrv->maxconn = atol(args[cur_arg + 1]);
1691 cur_arg += 2;
1692 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001693 else if (!strcmp(args[cur_arg], "maxqueue")) {
1694 newsrv->maxqueue = atol(args[cur_arg + 1]);
1695 cur_arg += 2;
1696 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001697 else if (!strcmp(args[cur_arg], "slowstart")) {
1698 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001699 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001700 if (err) {
1701 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1702 file, linenum, *err, newsrv->id);
1703 return -1;
1704 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001705 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001706 cur_arg += 2;
1707 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001708 else if (!strcmp(args[cur_arg], "track")) {
1709
1710 if (!*args[cur_arg + 1]) {
1711 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1712 file, linenum);
1713 return -1;
1714 }
1715
1716 newsrv->trackit = strdup(args[cur_arg + 1]);
1717
1718 cur_arg += 2;
1719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 else if (!strcmp(args[cur_arg], "check")) {
1721 global.maxsock++;
1722 do_check = 1;
1723 cur_arg += 1;
1724 }
1725 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1726 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001727#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001728 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1729 file, linenum, "source", "usesrc");
1730#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001731 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1732 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001733#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001734 return -1;
1735 }
1736 newsrv->state |= SRV_BIND_SRC;
1737 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1738 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001739 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001740#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1741#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001742 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001743 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1744 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001745 return -1;
1746 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001747#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001748 if (!*args[cur_arg + 1]) {
1749 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1750 file, linenum, "usesrc");
1751 return -1;
1752 }
1753 if (!strcmp(args[cur_arg + 1], "client")) {
1754 newsrv->state |= SRV_TPROXY_CLI;
1755 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1756 newsrv->state |= SRV_TPROXY_CIP;
1757 } else {
1758 newsrv->state |= SRV_TPROXY_ADDR;
1759 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1760 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001761 global.last_checks |= LSTCHK_NETADM;
1762#if !defined(CONFIG_HAP_LINUX_TPROXY)
1763 global.last_checks |= LSTCHK_CTTPROXY;
1764#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001765 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001766#else /* no TPROXY support */
1767 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001768 file, linenum, "usesrc");
1769 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001770#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001771 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001772 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001773 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1774 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1775 file, linenum, "usesrc", "source");
1776 return -1;
1777 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001779 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 +02001780 file, linenum, newsrv->id);
1781 return -1;
1782 }
1783 }
1784
1785 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001786 if (newsrv->trackit) {
1787 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1788 file, linenum);
1789 return -1;
1790 }
1791
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001792 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1793 newsrv->check_port = newsrv->check_addr.sin_port;
1794
Willy Tarreaubaaee002006-06-26 02:48:02 +02001795 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1796 newsrv->check_port = realport; /* by default */
1797 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001798 /* not yet valid, because no port was set on
1799 * the server either. We'll check if we have
1800 * a known port on the first listener.
1801 */
1802 struct listener *l;
1803 l = curproxy->listen;
1804 if (l) {
1805 int port;
1806 port = (l->addr.ss_family == AF_INET6)
1807 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1808 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1809 newsrv->check_port = port;
1810 }
1811 }
1812 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001813 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1814 file, linenum, newsrv->id);
1815 return -1;
1816 }
1817 newsrv->state |= SRV_CHECKED;
1818 }
1819
1820 if (newsrv->state & SRV_BACKUP)
1821 curproxy->srv_bck++;
1822 else
1823 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001824
1825 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001826 }
1827 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001828 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001829 int facility;
1830
1831 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1832 curproxy->logfac1 = global.logfac1;
1833 curproxy->logsrv1 = global.logsrv1;
1834 curproxy->loglev1 = global.loglev1;
1835 curproxy->logfac2 = global.logfac2;
1836 curproxy->logsrv2 = global.logsrv2;
1837 curproxy->loglev2 = global.loglev2;
1838 }
1839 else if (*(args[1]) && *(args[2])) {
1840 int level;
1841
1842 facility = get_log_facility(args[2]);
1843 if (facility < 0) {
1844 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1845 exit(1);
1846 }
1847
1848 level = 7; /* max syslog level = debug */
1849 if (*(args[3])) {
1850 level = get_log_level(args[3]);
1851 if (level < 0) {
1852 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1853 exit(1);
1854 }
1855 }
1856
Robert Tsai81ae1952007-12-05 10:47:29 +01001857 if (args[1][0] == '/') {
1858 logsrv.u.addr.sa_family = AF_UNIX;
1859 logsrv.u.un = *str2sun(args[1]);
1860 } else {
1861 logsrv.u.addr.sa_family = AF_INET;
1862 logsrv.u.in = *str2sa(args[1]);
1863 if (!logsrv.u.in.sin_port) {
1864 logsrv.u.in.sin_port =
1865 htons(SYSLOG_PORT);
1866 }
1867 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868
1869 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001870 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 curproxy->logfac1 = facility;
1872 curproxy->loglev1 = level;
1873 }
1874 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001875 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001876 curproxy->logfac2 = facility;
1877 curproxy->loglev2 = level;
1878 }
1879 else {
1880 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1881 return -1;
1882 }
1883 }
1884 else {
1885 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1886 file, linenum);
1887 return -1;
1888 }
1889 }
1890 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001891 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1892 return 0;
1893
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001895#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001896 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1897 file, linenum, "source", "usesrc");
1898#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001899 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1900 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001901#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 return -1;
1903 }
1904
1905 curproxy->source_addr = *str2sa(args[1]);
1906 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001907 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001908#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1909#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001910 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1911 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1912 file, linenum, "usesrc");
1913 return -1;
1914 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001915#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001916 if (!*args[3]) {
1917 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1918 file, linenum, "usesrc");
1919 return -1;
1920 }
1921
1922 if (!strcmp(args[3], "client")) {
1923 curproxy->options |= PR_O_TPXY_CLI;
1924 } else if (!strcmp(args[3], "clientip")) {
1925 curproxy->options |= PR_O_TPXY_CIP;
1926 } else {
1927 curproxy->options |= PR_O_TPXY_ADDR;
1928 curproxy->tproxy_addr = *str2sa(args[3]);
1929 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001930 global.last_checks |= LSTCHK_NETADM;
1931#if !defined(CONFIG_HAP_LINUX_TPROXY)
1932 global.last_checks |= LSTCHK_CTTPROXY;
1933#endif
1934#else /* no TPROXY support */
1935 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001936 file, linenum, "usesrc");
1937 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001938#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001939 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001941 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1942 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1943 file, linenum, "usesrc", "source");
1944 return -1;
1945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1947 regex_t *preg;
1948 if (curproxy == &defproxy) {
1949 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1950 return -1;
1951 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001952 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1953 return 0;
1954
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955 if (*(args[1]) == 0 || *(args[2]) == 0) {
1956 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1957 file, linenum, args[0]);
1958 return -1;
1959 }
1960
1961 preg = calloc(1, sizeof(regex_t));
1962 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1963 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1964 return -1;
1965 }
1966
1967 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1968 if (err) {
1969 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1970 file, linenum, *err);
1971 return -1;
1972 }
1973 }
1974 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1975 regex_t *preg;
1976 if (curproxy == &defproxy) {
1977 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1978 return -1;
1979 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001980 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1981 return 0;
1982
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983 if (*(args[1]) == 0) {
1984 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1985 return -1;
1986 }
1987
1988 preg = calloc(1, sizeof(regex_t));
1989 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1990 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1991 return -1;
1992 }
1993
1994 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1995 }
1996 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1997 regex_t *preg;
1998 if (curproxy == &defproxy) {
1999 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2000 return -1;
2001 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002002 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2003 return 0;
2004
Willy Tarreaubaaee002006-06-26 02:48:02 +02002005 if (*(args[1]) == 0) {
2006 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2007 return -1;
2008 }
2009
2010 preg = calloc(1, sizeof(regex_t));
2011 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2012 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2013 return -1;
2014 }
2015
2016 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2017 }
2018 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2019 regex_t *preg;
2020 if (curproxy == &defproxy) {
2021 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2022 return -1;
2023 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002024 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2025 return 0;
2026
Willy Tarreaubaaee002006-06-26 02:48:02 +02002027 if (*(args[1]) == 0) {
2028 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2029 return -1;
2030 }
2031
2032 preg = calloc(1, sizeof(regex_t));
2033 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2034 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2035 return -1;
2036 }
2037
2038 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2039 }
2040 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2041 regex_t *preg;
2042 if (curproxy == &defproxy) {
2043 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2044 return -1;
2045 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002046 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2047 return 0;
2048
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049 if (*(args[1]) == 0) {
2050 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", 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 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2061 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002062 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2063 regex_t *preg;
2064 if (curproxy == &defproxy) {
2065 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2066 return -1;
2067 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002068 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2069 return 0;
2070
Willy Tarreaub8750a82006-09-03 09:56:00 +02002071 if (*(args[1]) == 0) {
2072 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2073 return -1;
2074 }
2075
2076 preg = calloc(1, sizeof(regex_t));
2077 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2078 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2079 return -1;
2080 }
2081
2082 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2083 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002084 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2085 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002086 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002087 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2088 return -1;
2089 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002090 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2091 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002092
Willy Tarreau977b8e42006-12-29 14:19:17 +01002093 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002094 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2095 file, linenum, args[0]);
2096 return -1;
2097 }
2098
2099 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002100 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002101 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2102 }
2103
2104 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2105 }
2106 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2107 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002108 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002109 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2110 return -1;
2111 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002112 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2113 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002114
Willy Tarreau977b8e42006-12-29 14:19:17 +01002115 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002116 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2117 file, linenum, args[0]);
2118 return -1;
2119 }
2120
2121 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002122 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002123 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2124 }
2125
2126 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2127 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002128 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2129 regex_t *preg;
2130 if (curproxy == &defproxy) {
2131 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2132 return -1;
2133 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002134 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2135 return 0;
2136
Willy Tarreaubaaee002006-06-26 02:48:02 +02002137 if (*(args[1]) == 0 || *(args[2]) == 0) {
2138 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2139 file, linenum, args[0]);
2140 return -1;
2141 }
2142
2143 preg = calloc(1, sizeof(regex_t));
2144 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2145 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2146 return -1;
2147 }
2148
2149 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2150 if (err) {
2151 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2152 file, linenum, *err);
2153 return -1;
2154 }
2155 }
2156 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2157 regex_t *preg;
2158 if (curproxy == &defproxy) {
2159 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2160 return -1;
2161 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002162 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2163 return 0;
2164
Willy Tarreaubaaee002006-06-26 02:48:02 +02002165 if (*(args[1]) == 0) {
2166 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2167 return -1;
2168 }
2169
2170 preg = calloc(1, sizeof(regex_t));
2171 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2172 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2173 return -1;
2174 }
2175
2176 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2177 }
2178 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2179 regex_t *preg;
2180 if (curproxy == &defproxy) {
2181 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2182 return -1;
2183 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002184 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2185 return 0;
2186
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187 if (*(args[1]) == 0) {
2188 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2189 return -1;
2190 }
2191
2192 preg = calloc(1, sizeof(regex_t));
2193 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2194 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2195 return -1;
2196 }
2197
2198 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2199 }
2200 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2201 regex_t *preg;
2202 if (curproxy == &defproxy) {
2203 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2204 return -1;
2205 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002206 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2207 return 0;
2208
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 if (*(args[1]) == 0) {
2210 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2211 return -1;
2212 }
2213
2214 preg = calloc(1, sizeof(regex_t));
2215 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2216 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2217 return -1;
2218 }
2219
2220 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2221 }
2222 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2223 regex_t *preg;
2224 if (curproxy == &defproxy) {
2225 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2226 return -1;
2227 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002228 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2229 return 0;
2230
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 if (*(args[1]) == 0) {
2232 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", 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 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2243 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002244 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2245 regex_t *preg;
2246 if (curproxy == &defproxy) {
2247 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2248 return -1;
2249 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002250 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2251 return 0;
2252
Willy Tarreaub8750a82006-09-03 09:56:00 +02002253 if (*(args[1]) == 0) {
2254 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2255 return -1;
2256 }
2257
2258 preg = calloc(1, sizeof(regex_t));
2259 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2260 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2261 return -1;
2262 }
2263
2264 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2267 if (curproxy == &defproxy) {
2268 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2269 return -1;
2270 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002271 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2272 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002273
2274 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2275 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2276 return 0;
2277 }
2278
2279 if (*(args[1]) == 0) {
2280 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2281 return -1;
2282 }
2283
2284 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2285 }
2286 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2287 regex_t *preg;
2288
2289 if (*(args[1]) == 0 || *(args[2]) == 0) {
2290 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2291 file, linenum, args[0]);
2292 return -1;
2293 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002294 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2295 return 0;
2296
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297 preg = calloc(1, sizeof(regex_t));
2298 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2299 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2300 return -1;
2301 }
2302
2303 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2304 if (err) {
2305 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2306 file, linenum, *err);
2307 return -1;
2308 }
2309 }
2310 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2311 regex_t *preg;
2312 if (curproxy == &defproxy) {
2313 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2314 return -1;
2315 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002316 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2317 return 0;
2318
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 if (*(args[1]) == 0) {
2320 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2321 return -1;
2322 }
2323
2324 preg = calloc(1, sizeof(regex_t));
2325 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2326 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2327 return -1;
2328 }
2329
2330 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2331 if (err) {
2332 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2333 file, linenum, *err);
2334 return -1;
2335 }
2336 }
2337 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
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 Tarreaubaaee002006-06-26 02:48:02 +02002346 if (*(args[1]) == 0) {
2347 Alert("parsing [%s:%d] : '%s' expects <search> 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) != 0) {
2353 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2354 return -1;
2355 }
2356
2357 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2358 if (err) {
2359 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2360 file, linenum, *err);
2361 return -1;
2362 }
2363 }
2364 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2365 regex_t *preg;
2366 if (curproxy == &defproxy) {
2367 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2368 return -1;
2369 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002370 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2371 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372
2373 if (*(args[1]) == 0 || *(args[2]) == 0) {
2374 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2375 file, linenum, args[0]);
2376 return -1;
2377 }
2378
2379 preg = calloc(1, sizeof(regex_t));
2380 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2381 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2382 return -1;
2383 }
2384
2385 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2386 if (err) {
2387 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2388 file, linenum, *err);
2389 return -1;
2390 }
2391 }
2392 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2393 regex_t *preg;
2394 if (curproxy == &defproxy) {
2395 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2396 return -1;
2397 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002398 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2399 return 0;
2400
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 if (*(args[1]) == 0) {
2402 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2403 return -1;
2404 }
2405
2406 preg = calloc(1, sizeof(regex_t));
2407 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2408 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2409 return -1;
2410 }
2411
2412 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2413 if (err) {
2414 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2415 file, linenum, *err);
2416 return -1;
2417 }
2418 }
2419 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2420 regex_t *preg;
2421 if (curproxy == &defproxy) {
2422 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2423 return -1;
2424 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002425 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2426 return 0;
2427
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 if (*(args[1]) == 0) {
2429 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2430 return -1;
2431 }
2432
2433 preg = calloc(1, sizeof(regex_t));
2434 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2435 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2436 return -1;
2437 }
2438
2439 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2440 if (err) {
2441 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2442 file, linenum, *err);
2443 return -1;
2444 }
2445 }
2446 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2447 if (curproxy == &defproxy) {
2448 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2449 return -1;
2450 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002451 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2452 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453
2454 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2455 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2456 return 0;
2457 }
2458
2459 if (*(args[1]) == 0) {
2460 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2461 return -1;
2462 }
2463
2464 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2465 }
2466 else if (!strcmp(args[0], "errorloc") ||
2467 !strcmp(args[0], "errorloc302") ||
2468 !strcmp(args[0], "errorloc303")) { /* error location */
2469 int errnum, errlen;
2470 char *err;
2471
Willy Tarreau977b8e42006-12-29 14:19:17 +01002472 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2473 return 0;
2474
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002476 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 return -1;
2478 }
2479
2480 errnum = atol(args[1]);
2481 if (!strcmp(args[0], "errorloc303")) {
2482 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2483 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2484 } else {
2485 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2486 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2487 }
2488
Willy Tarreau0f772532006-12-23 20:51:41 +01002489 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2490 if (http_err_codes[rc] == errnum) {
2491 if (curproxy->errmsg[rc].str)
2492 free(curproxy->errmsg[rc].str);
2493 curproxy->errmsg[rc].str = err;
2494 curproxy->errmsg[rc].len = errlen;
2495 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002498
2499 if (rc >= HTTP_ERR_SIZE) {
2500 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2501 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002502 free(err);
2503 }
2504 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002505 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2506 int errnum, errlen, fd;
2507 char *err;
2508 struct stat stat;
2509
2510 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2511 return 0;
2512
2513 if (*(args[2]) == 0) {
2514 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2515 return -1;
2516 }
2517
2518 fd = open(args[2], O_RDONLY);
2519 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2520 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2521 file, linenum, args[2], args[1]);
2522 if (fd >= 0)
2523 close(fd);
2524 return -1;
2525 }
2526
2527 if (stat.st_size <= BUFSIZE) {
2528 errlen = stat.st_size;
2529 } else {
2530 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2531 file, linenum, args[2], BUFSIZE);
2532 errlen = BUFSIZE;
2533 }
2534
2535 err = malloc(errlen); /* malloc() must succeed during parsing */
2536 errnum = read(fd, err, errlen);
2537 if (errnum != errlen) {
2538 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2539 file, linenum, args[2], args[1]);
2540 close(fd);
2541 free(err);
2542 return -1;
2543 }
2544 close(fd);
2545
2546 errnum = atol(args[1]);
2547 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2548 if (http_err_codes[rc] == errnum) {
2549 if (curproxy->errmsg[rc].str)
2550 free(curproxy->errmsg[rc].str);
2551 curproxy->errmsg[rc].str = err;
2552 curproxy->errmsg[rc].len = errlen;
2553 break;
2554 }
2555 }
2556
2557 if (rc >= HTTP_ERR_SIZE) {
2558 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2559 file, linenum, errnum);
2560 free(err);
2561 }
2562 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 else {
Willy Tarreau6daf3432008-01-22 16:44:08 +01002564 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 return -1;
2566 }
2567 return 0;
2568}
2569
2570
2571/*
2572 * This function reads and parses the configuration file given in the argument.
2573 * returns 0 if OK, -1 if error.
2574 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002575int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002577 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 FILE *f;
2579 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581 int confsect = CFG_NONE;
2582
2583 struct proxy *curproxy = NULL;
2584 struct server *newsrv = NULL;
2585
2586 if ((f=fopen(file,"r")) == NULL)
2587 return -1;
2588
2589 init_default_instance();
2590
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002591 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002592 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002593 char *end;
2594 char *args[MAX_LINE_ARGS + 1];
2595 char *line = thisline;
2596
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 linenum++;
2598
2599 end = line + strlen(line);
2600
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002601 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2602 /* Check if we reached the limit and the last char is not \n.
2603 * Watch out for the last line without the terminating '\n'!
2604 */
2605 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2606 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002607 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002608 }
2609
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002611 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612 line++;
2613
2614 arg = 0;
2615 args[arg] = line;
2616
2617 while (*line && arg < MAX_LINE_ARGS) {
2618 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2619 * C equivalent value. Other combinations left unchanged (eg: \1).
2620 */
2621 if (*line == '\\') {
2622 int skip = 0;
2623 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2624 *line = line[1];
2625 skip = 1;
2626 }
2627 else if (line[1] == 'r') {
2628 *line = '\r';
2629 skip = 1;
2630 }
2631 else if (line[1] == 'n') {
2632 *line = '\n';
2633 skip = 1;
2634 }
2635 else if (line[1] == 't') {
2636 *line = '\t';
2637 skip = 1;
2638 }
2639 else if (line[1] == 'x') {
2640 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2641 unsigned char hex1, hex2;
2642 hex1 = toupper(line[2]) - '0';
2643 hex2 = toupper(line[3]) - '0';
2644 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2645 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2646 *line = (hex1<<4) + hex2;
2647 skip = 3;
2648 }
2649 else {
2650 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002651 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002652 }
2653 }
2654 if (skip) {
2655 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2656 end -= skip;
2657 }
2658 line++;
2659 }
2660 else if (*line == '#' || *line == '\n' || *line == '\r') {
2661 /* end of string, end of loop */
2662 *line = 0;
2663 break;
2664 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002665 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002667 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002668 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002669 line++;
2670 args[++arg] = line;
2671 }
2672 else {
2673 line++;
2674 }
2675 }
2676
2677 /* empty line */
2678 if (!**args)
2679 continue;
2680
Willy Tarreau540abe42007-05-02 20:50:16 +02002681 /* zero out remaining args and ensure that at least one entry
2682 * is zeroed out.
2683 */
2684 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002685 args[arg] = line;
2686 }
2687
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002688 if (!strcmp(args[0], "no")) {
2689 inv = 1;
2690 for (arg=0; *args[arg+1]; arg++)
2691 args[arg] = args[arg+1]; // shift args after inversion
2692 }
2693
2694 if (inv && strcmp(args[0], "option")) {
2695 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002696 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002697 }
2698
Willy Tarreau977b8e42006-12-29 14:19:17 +01002699 if (!strcmp(args[0], "listen") ||
2700 !strcmp(args[0], "frontend") ||
2701 !strcmp(args[0], "backend") ||
2702 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002703 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002704 confsect = CFG_LISTEN;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002705 if (cursection)
2706 free(cursection);
2707 cursection = strdup(args[0]);
2708 }
2709 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002710 confsect = CFG_GLOBAL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002711 if (cursection)
2712 free(cursection);
2713 cursection = strdup(args[0]);
2714 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002715 /* else it's a section keyword */
2716
2717 switch (confsect) {
2718 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002719 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002720 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002721 break;
2722 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002723 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002724 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002725 break;
2726 default:
2727 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002728 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002730 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01002731 if (cursection)
2732 free(cursection);
2733 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002734 fclose(f);
2735
2736 /*
2737 * Now, check for the integrity of all that we have collected.
2738 */
2739
2740 /* will be needed further to delay some tasks */
2741 tv_now(&now);
2742
2743 if ((curproxy = proxy) == NULL) {
2744 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2745 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002746 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002747 }
2748
2749 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002750 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002751 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002752
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 if (curproxy->state == PR_STSTOPPED) {
2754 curproxy = curproxy->next;
2755 continue;
2756 }
2757
Willy Tarreau977b8e42006-12-29 14:19:17 +01002758 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2759 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 +01002760 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 cfgerr++;
2762 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002763 else if (curproxy->cap & PR_CAP_BE &&
2764 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002765 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002766 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002767 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2768 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 +01002769 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 cfgerr++;
2771 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002772
Willy Tarreau31682232007-11-29 15:38:04 +01002773 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002774 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002775 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002776 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002777 cfgerr++;
2778 }
2779#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2780 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002781 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002782 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 cfgerr++;
2784 }
2785#endif
2786 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002787 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002788 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 }
2790 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002791
2792 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002793 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002794 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002795 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002796 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002797 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002798 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002799 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002800 }
2801 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002802 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002803 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002805 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002806 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002807 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002808 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002809 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002810 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2811 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002812
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002813 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002814 file, proxy_type_str(curproxy), curproxy->id);
2815 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002816 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002817
2818 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2819 if ((newsrv = curproxy->srv) != NULL) {
2820 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2821 file, proxy_type_str(curproxy), curproxy->id);
2822 }
2823 }
2824
2825 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002826 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2827 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2828 file, curproxy->id);
2829 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002830 }
2831 }
2832
Willy Tarreau82936582007-11-30 15:20:09 +01002833 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2834 curproxy->options &= ~PR_O_DISABLE404;
2835 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2836 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2837 }
2838
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002839 /* if a default backend was specified, let's find it */
2840 if (curproxy->defbe.name) {
2841 struct proxy *target;
2842
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002843 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2844 if (!target) {
2845 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2846 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002847 cfgerr++;
2848 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002849 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2850 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002851 } else {
2852 free(curproxy->defbe.name);
2853 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002854 }
2855 }
2856
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002857 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002858 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2859 /* map jump target for ACT_SETBE in req_rep chain */
2860 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002861 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002862 struct proxy *target;
2863
Willy Tarreaua496b602006-12-17 23:15:24 +01002864 if (exp->action != ACT_SETBE)
2865 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002866
2867 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2868 if (!target) {
2869 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2870 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002871 cfgerr++;
2872 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002873 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2874 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002875 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002876 } else {
2877 free((void *)exp->replace);
2878 exp->replace = (const char *)target;
2879 }
2880 }
2881 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002882
2883 /* find the target proxy for 'use_backend' rules */
2884 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002885 struct proxy *target;
2886
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002887 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002888
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002889 if (!target) {
2890 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2891 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002892 cfgerr++;
2893 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002894 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2895 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002896 cfgerr++;
2897 } else {
2898 free((void *)rule->be.name);
2899 rule->be.backend = target;
2900 }
2901 }
2902
Willy Tarreau2738a142006-07-08 17:28:09 +02002903 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002904 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->timeout.client)) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02002905 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002906 (!tv_isset(&curproxy->timeout.connect) || !tv_isset(&curproxy->timeout.server))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002907 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002908 " | While not properly invalid, you will certainly encounter various problems\n"
2909 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01002910 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002911 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002912 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002913
Willy Tarreau1fa31262007-12-03 00:36:16 +01002914 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
2915 * We must still support older configurations, so let's find out whether those
2916 * parameters have been set or must be copied from contimeouts.
2917 */
2918 if (curproxy != &defproxy) {
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002919 if (!tv_isset(&curproxy->timeout.tarpit) ||
2920 __tv_iseq(&curproxy->timeout.tarpit, &defproxy.timeout.tarpit)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01002921 /* tarpit timeout not set. We search in the following order:
2922 * default.tarpit, curr.connect, default.connect.
2923 */
2924 if (tv_isset(&defproxy.timeout.tarpit))
2925 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002926 else if (tv_isset(&curproxy->timeout.connect))
2927 curproxy->timeout.tarpit = curproxy->timeout.connect;
2928 else if (tv_isset(&defproxy.timeout.connect))
2929 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002930 }
2931 if ((curproxy->cap & PR_CAP_BE) &&
2932 (!tv_isset(&curproxy->timeout.queue) ||
2933 __tv_iseq(&curproxy->timeout.queue, &defproxy.timeout.queue))) {
2934 /* queue timeout not set. We search in the following order:
2935 * default.queue, curr.connect, default.connect.
2936 */
2937 if (tv_isset(&defproxy.timeout.queue))
2938 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002939 else if (tv_isset(&curproxy->timeout.connect))
2940 curproxy->timeout.queue = curproxy->timeout.connect;
2941 else if (tv_isset(&defproxy.timeout.connect))
2942 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002943 }
2944 }
2945
Willy Tarreauf3c69202006-07-09 16:42:34 +02002946 if (curproxy->options & PR_O_SSL3_CHK) {
2947 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2948 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2949 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2950 }
2951
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002952 /* The small pools required for the capture lists */
2953 if (curproxy->nb_req_cap)
2954 curproxy->req_cap_pool = create_pool("ptrcap",
2955 curproxy->nb_req_cap * sizeof(char *),
2956 MEM_F_SHARED);
2957 if (curproxy->nb_rsp_cap)
2958 curproxy->rsp_cap_pool = create_pool("ptrcap",
2959 curproxy->nb_rsp_cap * sizeof(char *),
2960 MEM_F_SHARED);
2961
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002962 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2963 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2964 MEM_F_SHARED);
2965
Willy Tarreau86034312006-12-29 00:10:33 +01002966 /* for backwards compatibility with "listen" instances, if
2967 * fullconn is not set but maxconn is set, then maxconn
2968 * is used.
2969 */
2970 if (!curproxy->fullconn)
2971 curproxy->fullconn = curproxy->maxconn;
2972
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973 /* first, we will invert the servers list order */
2974 newsrv = NULL;
2975 while (curproxy->srv) {
2976 struct server *next;
2977
2978 next = curproxy->srv->next;
2979 curproxy->srv->next = newsrv;
2980 newsrv = curproxy->srv;
2981 if (!next)
2982 break;
2983 curproxy->srv = next;
2984 }
2985
Willy Tarreau20697042007-11-15 23:26:18 +01002986 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01002987 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002988
Willy Tarreaub625a082007-11-26 01:15:43 +01002989 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01002990 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01002991 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01002992 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
2993 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01002994 else
2995 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002996
2997 if (curproxy->options & PR_O_LOGASAP)
2998 curproxy->to_log &= ~LW_BYTES;
2999
Willy Tarreaubaaee002006-06-26 02:48:02 +02003000 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003001 * ensure that we're not cross-dressing a TCP server into HTTP.
3002 */
3003 newsrv = curproxy->srv;
3004 while (newsrv != NULL) {
3005 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3006 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3007 file, proxy_type_str(curproxy), curproxy->id, linenum);
3008 goto err;
3009 }
3010 newsrv = newsrv->next;
3011 }
3012
3013 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 * If this server supports a maxconn parameter, it needs a dedicated
3015 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003016 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003017 */
3018 newsrv = curproxy->srv;
3019 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003020 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 /* Only 'minconn' was specified, or it was higher than or equal
3022 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3023 * this will avoid further useless expensive computations.
3024 */
3025 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003026 } else if (newsrv->maxconn && !newsrv->minconn) {
3027 /* minconn was not specified, so we set it to maxconn */
3028 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003029 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3030 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003031 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003032 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 }
3034
3035 if (newsrv->maxconn > 0) {
3036 struct task *t;
3037
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02003038 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003039 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003040 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 }
3042
Willy Tarreau96bcfd72007-04-29 10:41:56 +02003043 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01003044 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003045 t->state = TASK_IDLE;
3046 t->process = process_srv_queue;
3047 t->context = newsrv;
3048 newsrv->queue_mgt = t;
3049
3050 /* never run it unless specifically woken up */
3051 tv_eternity(&t->expire);
3052 task_queue(t);
3053 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003054
3055 if (newsrv->trackit) {
3056 struct proxy *px;
3057 struct server *srv;
3058 char *pname, *sname;
3059
3060 pname = newsrv->trackit;
3061 sname = strrchr(pname, '/');
3062
3063 if (sname)
3064 *sname++ = '\0';
3065 else {
3066 sname = pname;
3067 pname = NULL;
3068 }
3069
3070 if (pname) {
3071 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3072 if (!px) {
3073 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3074 file, proxy_type_str(curproxy), curproxy->id,
3075 newsrv->id, pname);
3076 return -1;
3077 }
3078 } else
3079 px = curproxy;
3080
3081 srv = findserver(px, sname);
3082 if (!srv) {
3083 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3084 file, proxy_type_str(curproxy), curproxy->id,
3085 newsrv->id, sname);
3086 return -1;
3087 }
3088
3089 if (!(srv->state & SRV_CHECKED)) {
3090 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3091 "tracing as it does not have checks enabled.\n",
3092 file, proxy_type_str(curproxy), curproxy->id,
3093 newsrv->id, px->id, srv->id);
3094 return -1;
3095 }
3096
3097 if (curproxy != px &&
3098 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3099 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3100 "tracing: disable-on-404 option inconsistency.\n",
3101 file, proxy_type_str(curproxy), curproxy->id,
3102 newsrv->id, px->id, srv->id);
3103 return -1;
3104 }
3105
3106 newsrv->tracked = srv;
3107 newsrv->tracknext = srv->tracknext;
3108 srv->tracknext = newsrv;
3109
3110 free(newsrv->trackit);
3111 }
3112
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113 newsrv = newsrv->next;
3114 }
3115
Willy Tarreaue6b98942007-10-29 01:09:36 +01003116 /* adjust this proxy's listeners */
3117 listener = curproxy->listen;
3118 while (listener) {
3119 if (curproxy->options & PR_O_TCP_NOLING)
3120 listener->options |= LI_O_NOLINGER;
3121 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003122 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003123 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003124 listener->accept = event_accept;
3125 listener->private = curproxy;
3126
3127 listener = listener->next;
3128 }
3129
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 curproxy = curproxy->next;
3131 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003132
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 if (cfgerr > 0) {
3134 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003135 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003137
3138 /*
3139 * Recount currently required checks.
3140 */
3141
3142 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3143 int optnum;
3144
3145 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3146 if (!(curproxy->options & cfg_opts[optnum].val))
3147 continue;
3148
3149 global.last_checks |= cfg_opts[optnum].checks;
3150 }
3151 }
3152
Willy Tarreau6daf3432008-01-22 16:44:08 +01003153 if (cursection)
3154 free(cursection);
3155 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003156 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003157
3158 err:
3159 if (cursection)
3160 free(cursection);
3161 cursection = NULL;
3162 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163}
3164
3165
3166
3167/*
3168 * Local variables:
3169 * c-indent-level: 8
3170 * c-basic-offset: 8
3171 * End:
3172 */