blob: 0c89c5bb8cf2045be60706961ab8758189b11474 [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
119static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
120int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
121int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
122
123/*
124 * converts <str> to a list of listeners which are dynamically allocated.
125 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
126 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
127 * - <port> is a numerical port from 1 to 65535 ;
128 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
129 * This can be repeated as many times as necessary, separated by a coma.
130 * The <tail> argument is a pointer to a current list which should be appended
131 * to the tail of the new list. The pointer to the new list is returned.
132 */
133static struct listener *str2listener(char *str, struct listener *tail)
134{
135 struct listener *l;
136 char *c, *next, *range, *dupstr;
137 int port, end;
138
139 next = dupstr = strdup(str);
140
141 while (next && *next) {
142 struct sockaddr_storage ss;
143
144 str = next;
145 /* 1) look for the end of the first address */
146 if ((next = strrchr(str, ',')) != NULL) {
147 *next++ = 0;
148 }
149
150 /* 2) look for the addr/port delimiter, it's the last colon. */
151 if ((range = strrchr(str, ':')) == NULL) {
152 Alert("Missing port number: '%s'\n", str);
153 goto fail;
154 }
155
156 *range++ = 0;
157
158 if (strrchr(str, ':') != NULL) {
159 /* IPv6 address contains ':' */
160 memset(&ss, 0, sizeof(ss));
161 ss.ss_family = AF_INET6;
162
163 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
164 Alert("Invalid server address: '%s'\n", str);
165 goto fail;
166 }
167 }
168 else {
169 memset(&ss, 0, sizeof(ss));
170 ss.ss_family = AF_INET;
171
172 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
173 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
174 }
175 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
176 struct hostent *he;
177
178 if ((he = gethostbyname(str)) == NULL) {
179 Alert("Invalid server name: '%s'\n", str);
180 goto fail;
181 }
182 else
183 ((struct sockaddr_in *)&ss)->sin_addr =
184 *(struct in_addr *) *(he->h_addr_list);
185 }
186 }
187
188 /* 3) look for the port-end delimiter */
189 if ((c = strchr(range, '-')) != NULL) {
190 *c++ = 0;
191 end = atol(c);
192 }
193 else {
194 end = atol(range);
195 }
196
197 port = atol(range);
198
199 if (port < 1 || port > 65535) {
200 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
201 goto fail;
202 }
203
204 if (end < 1 || end > 65535) {
205 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
206 goto fail;
207 }
208
209 for (; port <= end; port++) {
210 l = (struct listener *)calloc(1, sizeof(struct listener));
211 l->next = tail;
212 tail = l;
213
214 l->fd = -1;
215 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100216 l->state = LI_INIT;
217
218 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100220 tcpv6_add_listener(l);
221 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100223 tcpv4_add_listener(l);
224 }
225 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 } /* end for(port) */
227 } /* end while(next) */
228 free(dupstr);
229 return tail;
230 fail:
231 free(dupstr);
232 return NULL;
233}
234
Willy Tarreau977b8e42006-12-29 14:19:17 +0100235/*
236 * Sends a warning if proxy <proxy> does not have at least one of the
237 * capabilities in <cap>. An optionnal <hint> may be added at the end
238 * of the warning to help the user. Returns 1 if a warning was emitted
239 * or 0 if the condition is valid.
240 */
241int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
242{
243 char *msg;
244
245 switch (cap) {
246 case PR_CAP_BE: msg = "no backend"; break;
247 case PR_CAP_FE: msg = "no frontend"; break;
248 case PR_CAP_RS: msg = "no ruleset"; break;
249 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
250 default: msg = "not enough"; break;
251 }
252
253 if (!(proxy->cap & cap)) {
254 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100255 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100256 return 1;
257 }
258 return 0;
259}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200260
261/*
262 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
263 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100264int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265{
266
267 if (!strcmp(args[0], "global")) { /* new section */
268 /* no option, nothing special to do */
269 return 0;
270 }
271 else if (!strcmp(args[0], "daemon")) {
272 global.mode |= MODE_DAEMON;
273 }
274 else if (!strcmp(args[0], "debug")) {
275 global.mode |= MODE_DEBUG;
276 }
277 else if (!strcmp(args[0], "noepoll")) {
278 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
279 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200280 else if (!strcmp(args[0], "nosepoll")) {
281 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
282 }
283 else if (!strcmp(args[0], "nokqueue")) {
284 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286 else if (!strcmp(args[0], "nopoll")) {
287 cfg_polling_mechanism &= ~POLL_USE_POLL;
288 }
289 else if (!strcmp(args[0], "quiet")) {
290 global.mode |= MODE_QUIET;
291 }
292 else if (!strcmp(args[0], "stats")) {
Willy Tarreaufbee7132007-10-18 13:53:22 +0200293 memcpy(trash, "error near 'stats'", 19);
294 if (stats_parse_global((const char **)args + 1, trash, sizeof(trash)) < 0) {
295 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
296 return -1;
297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200299 else if (!strcmp(args[0], "tune.maxpollevents")) {
300 if (global.tune.maxpollevents != 0) {
301 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
302 return 0;
303 }
304 if (*(args[1]) == 0) {
305 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
306 return -1;
307 }
308 global.tune.maxpollevents = atol(args[1]);
309 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100310 else if (!strcmp(args[0], "tune.maxaccept")) {
311 if (global.tune.maxaccept != 0) {
312 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
313 return 0;
314 }
315 if (*(args[1]) == 0) {
316 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
317 return -1;
318 }
319 global.tune.maxaccept = atol(args[1]);
320 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321 else if (!strcmp(args[0], "uid")) {
322 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200323 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324 return 0;
325 }
326 if (*(args[1]) == 0) {
327 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
328 return -1;
329 }
330 global.uid = atol(args[1]);
331 }
332 else if (!strcmp(args[0], "gid")) {
333 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200334 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200335 return 0;
336 }
337 if (*(args[1]) == 0) {
338 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
339 return -1;
340 }
341 global.gid = atol(args[1]);
342 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200343 /* user/group name handling */
344 else if (!strcmp(args[0], "user")) {
345 struct passwd *ha_user;
346 if (global.uid != 0) {
347 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
348 return 0;
349 }
350 errno = 0;
351 ha_user = getpwnam(args[1]);
352 if (ha_user != NULL) {
353 global.uid = (int)ha_user->pw_uid;
354 }
355 else {
356 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
357 exit(1);
358 }
359 }
360 else if (!strcmp(args[0], "group")) {
361 struct group *ha_group;
362 if (global.gid != 0) {
363 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
364 return 0;
365 }
366 errno = 0;
367 ha_group = getgrnam(args[1]);
368 if (ha_group != NULL) {
369 global.gid = (int)ha_group->gr_gid;
370 }
371 else {
372 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
373 exit(1);
374 }
375 }
376 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200377 else if (!strcmp(args[0], "nbproc")) {
378 if (global.nbproc != 0) {
379 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
380 return 0;
381 }
382 if (*(args[1]) == 0) {
383 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
384 return -1;
385 }
386 global.nbproc = atol(args[1]);
387 }
388 else if (!strcmp(args[0], "maxconn")) {
389 if (global.maxconn != 0) {
390 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
391 return 0;
392 }
393 if (*(args[1]) == 0) {
394 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
395 return -1;
396 }
397 global.maxconn = atol(args[1]);
398#ifdef SYSTEM_MAXCONN
399 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
400 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);
401 global.maxconn = DEFAULT_MAXCONN;
402 }
403#endif /* SYSTEM_MAXCONN */
404 }
405 else if (!strcmp(args[0], "ulimit-n")) {
406 if (global.rlimit_nofile != 0) {
407 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
408 return 0;
409 }
410 if (*(args[1]) == 0) {
411 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
412 return -1;
413 }
414 global.rlimit_nofile = atol(args[1]);
415 }
416 else if (!strcmp(args[0], "chroot")) {
417 if (global.chroot != NULL) {
418 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
419 return 0;
420 }
421 if (*(args[1]) == 0) {
422 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
423 return -1;
424 }
425 global.chroot = strdup(args[1]);
426 }
427 else if (!strcmp(args[0], "pidfile")) {
428 if (global.pidfile != NULL) {
429 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
430 return 0;
431 }
432 if (*(args[1]) == 0) {
433 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
434 return -1;
435 }
436 global.pidfile = strdup(args[1]);
437 }
438 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100439 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200440 int facility, level;
441
442 if (*(args[1]) == 0 || *(args[2]) == 0) {
443 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
444 return -1;
445 }
446
447 facility = get_log_facility(args[2]);
448 if (facility < 0) {
449 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
450 exit(1);
451 }
452
453 level = 7; /* max syslog level = debug */
454 if (*(args[3])) {
455 level = get_log_level(args[3]);
456 if (level < 0) {
457 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
458 exit(1);
459 }
460 }
461
Robert Tsai81ae1952007-12-05 10:47:29 +0100462 if (args[1][0] == '/') {
463 logsrv.u.addr.sa_family = AF_UNIX;
464 logsrv.u.un = *str2sun(args[1]);
465 } else {
466 logsrv.u.addr.sa_family = AF_INET;
467 logsrv.u.in = *str2sa(args[1]);
468 if (!logsrv.u.in.sin_port)
469 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
470 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200471
472 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100473 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200474 global.logfac1 = facility;
475 global.loglev1 = level;
476 }
477 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100478 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 global.logfac2 = facility;
480 global.loglev2 = level;
481 }
482 else {
483 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
484 return -1;
485 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200486 }
487 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
488 if (global.spread_checks != 0) {
489 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
490 return 0;
491 }
492 if (*(args[1]) == 0) {
493 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
494 return -1;
495 }
496 global.spread_checks = atol(args[1]);
497 if (global.spread_checks < 0 || global.spread_checks > 50) {
498 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
499 return -1;
500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200501 }
502 else {
503 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
504 return -1;
505 }
506 return 0;
507}
508
509
510static void init_default_instance()
511{
512 memset(&defproxy, 0, sizeof(defproxy));
513 defproxy.mode = PR_MODE_TCP;
514 defproxy.state = PR_STNEW;
515 defproxy.maxconn = cfg_maxpconn;
516 defproxy.conn_retries = CONN_RETRIES;
517 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100518 tv_eternity(&defproxy.timeout.client);
519 tv_eternity(&defproxy.timeout.connect);
520 tv_eternity(&defproxy.timeout.server);
521 tv_eternity(&defproxy.timeout.appsession);
Willy Tarreau1fa31262007-12-03 00:36:16 +0100522 tv_eternity(&defproxy.timeout.queue);
523 tv_eternity(&defproxy.timeout.tarpit);
Willy Tarreau036fae02008-01-06 13:24:40 +0100524 tv_eternity(&defproxy.timeout.httpreq);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200525}
526
527/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100528 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
529 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100531int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200532{
533 static struct proxy *curproxy = NULL;
534 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200535 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100536 int rc;
537 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538
Willy Tarreau977b8e42006-12-29 14:19:17 +0100539 if (!strcmp(args[0], "listen"))
540 rc = PR_CAP_LISTEN;
541 else if (!strcmp(args[0], "frontend"))
542 rc = PR_CAP_FE | PR_CAP_RS;
543 else if (!strcmp(args[0], "backend"))
544 rc = PR_CAP_BE | PR_CAP_RS;
545 else if (!strcmp(args[0], "ruleset"))
546 rc = PR_CAP_RS;
547 else
548 rc = PR_CAP_NONE;
549
550 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200551 if (!*args[1]) {
552 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
553 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
554 file, linenum, args[0]);
555 return -1;
556 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200557
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100558 err = invalid_char(args[1]);
559 if (err) {
560 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
561 file, linenum, *err, args[0], args[1]);
562 return -1;
563 }
564
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200565 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
566 /*
567 * If there are two proxies with the same name only following
568 * combinations are allowed:
569 *
570 * listen backend frontend ruleset
571 * listen - - - -
572 * backend - - OK -
573 * frontend - OK - -
574 * ruleset - - - -
575 */
576
577 if (!strcmp(curproxy->id, args[1]) &&
578 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
579 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100580 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
581 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200582 }
583 }
584
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
586 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
587 return -1;
588 }
589
590 curproxy->next = proxy;
591 proxy = curproxy;
592 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200593 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200594 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100595 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200596 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200597
Willy Tarreauee991362007-05-14 14:37:50 +0200598 /* Timeouts are defined as -1, so we cannot use the zeroed area
599 * as a default value.
600 */
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100601 tv_eternity(&curproxy->timeout.client);
602 tv_eternity(&curproxy->timeout.server);
603 tv_eternity(&curproxy->timeout.connect);
604 tv_eternity(&curproxy->timeout.appsession);
Willy Tarreau1fa31262007-12-03 00:36:16 +0100605 tv_eternity(&curproxy->timeout.queue);
606 tv_eternity(&curproxy->timeout.tarpit);
Willy Tarreau036fae02008-01-06 13:24:40 +0100607 tv_eternity(&curproxy->timeout.httpreq);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200608
609 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100611 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612
613 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100614 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 curproxy->listen = str2listener(args[2], curproxy->listen);
616 if (!curproxy->listen)
617 return -1;
618 global.maxsock++;
619 }
620
621 /* set default values */
622 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100624 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200625 curproxy->except_net = defproxy.except_net;
626 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200627
Willy Tarreau977b8e42006-12-29 14:19:17 +0100628 if (curproxy->cap & PR_CAP_FE) {
629 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100630 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100631
632 /* initialize error relocations */
633 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
634 if (defproxy.errmsg[rc].str)
635 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
636 }
637
638 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
639 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200640
Willy Tarreau977b8e42006-12-29 14:19:17 +0100641 if (curproxy->cap & PR_CAP_BE) {
642 curproxy->fullconn = defproxy.fullconn;
643 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644
Willy Tarreau977b8e42006-12-29 14:19:17 +0100645 if (defproxy.check_req)
646 curproxy->check_req = strdup(defproxy.check_req);
647 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200648
Willy Tarreau977b8e42006-12-29 14:19:17 +0100649 if (defproxy.cookie_name)
650 curproxy->cookie_name = strdup(defproxy.cookie_name);
651 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100652
653 if (defproxy.url_param_name)
654 curproxy->url_param_name = strdup(defproxy.url_param_name);
655 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657
Willy Tarreau977b8e42006-12-29 14:19:17 +0100658 if (curproxy->cap & PR_CAP_RS) {
659 if (defproxy.capture_name)
660 curproxy->capture_name = strdup(defproxy.capture_name);
661 curproxy->capture_namelen = defproxy.capture_namelen;
662 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100663 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200664
Willy Tarreau977b8e42006-12-29 14:19:17 +0100665 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100666 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100667 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100668 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100669 curproxy->uri_auth = defproxy.uri_auth;
670 curproxy->mon_net = defproxy.mon_net;
671 curproxy->mon_mask = defproxy.mon_mask;
672 if (defproxy.monitor_uri)
673 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
674 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100675 if (defproxy.defbe.name)
676 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100677 }
678
679 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100680 curproxy->timeout.connect = defproxy.timeout.connect;
681 curproxy->timeout.server = defproxy.timeout.server;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100682 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100683 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100684 curproxy->source_addr = defproxy.source_addr;
685 }
686
Willy Tarreaubaaee002006-06-26 02:48:02 +0200687 curproxy->mode = defproxy.mode;
688 curproxy->logfac1 = defproxy.logfac1;
689 curproxy->logsrv1 = defproxy.logsrv1;
690 curproxy->loglev1 = defproxy.loglev1;
691 curproxy->logfac2 = defproxy.logfac2;
692 curproxy->logsrv2 = defproxy.logsrv2;
693 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200694 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100695 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
696 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200697
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 return 0;
699 }
700 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
701 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100702 /* FIXME-20070101: we should do this too at the end of the
703 * config parsing to free all default values.
704 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200705 if (defproxy.check_req) free(defproxy.check_req);
706 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100707 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200708 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200709 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100710 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100711
712 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
713 if (defproxy.errmsg[rc].len)
714 free(defproxy.errmsg[rc].str);
715 }
716
Willy Tarreaubaaee002006-06-26 02:48:02 +0200717 /* we cannot free uri_auth because it might already be used */
718 init_default_instance();
719 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100720 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 return 0;
722 }
723 else if (curproxy == NULL) {
724 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
725 return -1;
726 }
727
Willy Tarreau977b8e42006-12-29 14:19:17 +0100728
729 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200730 if (!strcmp(args[0], "bind")) { /* new listen addresses */
731 if (curproxy == &defproxy) {
732 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
733 return -1;
734 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100735 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
736 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200737
738 if (strchr(args[1], ':') == NULL) {
739 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
740 file, linenum, args[0]);
741 return -1;
742 }
743 curproxy->listen = str2listener(args[1], curproxy->listen);
744 if (!curproxy->listen)
745 return -1;
746 global.maxsock++;
747 return 0;
748 }
749 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
750 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
751 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
752 file, linenum, args[0]);
753 return -1;
754 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100755 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
756 return 0;
757
Willy Tarreaubaaee002006-06-26 02:48:02 +0200758 /* flush useless bits */
759 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
760 return 0;
761 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200762 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100763 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
764 return 0;
765
Willy Tarreau1c47f852006-07-09 08:22:27 +0200766 if (!*args[1]) {
767 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
768 file, linenum, args[0]);
769 return -1;
770 }
771
772 if (curproxy->monitor_uri != NULL)
773 free(curproxy->monitor_uri);
774
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100775 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200776 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100777 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200778 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
779
780 return 0;
781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
783 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
784 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
785 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
786 else {
787 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
788 return -1;
789 }
790 }
791 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
792 curproxy->state = PR_STSTOPPED;
793 }
794 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
795 curproxy->state = PR_STNEW;
796 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200797 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100798 err = invalid_char(args[1]);
799 if (err) {
800 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
801 file, linenum, *err, args[1]);
802 return -1;
803 }
804
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200805 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
806 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
807 file, linenum, args[1]);
808 return -1;
809 }
810 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200811 else if (!strcmp(args[0], "cookie")) { /* cookie name */
812 int cur_arg;
813 // if (curproxy == &defproxy) {
814 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
815 // return -1;
816 // }
817
Willy Tarreau977b8e42006-12-29 14:19:17 +0100818 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
819 return 0;
820
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821 if (curproxy->cookie_name != NULL) {
822 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
823 // file, linenum);
824 // return 0;
825 free(curproxy->cookie_name);
826 }
827
828 if (*(args[1]) == 0) {
829 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
830 file, linenum, args[0]);
831 return -1;
832 }
833 curproxy->cookie_name = strdup(args[1]);
834 curproxy->cookie_len = strlen(curproxy->cookie_name);
835
836 cur_arg = 2;
837 while (*(args[cur_arg])) {
838 if (!strcmp(args[cur_arg], "rewrite")) {
839 curproxy->options |= PR_O_COOK_RW;
840 }
841 else if (!strcmp(args[cur_arg], "indirect")) {
842 curproxy->options |= PR_O_COOK_IND;
843 }
844 else if (!strcmp(args[cur_arg], "insert")) {
845 curproxy->options |= PR_O_COOK_INS;
846 }
847 else if (!strcmp(args[cur_arg], "nocache")) {
848 curproxy->options |= PR_O_COOK_NOC;
849 }
850 else if (!strcmp(args[cur_arg], "postonly")) {
851 curproxy->options |= PR_O_COOK_POST;
852 }
853 else if (!strcmp(args[cur_arg], "prefix")) {
854 curproxy->options |= PR_O_COOK_PFX;
855 }
856 else {
857 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
858 file, linenum, args[0]);
859 return -1;
860 }
861 cur_arg++;
862 }
863 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
864 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
865 file, linenum);
866 return -1;
867 }
868
869 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
870 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
871 file, linenum);
872 return -1;
873 }
874 }/* end else if (!strcmp(args[0], "cookie")) */
875 else if (!strcmp(args[0], "appsession")) { /* cookie name */
876 // if (curproxy == &defproxy) {
877 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
878 // return -1;
879 // }
880
Willy Tarreau977b8e42006-12-29 14:19:17 +0100881 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
882 return 0;
883
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884 if (curproxy->appsession_name != NULL) {
885 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
886 // file, linenum);
887 // return 0;
888 free(curproxy->appsession_name);
889 }
890
891 if (*(args[5]) == 0) {
892 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
893 file, linenum, args[0]);
894 return -1;
895 }
896 have_appsession = 1;
897 curproxy->appsession_name = strdup(args[1]);
898 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
899 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100900 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
901 if (err) {
902 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
903 file, linenum, *err, args[0]);
904 return -1;
905 }
Willy Tarreauee991362007-05-14 14:37:50 +0200906 if (val > 0)
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100907 __tv_from_ms(&curproxy->timeout.appsession, val);
Willy Tarreauee991362007-05-14 14:37:50 +0200908 else
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100909 tv_eternity(&curproxy->timeout.appsession);
Willy Tarreauee991362007-05-14 14:37:50 +0200910
Willy Tarreau51041c72007-09-09 21:56:53 +0200911 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
912 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913 return -1;
914 }
915 } /* Url App Session */
916 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100917 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
918 return 0;
919
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
921 // if (curproxy == &defproxy) {
922 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
923 // return -1;
924 // }
925
926 if (curproxy->capture_name != NULL) {
927 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
928 // file, linenum, args[0]);
929 // return 0;
930 free(curproxy->capture_name);
931 }
932
933 if (*(args[4]) == 0) {
934 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
935 file, linenum, args[0]);
936 return -1;
937 }
938 curproxy->capture_name = strdup(args[2]);
939 curproxy->capture_namelen = strlen(curproxy->capture_name);
940 curproxy->capture_len = atol(args[4]);
941 if (curproxy->capture_len >= CAPTURE_LEN) {
942 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
943 file, linenum, CAPTURE_LEN - 1);
944 curproxy->capture_len = CAPTURE_LEN - 1;
945 }
946 curproxy->to_log |= LW_COOKIE;
947 }
948 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
949 struct cap_hdr *hdr;
950
951 if (curproxy == &defproxy) {
952 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
953 return -1;
954 }
955
956 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
957 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
958 file, linenum, args[0], args[1]);
959 return -1;
960 }
961
962 hdr = calloc(sizeof(struct cap_hdr), 1);
963 hdr->next = curproxy->req_cap;
964 hdr->name = strdup(args[3]);
965 hdr->namelen = strlen(args[3]);
966 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200967 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 hdr->index = curproxy->nb_req_cap++;
969 curproxy->req_cap = hdr;
970 curproxy->to_log |= LW_REQHDR;
971 }
972 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
973 struct cap_hdr *hdr;
974
975 if (curproxy == &defproxy) {
976 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
977 return -1;
978 }
979
980 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
981 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
982 file, linenum, args[0], args[1]);
983 return -1;
984 }
985 hdr = calloc(sizeof(struct cap_hdr), 1);
986 hdr->next = curproxy->rsp_cap;
987 hdr->name = strdup(args[3]);
988 hdr->namelen = strlen(args[3]);
989 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200990 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200991 hdr->index = curproxy->nb_rsp_cap++;
992 curproxy->rsp_cap = hdr;
993 curproxy->to_log |= LW_RSPHDR;
994 }
995 else {
996 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
997 file, linenum, args[0]);
998 return -1;
999 }
1000 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001001 else if (!strcmp(args[0], "contimeout") || !strcmp(args[0], "clitimeout") ||
1002 !strcmp(args[0], "srvtimeout") || !strcmp(args[0], "timeout")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001003
Willy Tarreaue219db72007-12-03 01:30:13 +01001004 /* either we have {con|srv|cli}timeout <value> or we have the
1005 * new form: timeout <type> <value>. The parser needs the word
1006 * preceeding the value.
1007 */
1008 const char **start_arg = (const char **)args;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001009
Willy Tarreaue219db72007-12-03 01:30:13 +01001010 if (strcmp(args[0], "timeout") == 0)
1011 start_arg++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001012
Willy Tarreaue219db72007-12-03 01:30:13 +01001013 snprintf(trash, sizeof(trash), "error near '%s'", args[0]);
1014 rc = proxy_parse_timeout(start_arg, curproxy, &defproxy, trash, sizeof(trash));
1015 if (rc < 0) {
1016 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001017 return -1;
1018 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001019 if (rc > 0)
1020 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021 }
1022 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001023 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1024 return 0;
1025
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026 if (*(args[1]) == 0) {
1027 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1028 file, linenum, args[0]);
1029 return -1;
1030 }
1031 curproxy->conn_retries = atol(args[1]);
1032 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001033 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1034 int pol = ACL_COND_NONE;
1035 struct acl_cond *cond;
1036
1037 if (!strcmp(args[1], "if"))
1038 pol = ACL_COND_IF;
1039 else if (!strcmp(args[1], "unless"))
1040 pol = ACL_COND_UNLESS;
1041
1042 if (pol == ACL_COND_NONE) {
1043 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1044 file, linenum, args[0]);
1045 return -1;
1046 }
1047
1048 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1049 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1050 file, linenum);
1051 return -1;
1052 }
1053 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1054 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001055 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1056 int pol = ACL_COND_NONE;
1057 struct acl_cond *cond;
1058 struct switching_rule *rule;
1059
1060 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1061 return 0;
1062
1063 if (*(args[1]) == 0) {
1064 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1065 return -1;
1066 }
1067
1068 if (!strcmp(args[2], "if"))
1069 pol = ACL_COND_IF;
1070 else if (!strcmp(args[2], "unless"))
1071 pol = ACL_COND_UNLESS;
1072
1073 if (pol == ACL_COND_NONE) {
1074 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1075 file, linenum, args[0]);
1076 return -1;
1077 }
1078
1079 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1080 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1081 file, linenum);
1082 return -1;
1083 }
1084
1085 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1086 rule->cond = cond;
1087 rule->be.name = strdup(args[1]);
1088 LIST_INIT(&rule->list);
1089 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1090 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001092 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1093 return 0;
1094
Willy Tarreaubaaee002006-06-26 02:48:02 +02001095 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1096 curproxy->uri_auth = NULL; /* we must detach from the default config */
1097
1098 if (*(args[1]) == 0) {
1099 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1100 return -1;
1101 } else if (!strcmp(args[1], "uri")) {
1102 if (*(args[2]) == 0) {
1103 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1104 return -1;
1105 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1106 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1107 return -1;
1108 }
1109 } else if (!strcmp(args[1], "realm")) {
1110 if (*(args[2]) == 0) {
1111 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1112 return -1;
1113 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1114 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1115 return -1;
1116 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001117 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001118 unsigned interval;
1119
1120 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1121 if (err) {
1122 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1123 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001124 return -1;
1125 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1126 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1127 return -1;
1128 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001129 } else if (!strcmp(args[1], "auth")) {
1130 if (*(args[2]) == 0) {
1131 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1132 return -1;
1133 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1134 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1135 return -1;
1136 }
1137 } else if (!strcmp(args[1], "scope")) {
1138 if (*(args[2]) == 0) {
1139 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1140 return -1;
1141 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1142 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1143 return -1;
1144 }
1145 } else if (!strcmp(args[1], "enable")) {
1146 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1147 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1148 return -1;
1149 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001150 } else if (!strcmp(args[1], "hide-version")) {
1151 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1152 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1153 return -1;
1154 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001155 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001156 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157 file, linenum, args[0]);
1158 return -1;
1159 }
1160 }
1161 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001162 int optnum;
1163
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001164 if (*(args[1]) == '\0') {
1165 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1166 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167 return -1;
1168 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001169
1170 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1171 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1172 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1173 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001174
1175 if (!inv)
1176 curproxy->options |= cfg_opts[optnum].val;
1177 else
1178 curproxy->options &= ~cfg_opts[optnum].val;
1179
Willy Tarreau13943ab2006-12-31 00:24:10 +01001180 return 0;
1181 }
1182 }
1183
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001184 if (inv) {
1185 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1186 file, linenum, args[1]);
1187 return -1;
1188 }
1189
Willy Tarreau13943ab2006-12-31 00:24:10 +01001190 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191 /* generate a complete HTTP log */
1192 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1193 else if (!strcmp(args[1], "tcplog"))
1194 /* generate a detailed TCP log */
1195 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001196 else if (!strcmp(args[1], "tcpka")) {
1197 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001198 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1199 return 0;
1200
1201 if (curproxy->cap & PR_CAP_FE)
1202 curproxy->options |= PR_O_TCP_CLI_KA;
1203 if (curproxy->cap & PR_CAP_BE)
1204 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 }
1206 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001207 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1208 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001209 /* use HTTP request to check servers' health */
1210 if (curproxy->check_req != NULL) {
1211 free(curproxy->check_req);
1212 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001213 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001214 curproxy->options &= ~PR_O_SMTP_CHK;
1215 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001216 if (!*args[2]) { /* no argument */
1217 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1218 curproxy->check_len = strlen(DEF_CHECK_REQ);
1219 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001220 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001221 curproxy->check_req = (char *)malloc(reqlen);
1222 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1223 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1224 } else { /* more arguments : METHOD URI [HTTP_VER] */
1225 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1226 if (*args[4])
1227 reqlen += strlen(args[4]);
1228 else
1229 reqlen += strlen("HTTP/1.0");
1230
1231 curproxy->check_req = (char *)malloc(reqlen);
1232 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1233 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1234 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001235 }
1236 else if (!strcmp(args[1], "ssl-hello-chk")) {
1237 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001238 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1239 return 0;
1240
Willy Tarreauf3c69202006-07-09 16:42:34 +02001241 if (curproxy->check_req != NULL) {
1242 free(curproxy->check_req);
1243 }
1244 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001245 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001246 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001247 }
Willy Tarreau23677902007-05-08 23:50:35 +02001248 else if (!strcmp(args[1], "smtpchk")) {
1249 /* use SMTP request to check servers' health */
1250 if (curproxy->check_req != NULL) {
1251 free(curproxy->check_req);
1252 }
1253 curproxy->options &= ~PR_O_HTTP_CHK;
1254 curproxy->options &= ~PR_O_SSL3_CHK;
1255 curproxy->options |= PR_O_SMTP_CHK;
1256
1257 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1258 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1259 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1260 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1261 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1262 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1263 curproxy->check_req = (char *)malloc(reqlen);
1264 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1265 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1266 } else {
1267 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1268 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1269 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1270 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1271 }
1272 }
1273 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001274 else if (!strcmp(args[1], "forwardfor")) {
1275 /* insert x-forwarded-for field, but not for the
1276 * IP address listed as an except.
1277 */
1278 if (*(args[2])) {
1279 if (!strcmp(args[2], "except")) {
1280 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1281 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1282 file, linenum, args[0]);
1283 return -1;
1284 }
1285 /* flush useless bits */
1286 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1287 } else {
1288 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1289 file, linenum, args[0]);
1290 return -1;
1291 }
1292 }
1293 curproxy->options |= PR_O_FWDFOR;
1294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001295 else {
1296 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1297 return -1;
1298 }
1299 return 0;
1300 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001301 else if (!strcmp(args[0], "default_backend")) {
1302 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1303 return 0;
1304
1305 if (*(args[1]) == 0) {
1306 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1307 return -1;
1308 }
1309 if (curproxy->defbe.name)
1310 free(curproxy->defbe.name);
1311 curproxy->defbe.name = strdup(args[1]);
1312 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001313 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001314 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1315 return 0;
1316
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001317 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1318 file, linenum, args[0]);
1319
Willy Tarreaubaaee002006-06-26 02:48:02 +02001320 /* enable reconnections to dispatch */
1321 curproxy->options |= PR_O_REDISP;
1322 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001323 else if (!strcmp(args[0], "http-check")) {
1324 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1325 return 0;
1326
1327 if (strcmp(args[1], "disable-on-404") == 0) {
1328 /* enable a graceful server shutdown on an HTTP 404 response */
1329 curproxy->options |= PR_O_DISABLE404;
1330 }
1331 else {
1332 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1333 return -1;
1334 }
1335 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001336 else if (!strcmp(args[0], "monitor")) {
1337 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1338 return 0;
1339
1340 if (strcmp(args[1], "fail") == 0) {
1341 /* add a condition to fail monitor requests */
1342 int pol = ACL_COND_NONE;
1343 struct acl_cond *cond;
1344
1345 if (!strcmp(args[2], "if"))
1346 pol = ACL_COND_IF;
1347 else if (!strcmp(args[2], "unless"))
1348 pol = ACL_COND_UNLESS;
1349
1350 if (pol == ACL_COND_NONE) {
1351 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1352 file, linenum, args[0], args[1]);
1353 return -1;
1354 }
1355
1356 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1357 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1358 file, linenum, args[0], args[1]);
1359 return -1;
1360 }
1361 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1362 }
1363 else {
1364 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1365 return -1;
1366 }
1367 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368#ifdef TPROXY
1369 else if (!strcmp(args[0], "transparent")) {
1370 /* enable transparent proxy connections */
1371 curproxy->options |= PR_O_TRANSP;
1372 }
1373#endif
1374 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001375 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1376 return 0;
1377
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378 if (*(args[1]) == 0) {
1379 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1380 return -1;
1381 }
1382 curproxy->maxconn = atol(args[1]);
1383 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001384 else if (!strcmp(args[0], "backlog")) { /* backlog */
1385 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1386 return 0;
1387
1388 if (*(args[1]) == 0) {
1389 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1390 return -1;
1391 }
1392 curproxy->backlog = atol(args[1]);
1393 }
Willy Tarreau86034312006-12-29 00:10:33 +01001394 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001395 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1396 return 0;
1397
Willy Tarreau86034312006-12-29 00:10:33 +01001398 if (*(args[1]) == 0) {
1399 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1400 return -1;
1401 }
1402 curproxy->fullconn = atol(args[1]);
1403 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001404 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1405 if (*(args[1]) == 0) {
1406 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1407 return -1;
1408 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001409 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1410 if (err) {
1411 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1412 file, linenum, *err);
1413 return -1;
1414 }
1415 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001416 }
1417 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1418 if (curproxy == &defproxy) {
1419 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1420 return -1;
1421 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001422 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1423 return 0;
1424
Willy Tarreaubaaee002006-06-26 02:48:02 +02001425 if (strchr(args[1], ':') == NULL) {
1426 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1427 return -1;
1428 }
1429 curproxy->dispatch_addr = *str2sa(args[1]);
1430 }
1431 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001432 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1433 return 0;
1434
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001435 memcpy(trash, "error near 'balance'", 19);
1436 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1437 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1438 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001439 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001440 }
1441 else if (!strcmp(args[0], "server")) { /* server address */
1442 int cur_arg;
1443 char *rport;
1444 char *raddr;
1445 short realport;
1446 int do_check;
1447
1448 if (curproxy == &defproxy) {
1449 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1450 return -1;
1451 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001452 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1453 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454
1455 if (!*args[2]) {
1456 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1457 file, linenum, args[0]);
1458 return -1;
1459 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001460
1461 err = invalid_char(args[1]);
1462 if (err) {
1463 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1464 file, linenum, *err, args[1]);
1465 return -1;
1466 }
1467
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1469 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1470 return -1;
1471 }
1472
1473 /* the servers are linked backwards first */
1474 newsrv->next = curproxy->srv;
1475 curproxy->srv = newsrv;
1476 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001477 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001478
1479 LIST_INIT(&newsrv->pendconns);
1480 do_check = 0;
1481 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001482 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001483 newsrv->id = strdup(args[1]);
1484
1485 /* several ways to check the port component :
1486 * - IP => port=+0, relative
1487 * - IP: => port=+0, relative
1488 * - IP:N => port=N, absolute
1489 * - IP:+N => port=+N, relative
1490 * - IP:-N => port=-N, relative
1491 */
1492 raddr = strdup(args[2]);
1493 rport = strchr(raddr, ':');
1494 if (rport) {
1495 *rport++ = 0;
1496 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001497 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001498 newsrv->state |= SRV_MAPPORTS;
1499 } else {
1500 realport = 0;
1501 newsrv->state |= SRV_MAPPORTS;
1502 }
1503
1504 newsrv->addr = *str2sa(raddr);
1505 newsrv->addr.sin_port = htons(realport);
1506 free(raddr);
1507
1508 newsrv->curfd = -1; /* no health-check in progress */
1509 newsrv->inter = DEF_CHKINTR;
1510 newsrv->rise = DEF_RISETIME;
1511 newsrv->fall = DEF_FALLTIME;
1512 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001513 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001514 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001515 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001516
Willy Tarreaubaaee002006-06-26 02:48:02 +02001517 cur_arg = 3;
1518 while (*args[cur_arg]) {
1519 if (!strcmp(args[cur_arg], "cookie")) {
1520 newsrv->cookie = strdup(args[cur_arg + 1]);
1521 newsrv->cklen = strlen(args[cur_arg + 1]);
1522 cur_arg += 2;
1523 }
1524 else if (!strcmp(args[cur_arg], "rise")) {
1525 newsrv->rise = atol(args[cur_arg + 1]);
1526 newsrv->health = newsrv->rise;
1527 cur_arg += 2;
1528 }
1529 else if (!strcmp(args[cur_arg], "fall")) {
1530 newsrv->fall = atol(args[cur_arg + 1]);
1531 cur_arg += 2;
1532 }
1533 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001534 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1535 if (err) {
1536 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1537 file, linenum, *err, newsrv->id);
1538 return -1;
1539 }
1540 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001541 cur_arg += 2;
1542 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001543 else if (!strcmp(args[cur_arg], "addr")) {
1544 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001545 cur_arg += 2;
1546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001547 else if (!strcmp(args[cur_arg], "port")) {
1548 newsrv->check_port = atol(args[cur_arg + 1]);
1549 cur_arg += 2;
1550 }
1551 else if (!strcmp(args[cur_arg], "backup")) {
1552 newsrv->state |= SRV_BACKUP;
1553 cur_arg ++;
1554 }
1555 else if (!strcmp(args[cur_arg], "weight")) {
1556 int w;
1557 w = atol(args[cur_arg + 1]);
1558 if (w < 1 || w > 256) {
1559 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1560 file, linenum, newsrv->id, w);
1561 return -1;
1562 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001563 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564 cur_arg += 2;
1565 }
1566 else if (!strcmp(args[cur_arg], "minconn")) {
1567 newsrv->minconn = atol(args[cur_arg + 1]);
1568 cur_arg += 2;
1569 }
1570 else if (!strcmp(args[cur_arg], "maxconn")) {
1571 newsrv->maxconn = atol(args[cur_arg + 1]);
1572 cur_arg += 2;
1573 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001574 else if (!strcmp(args[cur_arg], "maxqueue")) {
1575 newsrv->maxqueue = atol(args[cur_arg + 1]);
1576 cur_arg += 2;
1577 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001578 else if (!strcmp(args[cur_arg], "slowstart")) {
1579 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001580 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001581 if (err) {
1582 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1583 file, linenum, *err, newsrv->id);
1584 return -1;
1585 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001586 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001587 cur_arg += 2;
1588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 else if (!strcmp(args[cur_arg], "check")) {
1590 global.maxsock++;
1591 do_check = 1;
1592 cur_arg += 1;
1593 }
1594 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1595 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001596#ifdef CONFIG_HAP_CTTPROXY
1597 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1598 file, linenum, "source", "usesrc");
1599#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1601 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001602#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 return -1;
1604 }
1605 newsrv->state |= SRV_BIND_SRC;
1606 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1607 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001608 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001609#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001610 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001611 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1612 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001613 return -1;
1614 }
1615 if (!*args[cur_arg + 1]) {
1616 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1617 file, linenum, "usesrc");
1618 return -1;
1619 }
1620 if (!strcmp(args[cur_arg + 1], "client")) {
1621 newsrv->state |= SRV_TPROXY_CLI;
1622 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1623 newsrv->state |= SRV_TPROXY_CIP;
1624 } else {
1625 newsrv->state |= SRV_TPROXY_ADDR;
1626 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1627 }
1628 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1629 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001630#else /* no CTTPROXY support */
1631 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1632 file, linenum, "usesrc");
1633 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001634#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001635 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001637#ifdef CONFIG_HAP_CTTPROXY
1638 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1639 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1640 file, linenum, "usesrc", "source");
1641 return -1;
1642 }
1643#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644 else {
Willy Tarreau9909fc12007-11-30 17:42:05 +01001645 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001646 file, linenum, newsrv->id);
1647 return -1;
1648 }
1649 }
1650
1651 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001652 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1653 newsrv->check_port = newsrv->check_addr.sin_port;
1654
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1656 newsrv->check_port = realport; /* by default */
1657 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001658 /* not yet valid, because no port was set on
1659 * the server either. We'll check if we have
1660 * a known port on the first listener.
1661 */
1662 struct listener *l;
1663 l = curproxy->listen;
1664 if (l) {
1665 int port;
1666 port = (l->addr.ss_family == AF_INET6)
1667 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1668 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1669 newsrv->check_port = port;
1670 }
1671 }
1672 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1674 file, linenum, newsrv->id);
1675 return -1;
1676 }
1677 newsrv->state |= SRV_CHECKED;
1678 }
1679
1680 if (newsrv->state & SRV_BACKUP)
1681 curproxy->srv_bck++;
1682 else
1683 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001684
1685 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 }
1687 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001688 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001689 int facility;
1690
1691 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1692 curproxy->logfac1 = global.logfac1;
1693 curproxy->logsrv1 = global.logsrv1;
1694 curproxy->loglev1 = global.loglev1;
1695 curproxy->logfac2 = global.logfac2;
1696 curproxy->logsrv2 = global.logsrv2;
1697 curproxy->loglev2 = global.loglev2;
1698 }
1699 else if (*(args[1]) && *(args[2])) {
1700 int level;
1701
1702 facility = get_log_facility(args[2]);
1703 if (facility < 0) {
1704 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1705 exit(1);
1706 }
1707
1708 level = 7; /* max syslog level = debug */
1709 if (*(args[3])) {
1710 level = get_log_level(args[3]);
1711 if (level < 0) {
1712 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1713 exit(1);
1714 }
1715 }
1716
Robert Tsai81ae1952007-12-05 10:47:29 +01001717 if (args[1][0] == '/') {
1718 logsrv.u.addr.sa_family = AF_UNIX;
1719 logsrv.u.un = *str2sun(args[1]);
1720 } else {
1721 logsrv.u.addr.sa_family = AF_INET;
1722 logsrv.u.in = *str2sa(args[1]);
1723 if (!logsrv.u.in.sin_port) {
1724 logsrv.u.in.sin_port =
1725 htons(SYSLOG_PORT);
1726 }
1727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728
1729 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001730 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001731 curproxy->logfac1 = facility;
1732 curproxy->loglev1 = level;
1733 }
1734 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001735 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 curproxy->logfac2 = facility;
1737 curproxy->loglev2 = level;
1738 }
1739 else {
1740 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1741 return -1;
1742 }
1743 }
1744 else {
1745 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1746 file, linenum);
1747 return -1;
1748 }
1749 }
1750 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001751 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1752 return 0;
1753
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001755#ifdef CONFIG_HAP_CTTPROXY
1756 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1757 file, linenum, "source", "usesrc");
1758#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001759 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1760 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001761#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001762 return -1;
1763 }
1764
1765 curproxy->source_addr = *str2sa(args[1]);
1766 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001767 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001768#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001769 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1770 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1771 file, linenum, "usesrc");
1772 return -1;
1773 }
1774 if (!*args[3]) {
1775 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1776 file, linenum, "usesrc");
1777 return -1;
1778 }
1779
1780 if (!strcmp(args[3], "client")) {
1781 curproxy->options |= PR_O_TPXY_CLI;
1782 } else if (!strcmp(args[3], "clientip")) {
1783 curproxy->options |= PR_O_TPXY_CIP;
1784 } else {
1785 curproxy->options |= PR_O_TPXY_ADDR;
1786 curproxy->tproxy_addr = *str2sa(args[3]);
1787 }
1788 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001789#else /* no CTTPROXY support */
1790 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1791 file, linenum, "usesrc");
1792 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001793#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001794 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001795 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001796#ifdef CONFIG_HAP_CTTPROXY
1797 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1798 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1799 file, linenum, "usesrc", "source");
1800 return -1;
1801 }
1802#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001803 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1804 regex_t *preg;
1805 if (curproxy == &defproxy) {
1806 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1807 return -1;
1808 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001809 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1810 return 0;
1811
Willy Tarreaubaaee002006-06-26 02:48:02 +02001812 if (*(args[1]) == 0 || *(args[2]) == 0) {
1813 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1814 file, linenum, args[0]);
1815 return -1;
1816 }
1817
1818 preg = calloc(1, sizeof(regex_t));
1819 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1820 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1821 return -1;
1822 }
1823
1824 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1825 if (err) {
1826 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1827 file, linenum, *err);
1828 return -1;
1829 }
1830 }
1831 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1832 regex_t *preg;
1833 if (curproxy == &defproxy) {
1834 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1835 return -1;
1836 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001837 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1838 return 0;
1839
Willy Tarreaubaaee002006-06-26 02:48:02 +02001840 if (*(args[1]) == 0) {
1841 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1842 return -1;
1843 }
1844
1845 preg = calloc(1, sizeof(regex_t));
1846 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1847 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1848 return -1;
1849 }
1850
1851 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1852 }
1853 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1854 regex_t *preg;
1855 if (curproxy == &defproxy) {
1856 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1857 return -1;
1858 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001859 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1860 return 0;
1861
Willy Tarreaubaaee002006-06-26 02:48:02 +02001862 if (*(args[1]) == 0) {
1863 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1864 return -1;
1865 }
1866
1867 preg = calloc(1, sizeof(regex_t));
1868 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1869 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1870 return -1;
1871 }
1872
1873 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1874 }
1875 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1876 regex_t *preg;
1877 if (curproxy == &defproxy) {
1878 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1879 return -1;
1880 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001881 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1882 return 0;
1883
Willy Tarreaubaaee002006-06-26 02:48:02 +02001884 if (*(args[1]) == 0) {
1885 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1886 return -1;
1887 }
1888
1889 preg = calloc(1, sizeof(regex_t));
1890 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1891 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1892 return -1;
1893 }
1894
1895 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1896 }
1897 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1898 regex_t *preg;
1899 if (curproxy == &defproxy) {
1900 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1901 return -1;
1902 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001903 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1904 return 0;
1905
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906 if (*(args[1]) == 0) {
1907 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1908 return -1;
1909 }
1910
1911 preg = calloc(1, sizeof(regex_t));
1912 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1913 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1914 return -1;
1915 }
1916
1917 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1918 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001919 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1920 regex_t *preg;
1921 if (curproxy == &defproxy) {
1922 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1923 return -1;
1924 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001925 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1926 return 0;
1927
Willy Tarreaub8750a82006-09-03 09:56:00 +02001928 if (*(args[1]) == 0) {
1929 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1930 return -1;
1931 }
1932
1933 preg = calloc(1, sizeof(regex_t));
1934 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1935 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1936 return -1;
1937 }
1938
1939 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1940 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001941 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1942 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001943 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001944 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1945 return -1;
1946 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001947 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1948 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001949
Willy Tarreau977b8e42006-12-29 14:19:17 +01001950 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001951 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1952 file, linenum, args[0]);
1953 return -1;
1954 }
1955
1956 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001957 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001958 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1959 }
1960
1961 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1962 }
1963 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1964 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001965 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001966 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1967 return -1;
1968 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001969 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1970 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001971
Willy Tarreau977b8e42006-12-29 14:19:17 +01001972 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001973 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1974 file, linenum, args[0]);
1975 return -1;
1976 }
1977
1978 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001979 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001980 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1981 }
1982
1983 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001985 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1986 regex_t *preg;
1987 if (curproxy == &defproxy) {
1988 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1989 return -1;
1990 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001991 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1992 return 0;
1993
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994 if (*(args[1]) == 0 || *(args[2]) == 0) {
1995 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1996 file, linenum, args[0]);
1997 return -1;
1998 }
1999
2000 preg = calloc(1, sizeof(regex_t));
2001 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2002 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2003 return -1;
2004 }
2005
2006 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2007 if (err) {
2008 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2009 file, linenum, *err);
2010 return -1;
2011 }
2012 }
2013 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2014 regex_t *preg;
2015 if (curproxy == &defproxy) {
2016 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2017 return -1;
2018 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002019 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2020 return 0;
2021
Willy Tarreaubaaee002006-06-26 02:48:02 +02002022 if (*(args[1]) == 0) {
2023 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2024 return -1;
2025 }
2026
2027 preg = calloc(1, sizeof(regex_t));
2028 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2029 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2030 return -1;
2031 }
2032
2033 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2034 }
2035 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2036 regex_t *preg;
2037 if (curproxy == &defproxy) {
2038 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2039 return -1;
2040 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002041 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2042 return 0;
2043
Willy Tarreaubaaee002006-06-26 02:48:02 +02002044 if (*(args[1]) == 0) {
2045 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2046 return -1;
2047 }
2048
2049 preg = calloc(1, sizeof(regex_t));
2050 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2051 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2052 return -1;
2053 }
2054
2055 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2056 }
2057 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2058 regex_t *preg;
2059 if (curproxy == &defproxy) {
2060 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2061 return -1;
2062 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002063 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2064 return 0;
2065
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066 if (*(args[1]) == 0) {
2067 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2068 return -1;
2069 }
2070
2071 preg = calloc(1, sizeof(regex_t));
2072 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2073 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2074 return -1;
2075 }
2076
2077 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2078 }
2079 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2080 regex_t *preg;
2081 if (curproxy == &defproxy) {
2082 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2083 return -1;
2084 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002085 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2086 return 0;
2087
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 if (*(args[1]) == 0) {
2089 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2090 return -1;
2091 }
2092
2093 preg = calloc(1, sizeof(regex_t));
2094 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2095 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2096 return -1;
2097 }
2098
2099 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2100 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002101 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2102 regex_t *preg;
2103 if (curproxy == &defproxy) {
2104 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2105 return -1;
2106 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002107 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2108 return 0;
2109
Willy Tarreaub8750a82006-09-03 09:56:00 +02002110 if (*(args[1]) == 0) {
2111 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2112 return -1;
2113 }
2114
2115 preg = calloc(1, sizeof(regex_t));
2116 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2117 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2118 return -1;
2119 }
2120
2121 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2122 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002123 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2124 if (curproxy == &defproxy) {
2125 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2126 return -1;
2127 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002128 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2129 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002130
2131 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2132 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2133 return 0;
2134 }
2135
2136 if (*(args[1]) == 0) {
2137 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2138 return -1;
2139 }
2140
2141 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2142 }
2143 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2144 regex_t *preg;
2145
2146 if (*(args[1]) == 0 || *(args[2]) == 0) {
2147 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2148 file, linenum, args[0]);
2149 return -1;
2150 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002151 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2152 return 0;
2153
Willy Tarreaubaaee002006-06-26 02:48:02 +02002154 preg = calloc(1, sizeof(regex_t));
2155 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2156 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2157 return -1;
2158 }
2159
2160 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2161 if (err) {
2162 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2163 file, linenum, *err);
2164 return -1;
2165 }
2166 }
2167 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2168 regex_t *preg;
2169 if (curproxy == &defproxy) {
2170 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2171 return -1;
2172 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002173 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2174 return 0;
2175
Willy Tarreaubaaee002006-06-26 02:48:02 +02002176 if (*(args[1]) == 0) {
2177 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2178 return -1;
2179 }
2180
2181 preg = calloc(1, sizeof(regex_t));
2182 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2183 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2184 return -1;
2185 }
2186
2187 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2188 if (err) {
2189 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2190 file, linenum, *err);
2191 return -1;
2192 }
2193 }
2194 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2195 regex_t *preg;
2196 if (curproxy == &defproxy) {
2197 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2198 return -1;
2199 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002200 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2201 return 0;
2202
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 if (*(args[1]) == 0) {
2204 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2205 return -1;
2206 }
2207
2208 preg = calloc(1, sizeof(regex_t));
2209 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2210 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2211 return -1;
2212 }
2213
2214 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2215 if (err) {
2216 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2217 file, linenum, *err);
2218 return -1;
2219 }
2220 }
2221 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2222 regex_t *preg;
2223 if (curproxy == &defproxy) {
2224 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2225 return -1;
2226 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002227 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2228 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002229
2230 if (*(args[1]) == 0 || *(args[2]) == 0) {
2231 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2232 file, linenum, args[0]);
2233 return -1;
2234 }
2235
2236 preg = calloc(1, sizeof(regex_t));
2237 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2238 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2239 return -1;
2240 }
2241
2242 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2243 if (err) {
2244 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2245 file, linenum, *err);
2246 return -1;
2247 }
2248 }
2249 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2250 regex_t *preg;
2251 if (curproxy == &defproxy) {
2252 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2253 return -1;
2254 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002255 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2256 return 0;
2257
Willy Tarreaubaaee002006-06-26 02:48:02 +02002258 if (*(args[1]) == 0) {
2259 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2260 return -1;
2261 }
2262
2263 preg = calloc(1, sizeof(regex_t));
2264 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2265 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2266 return -1;
2267 }
2268
2269 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2270 if (err) {
2271 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2272 file, linenum, *err);
2273 return -1;
2274 }
2275 }
2276 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2277 regex_t *preg;
2278 if (curproxy == &defproxy) {
2279 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2280 return -1;
2281 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002282 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2283 return 0;
2284
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285 if (*(args[1]) == 0) {
2286 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2287 return -1;
2288 }
2289
2290 preg = calloc(1, sizeof(regex_t));
2291 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2292 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2293 return -1;
2294 }
2295
2296 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2297 if (err) {
2298 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2299 file, linenum, *err);
2300 return -1;
2301 }
2302 }
2303 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2304 if (curproxy == &defproxy) {
2305 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2306 return -1;
2307 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002308 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2309 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002310
2311 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2312 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2313 return 0;
2314 }
2315
2316 if (*(args[1]) == 0) {
2317 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2318 return -1;
2319 }
2320
2321 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2322 }
2323 else if (!strcmp(args[0], "errorloc") ||
2324 !strcmp(args[0], "errorloc302") ||
2325 !strcmp(args[0], "errorloc303")) { /* error location */
2326 int errnum, errlen;
2327 char *err;
2328
Willy Tarreau977b8e42006-12-29 14:19:17 +01002329 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2330 return 0;
2331
Willy Tarreaubaaee002006-06-26 02:48:02 +02002332 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002333 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 return -1;
2335 }
2336
2337 errnum = atol(args[1]);
2338 if (!strcmp(args[0], "errorloc303")) {
2339 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2340 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2341 } else {
2342 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2343 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2344 }
2345
Willy Tarreau0f772532006-12-23 20:51:41 +01002346 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2347 if (http_err_codes[rc] == errnum) {
2348 if (curproxy->errmsg[rc].str)
2349 free(curproxy->errmsg[rc].str);
2350 curproxy->errmsg[rc].str = err;
2351 curproxy->errmsg[rc].len = errlen;
2352 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002355
2356 if (rc >= HTTP_ERR_SIZE) {
2357 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2358 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 free(err);
2360 }
2361 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002362 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2363 int errnum, errlen, fd;
2364 char *err;
2365 struct stat stat;
2366
2367 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2368 return 0;
2369
2370 if (*(args[2]) == 0) {
2371 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2372 return -1;
2373 }
2374
2375 fd = open(args[2], O_RDONLY);
2376 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2377 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2378 file, linenum, args[2], args[1]);
2379 if (fd >= 0)
2380 close(fd);
2381 return -1;
2382 }
2383
2384 if (stat.st_size <= BUFSIZE) {
2385 errlen = stat.st_size;
2386 } else {
2387 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2388 file, linenum, args[2], BUFSIZE);
2389 errlen = BUFSIZE;
2390 }
2391
2392 err = malloc(errlen); /* malloc() must succeed during parsing */
2393 errnum = read(fd, err, errlen);
2394 if (errnum != errlen) {
2395 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2396 file, linenum, args[2], args[1]);
2397 close(fd);
2398 free(err);
2399 return -1;
2400 }
2401 close(fd);
2402
2403 errnum = atol(args[1]);
2404 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2405 if (http_err_codes[rc] == errnum) {
2406 if (curproxy->errmsg[rc].str)
2407 free(curproxy->errmsg[rc].str);
2408 curproxy->errmsg[rc].str = err;
2409 curproxy->errmsg[rc].len = errlen;
2410 break;
2411 }
2412 }
2413
2414 if (rc >= HTTP_ERR_SIZE) {
2415 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2416 file, linenum, errnum);
2417 free(err);
2418 }
2419 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 else {
2421 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2422 return -1;
2423 }
2424 return 0;
2425}
2426
2427
2428/*
2429 * This function reads and parses the configuration file given in the argument.
2430 * returns 0 if OK, -1 if error.
2431 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002432int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002434 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 FILE *f;
2436 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 int confsect = CFG_NONE;
2439
2440 struct proxy *curproxy = NULL;
2441 struct server *newsrv = NULL;
2442
2443 if ((f=fopen(file,"r")) == NULL)
2444 return -1;
2445
2446 init_default_instance();
2447
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002448 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002449 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002450 char *end;
2451 char *args[MAX_LINE_ARGS + 1];
2452 char *line = thisline;
2453
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454 linenum++;
2455
2456 end = line + strlen(line);
2457
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002458 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2459 /* Check if we reached the limit and the last char is not \n.
2460 * Watch out for the last line without the terminating '\n'!
2461 */
2462 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2463 file, linenum, sizeof(thisline)-1);
2464 return -1;
2465 }
2466
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002468 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002469 line++;
2470
2471 arg = 0;
2472 args[arg] = line;
2473
2474 while (*line && arg < MAX_LINE_ARGS) {
2475 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2476 * C equivalent value. Other combinations left unchanged (eg: \1).
2477 */
2478 if (*line == '\\') {
2479 int skip = 0;
2480 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2481 *line = line[1];
2482 skip = 1;
2483 }
2484 else if (line[1] == 'r') {
2485 *line = '\r';
2486 skip = 1;
2487 }
2488 else if (line[1] == 'n') {
2489 *line = '\n';
2490 skip = 1;
2491 }
2492 else if (line[1] == 't') {
2493 *line = '\t';
2494 skip = 1;
2495 }
2496 else if (line[1] == 'x') {
2497 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2498 unsigned char hex1, hex2;
2499 hex1 = toupper(line[2]) - '0';
2500 hex2 = toupper(line[3]) - '0';
2501 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2502 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2503 *line = (hex1<<4) + hex2;
2504 skip = 3;
2505 }
2506 else {
2507 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2508 return -1;
2509 }
2510 }
2511 if (skip) {
2512 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2513 end -= skip;
2514 }
2515 line++;
2516 }
2517 else if (*line == '#' || *line == '\n' || *line == '\r') {
2518 /* end of string, end of loop */
2519 *line = 0;
2520 break;
2521 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002522 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002524 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002525 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 line++;
2527 args[++arg] = line;
2528 }
2529 else {
2530 line++;
2531 }
2532 }
2533
2534 /* empty line */
2535 if (!**args)
2536 continue;
2537
Willy Tarreau540abe42007-05-02 20:50:16 +02002538 /* zero out remaining args and ensure that at least one entry
2539 * is zeroed out.
2540 */
2541 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 args[arg] = line;
2543 }
2544
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002545 if (!strcmp(args[0], "no")) {
2546 inv = 1;
2547 for (arg=0; *args[arg+1]; arg++)
2548 args[arg] = args[arg+1]; // shift args after inversion
2549 }
2550
2551 if (inv && strcmp(args[0], "option")) {
2552 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
2553 return -1;
2554 }
2555
Willy Tarreau977b8e42006-12-29 14:19:17 +01002556 if (!strcmp(args[0], "listen") ||
2557 !strcmp(args[0], "frontend") ||
2558 !strcmp(args[0], "backend") ||
2559 !strcmp(args[0], "ruleset") ||
2560 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 confsect = CFG_LISTEN;
2562 else if (!strcmp(args[0], "global")) /* global config */
2563 confsect = CFG_GLOBAL;
2564 /* else it's a section keyword */
2565
2566 switch (confsect) {
2567 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002568 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 return -1;
2570 break;
2571 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002572 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 return -1;
2574 break;
2575 default:
2576 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2577 return -1;
2578 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 }
2580 fclose(f);
2581
2582 /*
2583 * Now, check for the integrity of all that we have collected.
2584 */
2585
2586 /* will be needed further to delay some tasks */
2587 tv_now(&now);
2588
2589 if ((curproxy = proxy) == NULL) {
2590 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2591 file);
2592 return -1;
2593 }
2594
2595 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002596 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002597 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002598
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599 if (curproxy->state == PR_STSTOPPED) {
2600 curproxy = curproxy->next;
2601 continue;
2602 }
2603
Willy Tarreau977b8e42006-12-29 14:19:17 +01002604 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2605 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 +01002606 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 cfgerr++;
2608 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002609 else if (curproxy->cap & PR_CAP_BE &&
2610 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002611 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002612 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002613 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2614 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 +01002615 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616 cfgerr++;
2617 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002618
Willy Tarreau31682232007-11-29 15:38:04 +01002619 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002620 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002621 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002622 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623 cfgerr++;
2624 }
2625#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2626 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002627 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002628 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629 cfgerr++;
2630 }
2631#endif
2632 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002633 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002634 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002635 }
2636 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002637
2638 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002639 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002640 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002641 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002644 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002645 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646 }
2647 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002648 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002649 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002650 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002651 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002652 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002653 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002654 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002655 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002656 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2657 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002658
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002659 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002660 file, proxy_type_str(curproxy), curproxy->id);
2661 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002662 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002663
2664 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2665 if ((newsrv = curproxy->srv) != NULL) {
2666 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2667 file, proxy_type_str(curproxy), curproxy->id);
2668 }
2669 }
2670
2671 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2673 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2674 file, curproxy->id);
2675 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002676 }
2677 }
2678
Willy Tarreau82936582007-11-30 15:20:09 +01002679 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2680 curproxy->options &= ~PR_O_DISABLE404;
2681 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2682 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2683 }
2684
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002685 /* if a default backend was specified, let's find it */
2686 if (curproxy->defbe.name) {
2687 struct proxy *target;
2688
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002689 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2690 if (!target) {
2691 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2692 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002693 cfgerr++;
2694 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002695 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2696 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002697 } else {
2698 free(curproxy->defbe.name);
2699 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 }
2701 }
2702
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002703 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002704 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2705 /* map jump target for ACT_SETBE in req_rep chain */
2706 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002707 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002708 struct proxy *target;
2709
Willy Tarreaua496b602006-12-17 23:15:24 +01002710 if (exp->action != ACT_SETBE)
2711 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002712
2713 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2714 if (!target) {
2715 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2716 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002717 cfgerr++;
2718 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002719 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2720 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002721 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002722 } else {
2723 free((void *)exp->replace);
2724 exp->replace = (const char *)target;
2725 }
2726 }
2727 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002728
2729 /* find the target proxy for 'use_backend' rules */
2730 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002731 struct proxy *target;
2732
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002733 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002734
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002735 if (!target) {
2736 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2737 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002738 cfgerr++;
2739 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002740 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2741 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002742 cfgerr++;
2743 } else {
2744 free((void *)rule->be.name);
2745 rule->be.backend = target;
2746 }
2747 }
2748
Willy Tarreau2738a142006-07-08 17:28:09 +02002749 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002750 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->timeout.client)) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02002751 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002752 (!tv_isset(&curproxy->timeout.connect) || !tv_isset(&curproxy->timeout.server))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002753 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002754 " | While not properly invalid, you will certainly encounter various problems\n"
2755 " | with such a configuration. To fix this, please ensure that all following\n"
2756 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002757 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002758 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002759
Willy Tarreau1fa31262007-12-03 00:36:16 +01002760 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
2761 * We must still support older configurations, so let's find out whether those
2762 * parameters have been set or must be copied from contimeouts.
2763 */
2764 if (curproxy != &defproxy) {
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002765 if (!tv_isset(&curproxy->timeout.tarpit) ||
2766 __tv_iseq(&curproxy->timeout.tarpit, &defproxy.timeout.tarpit)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01002767 /* tarpit timeout not set. We search in the following order:
2768 * default.tarpit, curr.connect, default.connect.
2769 */
2770 if (tv_isset(&defproxy.timeout.tarpit))
2771 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002772 else if (tv_isset(&curproxy->timeout.connect))
2773 curproxy->timeout.tarpit = curproxy->timeout.connect;
2774 else if (tv_isset(&defproxy.timeout.connect))
2775 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002776 }
2777 if ((curproxy->cap & PR_CAP_BE) &&
2778 (!tv_isset(&curproxy->timeout.queue) ||
2779 __tv_iseq(&curproxy->timeout.queue, &defproxy.timeout.queue))) {
2780 /* queue timeout not set. We search in the following order:
2781 * default.queue, curr.connect, default.connect.
2782 */
2783 if (tv_isset(&defproxy.timeout.queue))
2784 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002785 else if (tv_isset(&curproxy->timeout.connect))
2786 curproxy->timeout.queue = curproxy->timeout.connect;
2787 else if (tv_isset(&defproxy.timeout.connect))
2788 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002789 }
2790 }
2791
Willy Tarreauf3c69202006-07-09 16:42:34 +02002792 if (curproxy->options & PR_O_SSL3_CHK) {
2793 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2794 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2795 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2796 }
2797
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002798 /* The small pools required for the capture lists */
2799 if (curproxy->nb_req_cap)
2800 curproxy->req_cap_pool = create_pool("ptrcap",
2801 curproxy->nb_req_cap * sizeof(char *),
2802 MEM_F_SHARED);
2803 if (curproxy->nb_rsp_cap)
2804 curproxy->rsp_cap_pool = create_pool("ptrcap",
2805 curproxy->nb_rsp_cap * sizeof(char *),
2806 MEM_F_SHARED);
2807
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002808 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2809 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2810 MEM_F_SHARED);
2811
Willy Tarreau86034312006-12-29 00:10:33 +01002812 /* for backwards compatibility with "listen" instances, if
2813 * fullconn is not set but maxconn is set, then maxconn
2814 * is used.
2815 */
2816 if (!curproxy->fullconn)
2817 curproxy->fullconn = curproxy->maxconn;
2818
Willy Tarreaubaaee002006-06-26 02:48:02 +02002819 /* first, we will invert the servers list order */
2820 newsrv = NULL;
2821 while (curproxy->srv) {
2822 struct server *next;
2823
2824 next = curproxy->srv->next;
2825 curproxy->srv->next = newsrv;
2826 newsrv = curproxy->srv;
2827 if (!next)
2828 break;
2829 curproxy->srv = next;
2830 }
2831
Willy Tarreau20697042007-11-15 23:26:18 +01002832 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01002833 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834
Willy Tarreaub625a082007-11-26 01:15:43 +01002835 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01002836 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01002837 fwrr_init_server_groups(curproxy);
2838 else
2839 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840
2841 if (curproxy->options & PR_O_LOGASAP)
2842 curproxy->to_log &= ~LW_BYTES;
2843
Willy Tarreaubaaee002006-06-26 02:48:02 +02002844 /*
2845 * If this server supports a maxconn parameter, it needs a dedicated
2846 * tasks to fill the emptied slots when a connection leaves.
2847 */
2848 newsrv = curproxy->srv;
2849 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002850 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 /* Only 'minconn' was specified, or it was higher than or equal
2852 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2853 * this will avoid further useless expensive computations.
2854 */
2855 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002856 } else if (newsrv->maxconn && !newsrv->minconn) {
2857 /* minconn was not specified, so we set it to maxconn */
2858 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002859 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2860 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002861 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002862 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002863 }
2864
2865 if (newsrv->maxconn > 0) {
2866 struct task *t;
2867
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002868 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2870 return -1;
2871 }
2872
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002873 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002874 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875 t->state = TASK_IDLE;
2876 t->process = process_srv_queue;
2877 t->context = newsrv;
2878 newsrv->queue_mgt = t;
2879
2880 /* never run it unless specifically woken up */
2881 tv_eternity(&t->expire);
2882 task_queue(t);
2883 }
2884 newsrv = newsrv->next;
2885 }
2886
Willy Tarreaue6b98942007-10-29 01:09:36 +01002887 /* adjust this proxy's listeners */
2888 listener = curproxy->listen;
2889 while (listener) {
2890 if (curproxy->options & PR_O_TCP_NOLING)
2891 listener->options |= LI_O_NOLINGER;
2892 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002893 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002894 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002895 listener->accept = event_accept;
2896 listener->private = curproxy;
2897
2898 listener = listener->next;
2899 }
2900
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 curproxy = curproxy->next;
2902 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002903
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 if (cfgerr > 0) {
2905 Alert("Errors found in configuration file, aborting.\n");
2906 return -1;
2907 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002908
2909 /*
2910 * Recount currently required checks.
2911 */
2912
2913 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
2914 int optnum;
2915
2916 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2917 if (!(curproxy->options & cfg_opts[optnum].val))
2918 continue;
2919
2920 global.last_checks |= cfg_opts[optnum].checks;
2921 }
2922 }
2923
2924 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002925}
2926
2927
2928
2929/*
2930 * Local variables:
2931 * c-indent-level: 8
2932 * c-basic-offset: 8
2933 * End:
2934 */