blob: 0ee060b2e16521448c3446a2a2bd477b252b2492 [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 */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100731 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200732 if (curproxy == &defproxy) {
733 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
734 return -1;
735 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100736 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
737 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200738
739 if (strchr(args[1], ':') == NULL) {
740 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
741 file, linenum, args[0]);
742 return -1;
743 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100744
745 last_listen = curproxy->listen;
746 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 if (!curproxy->listen)
748 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100749 if (*args[2]) {
750#ifdef CONFIG_HAP_LINUX_TPROXY
751 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
752 struct listener *l;
753
754 for (l = curproxy->listen; l != last_listen; l = l->next)
755 l->options |= LI_O_FOREIGN;
756 }
757 else {
758 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
759 file, linenum, args[0]);
760 return -1;
761 }
762#else
763 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
764 file, linenum, args[0]);
765 return -1;
766#endif
767 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200768 global.maxsock++;
769 return 0;
770 }
771 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
772 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
773 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
774 file, linenum, args[0]);
775 return -1;
776 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100777 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
778 return 0;
779
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780 /* flush useless bits */
781 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
782 return 0;
783 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200784 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100785 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
786 return 0;
787
Willy Tarreau1c47f852006-07-09 08:22:27 +0200788 if (!*args[1]) {
789 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
790 file, linenum, args[0]);
791 return -1;
792 }
793
794 if (curproxy->monitor_uri != NULL)
795 free(curproxy->monitor_uri);
796
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100797 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200798 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100799 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200800 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
801
802 return 0;
803 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200804 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
805 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
806 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
807 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
808 else {
809 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
810 return -1;
811 }
812 }
813 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
814 curproxy->state = PR_STSTOPPED;
815 }
816 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
817 curproxy->state = PR_STNEW;
818 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200819 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100820 err = invalid_char(args[1]);
821 if (err) {
822 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
823 file, linenum, *err, args[1]);
824 return -1;
825 }
826
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200827 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
828 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
829 file, linenum, args[1]);
830 return -1;
831 }
832 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 else if (!strcmp(args[0], "cookie")) { /* cookie name */
834 int cur_arg;
835 // if (curproxy == &defproxy) {
836 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
837 // return -1;
838 // }
839
Willy Tarreau977b8e42006-12-29 14:19:17 +0100840 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
841 return 0;
842
Willy Tarreaubaaee002006-06-26 02:48:02 +0200843 if (curproxy->cookie_name != NULL) {
844 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
845 // file, linenum);
846 // return 0;
847 free(curproxy->cookie_name);
848 }
849
850 if (*(args[1]) == 0) {
851 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
852 file, linenum, args[0]);
853 return -1;
854 }
855 curproxy->cookie_name = strdup(args[1]);
856 curproxy->cookie_len = strlen(curproxy->cookie_name);
857
858 cur_arg = 2;
859 while (*(args[cur_arg])) {
860 if (!strcmp(args[cur_arg], "rewrite")) {
861 curproxy->options |= PR_O_COOK_RW;
862 }
863 else if (!strcmp(args[cur_arg], "indirect")) {
864 curproxy->options |= PR_O_COOK_IND;
865 }
866 else if (!strcmp(args[cur_arg], "insert")) {
867 curproxy->options |= PR_O_COOK_INS;
868 }
869 else if (!strcmp(args[cur_arg], "nocache")) {
870 curproxy->options |= PR_O_COOK_NOC;
871 }
872 else if (!strcmp(args[cur_arg], "postonly")) {
873 curproxy->options |= PR_O_COOK_POST;
874 }
875 else if (!strcmp(args[cur_arg], "prefix")) {
876 curproxy->options |= PR_O_COOK_PFX;
877 }
878 else {
879 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
880 file, linenum, args[0]);
881 return -1;
882 }
883 cur_arg++;
884 }
885 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
886 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
887 file, linenum);
888 return -1;
889 }
890
891 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
892 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
893 file, linenum);
894 return -1;
895 }
896 }/* end else if (!strcmp(args[0], "cookie")) */
897 else if (!strcmp(args[0], "appsession")) { /* cookie name */
898 // if (curproxy == &defproxy) {
899 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
900 // return -1;
901 // }
902
Willy Tarreau977b8e42006-12-29 14:19:17 +0100903 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
904 return 0;
905
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906 if (curproxy->appsession_name != NULL) {
907 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
908 // file, linenum);
909 // return 0;
910 free(curproxy->appsession_name);
911 }
912
913 if (*(args[5]) == 0) {
914 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
915 file, linenum, args[0]);
916 return -1;
917 }
918 have_appsession = 1;
919 curproxy->appsession_name = strdup(args[1]);
920 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
921 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100922 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
923 if (err) {
924 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
925 file, linenum, *err, args[0]);
926 return -1;
927 }
Willy Tarreauee991362007-05-14 14:37:50 +0200928 if (val > 0)
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100929 __tv_from_ms(&curproxy->timeout.appsession, val);
Willy Tarreauee991362007-05-14 14:37:50 +0200930 else
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100931 tv_eternity(&curproxy->timeout.appsession);
Willy Tarreauee991362007-05-14 14:37:50 +0200932
Willy Tarreau51041c72007-09-09 21:56:53 +0200933 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
934 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 return -1;
936 }
937 } /* Url App Session */
938 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100939 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
940 return 0;
941
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
943 // if (curproxy == &defproxy) {
944 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
945 // return -1;
946 // }
947
948 if (curproxy->capture_name != NULL) {
949 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
950 // file, linenum, args[0]);
951 // return 0;
952 free(curproxy->capture_name);
953 }
954
955 if (*(args[4]) == 0) {
956 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
957 file, linenum, args[0]);
958 return -1;
959 }
960 curproxy->capture_name = strdup(args[2]);
961 curproxy->capture_namelen = strlen(curproxy->capture_name);
962 curproxy->capture_len = atol(args[4]);
963 if (curproxy->capture_len >= CAPTURE_LEN) {
964 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
965 file, linenum, CAPTURE_LEN - 1);
966 curproxy->capture_len = CAPTURE_LEN - 1;
967 }
968 curproxy->to_log |= LW_COOKIE;
969 }
970 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
971 struct cap_hdr *hdr;
972
973 if (curproxy == &defproxy) {
974 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
975 return -1;
976 }
977
978 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
979 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
980 file, linenum, args[0], args[1]);
981 return -1;
982 }
983
984 hdr = calloc(sizeof(struct cap_hdr), 1);
985 hdr->next = curproxy->req_cap;
986 hdr->name = strdup(args[3]);
987 hdr->namelen = strlen(args[3]);
988 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200989 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200990 hdr->index = curproxy->nb_req_cap++;
991 curproxy->req_cap = hdr;
992 curproxy->to_log |= LW_REQHDR;
993 }
994 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
995 struct cap_hdr *hdr;
996
997 if (curproxy == &defproxy) {
998 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
999 return -1;
1000 }
1001
1002 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1003 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1004 file, linenum, args[0], args[1]);
1005 return -1;
1006 }
1007 hdr = calloc(sizeof(struct cap_hdr), 1);
1008 hdr->next = curproxy->rsp_cap;
1009 hdr->name = strdup(args[3]);
1010 hdr->namelen = strlen(args[3]);
1011 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001012 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001013 hdr->index = curproxy->nb_rsp_cap++;
1014 curproxy->rsp_cap = hdr;
1015 curproxy->to_log |= LW_RSPHDR;
1016 }
1017 else {
1018 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1019 file, linenum, args[0]);
1020 return -1;
1021 }
1022 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001023 else if (!strcmp(args[0], "contimeout") || !strcmp(args[0], "clitimeout") ||
1024 !strcmp(args[0], "srvtimeout") || !strcmp(args[0], "timeout")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001025
Willy Tarreaue219db72007-12-03 01:30:13 +01001026 /* either we have {con|srv|cli}timeout <value> or we have the
1027 * new form: timeout <type> <value>. The parser needs the word
1028 * preceeding the value.
1029 */
1030 const char **start_arg = (const char **)args;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001031
Willy Tarreaue219db72007-12-03 01:30:13 +01001032 if (strcmp(args[0], "timeout") == 0)
1033 start_arg++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001034
Willy Tarreaue219db72007-12-03 01:30:13 +01001035 snprintf(trash, sizeof(trash), "error near '%s'", args[0]);
1036 rc = proxy_parse_timeout(start_arg, curproxy, &defproxy, trash, sizeof(trash));
1037 if (rc < 0) {
1038 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001039 return -1;
1040 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001041 if (rc > 0)
1042 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001043 }
1044 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001045 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1046 return 0;
1047
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048 if (*(args[1]) == 0) {
1049 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1050 file, linenum, args[0]);
1051 return -1;
1052 }
1053 curproxy->conn_retries = atol(args[1]);
1054 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001055 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1056 int pol = ACL_COND_NONE;
1057 struct acl_cond *cond;
1058
1059 if (!strcmp(args[1], "if"))
1060 pol = ACL_COND_IF;
1061 else if (!strcmp(args[1], "unless"))
1062 pol = ACL_COND_UNLESS;
1063
1064 if (pol == ACL_COND_NONE) {
1065 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1066 file, linenum, args[0]);
1067 return -1;
1068 }
1069
1070 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1071 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1072 file, linenum);
1073 return -1;
1074 }
1075 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1076 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001077 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1078 int pol = ACL_COND_NONE;
1079 struct acl_cond *cond;
1080 struct switching_rule *rule;
1081
1082 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1083 return 0;
1084
1085 if (*(args[1]) == 0) {
1086 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1087 return -1;
1088 }
1089
1090 if (!strcmp(args[2], "if"))
1091 pol = ACL_COND_IF;
1092 else if (!strcmp(args[2], "unless"))
1093 pol = ACL_COND_UNLESS;
1094
1095 if (pol == ACL_COND_NONE) {
1096 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1097 file, linenum, args[0]);
1098 return -1;
1099 }
1100
1101 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1102 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1103 file, linenum);
1104 return -1;
1105 }
1106
1107 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1108 rule->cond = cond;
1109 rule->be.name = strdup(args[1]);
1110 LIST_INIT(&rule->list);
1111 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001113 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001114 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1115 return 0;
1116
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1118 curproxy->uri_auth = NULL; /* we must detach from the default config */
1119
1120 if (*(args[1]) == 0) {
1121 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1122 return -1;
1123 } else if (!strcmp(args[1], "uri")) {
1124 if (*(args[2]) == 0) {
1125 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1126 return -1;
1127 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1128 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1129 return -1;
1130 }
1131 } else if (!strcmp(args[1], "realm")) {
1132 if (*(args[2]) == 0) {
1133 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1134 return -1;
1135 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1136 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1137 return -1;
1138 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001139 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001140 unsigned interval;
1141
1142 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1143 if (err) {
1144 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1145 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001146 return -1;
1147 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1148 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1149 return -1;
1150 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151 } else if (!strcmp(args[1], "auth")) {
1152 if (*(args[2]) == 0) {
1153 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1154 return -1;
1155 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1156 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1157 return -1;
1158 }
1159 } else if (!strcmp(args[1], "scope")) {
1160 if (*(args[2]) == 0) {
1161 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1162 return -1;
1163 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1164 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1165 return -1;
1166 }
1167 } else if (!strcmp(args[1], "enable")) {
1168 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1169 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1170 return -1;
1171 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001172 } else if (!strcmp(args[1], "hide-version")) {
1173 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1174 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1175 return -1;
1176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001177 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001178 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001179 file, linenum, args[0]);
1180 return -1;
1181 }
1182 }
1183 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001184 int optnum;
1185
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001186 if (*(args[1]) == '\0') {
1187 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1188 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001189 return -1;
1190 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001191
1192 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1193 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1194 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1195 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001196
1197 if (!inv)
1198 curproxy->options |= cfg_opts[optnum].val;
1199 else
1200 curproxy->options &= ~cfg_opts[optnum].val;
1201
Willy Tarreau13943ab2006-12-31 00:24:10 +01001202 return 0;
1203 }
1204 }
1205
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001206 if (inv) {
1207 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1208 file, linenum, args[1]);
1209 return -1;
1210 }
1211
Willy Tarreau13943ab2006-12-31 00:24:10 +01001212 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 /* generate a complete HTTP log */
1214 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1215 else if (!strcmp(args[1], "tcplog"))
1216 /* generate a detailed TCP log */
1217 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001218 else if (!strcmp(args[1], "tcpka")) {
1219 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001220 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1221 return 0;
1222
1223 if (curproxy->cap & PR_CAP_FE)
1224 curproxy->options |= PR_O_TCP_CLI_KA;
1225 if (curproxy->cap & PR_CAP_BE)
1226 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001227 }
1228 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001229 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1230 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001231 /* use HTTP request to check servers' health */
1232 if (curproxy->check_req != NULL) {
1233 free(curproxy->check_req);
1234 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001235 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001236 curproxy->options &= ~PR_O_SMTP_CHK;
1237 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001238 if (!*args[2]) { /* no argument */
1239 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1240 curproxy->check_len = strlen(DEF_CHECK_REQ);
1241 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001242 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001243 curproxy->check_req = (char *)malloc(reqlen);
1244 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1245 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1246 } else { /* more arguments : METHOD URI [HTTP_VER] */
1247 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1248 if (*args[4])
1249 reqlen += strlen(args[4]);
1250 else
1251 reqlen += strlen("HTTP/1.0");
1252
1253 curproxy->check_req = (char *)malloc(reqlen);
1254 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1255 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1256 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001257 }
1258 else if (!strcmp(args[1], "ssl-hello-chk")) {
1259 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001260 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1261 return 0;
1262
Willy Tarreauf3c69202006-07-09 16:42:34 +02001263 if (curproxy->check_req != NULL) {
1264 free(curproxy->check_req);
1265 }
1266 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001267 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001268 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001269 }
Willy Tarreau23677902007-05-08 23:50:35 +02001270 else if (!strcmp(args[1], "smtpchk")) {
1271 /* use SMTP request to check servers' health */
1272 if (curproxy->check_req != NULL) {
1273 free(curproxy->check_req);
1274 }
1275 curproxy->options &= ~PR_O_HTTP_CHK;
1276 curproxy->options &= ~PR_O_SSL3_CHK;
1277 curproxy->options |= PR_O_SMTP_CHK;
1278
1279 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1280 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1281 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1282 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1283 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1284 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1285 curproxy->check_req = (char *)malloc(reqlen);
1286 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1287 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1288 } else {
1289 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1290 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1291 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1292 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1293 }
1294 }
1295 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001296 else if (!strcmp(args[1], "forwardfor")) {
1297 /* insert x-forwarded-for field, but not for the
1298 * IP address listed as an except.
1299 */
1300 if (*(args[2])) {
1301 if (!strcmp(args[2], "except")) {
1302 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1303 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1304 file, linenum, args[0]);
1305 return -1;
1306 }
1307 /* flush useless bits */
1308 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1309 } else {
1310 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1311 file, linenum, args[0]);
1312 return -1;
1313 }
1314 }
1315 curproxy->options |= PR_O_FWDFOR;
1316 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001317 else {
1318 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1319 return -1;
1320 }
1321 return 0;
1322 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001323 else if (!strcmp(args[0], "default_backend")) {
1324 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1325 return 0;
1326
1327 if (*(args[1]) == 0) {
1328 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1329 return -1;
1330 }
1331 if (curproxy->defbe.name)
1332 free(curproxy->defbe.name);
1333 curproxy->defbe.name = strdup(args[1]);
1334 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001335 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001336 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1337 return 0;
1338
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001339 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1340 file, linenum, args[0]);
1341
Willy Tarreaubaaee002006-06-26 02:48:02 +02001342 /* enable reconnections to dispatch */
1343 curproxy->options |= PR_O_REDISP;
1344 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001345 else if (!strcmp(args[0], "http-check")) {
1346 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1347 return 0;
1348
1349 if (strcmp(args[1], "disable-on-404") == 0) {
1350 /* enable a graceful server shutdown on an HTTP 404 response */
1351 curproxy->options |= PR_O_DISABLE404;
1352 }
1353 else {
1354 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1355 return -1;
1356 }
1357 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001358 else if (!strcmp(args[0], "monitor")) {
1359 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1360 return 0;
1361
1362 if (strcmp(args[1], "fail") == 0) {
1363 /* add a condition to fail monitor requests */
1364 int pol = ACL_COND_NONE;
1365 struct acl_cond *cond;
1366
1367 if (!strcmp(args[2], "if"))
1368 pol = ACL_COND_IF;
1369 else if (!strcmp(args[2], "unless"))
1370 pol = ACL_COND_UNLESS;
1371
1372 if (pol == ACL_COND_NONE) {
1373 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1374 file, linenum, args[0], args[1]);
1375 return -1;
1376 }
1377
1378 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1379 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1380 file, linenum, args[0], args[1]);
1381 return -1;
1382 }
1383 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1384 }
1385 else {
1386 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1387 return -1;
1388 }
1389 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390#ifdef TPROXY
1391 else if (!strcmp(args[0], "transparent")) {
1392 /* enable transparent proxy connections */
1393 curproxy->options |= PR_O_TRANSP;
1394 }
1395#endif
1396 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001397 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1398 return 0;
1399
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 if (*(args[1]) == 0) {
1401 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1402 return -1;
1403 }
1404 curproxy->maxconn = atol(args[1]);
1405 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001406 else if (!strcmp(args[0], "backlog")) { /* backlog */
1407 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1408 return 0;
1409
1410 if (*(args[1]) == 0) {
1411 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1412 return -1;
1413 }
1414 curproxy->backlog = atol(args[1]);
1415 }
Willy Tarreau86034312006-12-29 00:10:33 +01001416 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001417 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1418 return 0;
1419
Willy Tarreau86034312006-12-29 00:10:33 +01001420 if (*(args[1]) == 0) {
1421 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1422 return -1;
1423 }
1424 curproxy->fullconn = atol(args[1]);
1425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001426 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1427 if (*(args[1]) == 0) {
1428 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1429 return -1;
1430 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001431 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1432 if (err) {
1433 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1434 file, linenum, *err);
1435 return -1;
1436 }
1437 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 }
1439 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1440 if (curproxy == &defproxy) {
1441 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1442 return -1;
1443 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001444 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1445 return 0;
1446
Willy Tarreaubaaee002006-06-26 02:48:02 +02001447 if (strchr(args[1], ':') == NULL) {
1448 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1449 return -1;
1450 }
1451 curproxy->dispatch_addr = *str2sa(args[1]);
1452 }
1453 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001454 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1455 return 0;
1456
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001457 memcpy(trash, "error near 'balance'", 19);
1458 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1459 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1460 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001461 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462 }
1463 else if (!strcmp(args[0], "server")) { /* server address */
1464 int cur_arg;
1465 char *rport;
1466 char *raddr;
1467 short realport;
1468 int do_check;
1469
1470 if (curproxy == &defproxy) {
1471 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1472 return -1;
1473 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001474 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1475 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476
1477 if (!*args[2]) {
1478 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1479 file, linenum, args[0]);
1480 return -1;
1481 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001482
1483 err = invalid_char(args[1]);
1484 if (err) {
1485 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1486 file, linenum, *err, args[1]);
1487 return -1;
1488 }
1489
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1491 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1492 return -1;
1493 }
1494
1495 /* the servers are linked backwards first */
1496 newsrv->next = curproxy->srv;
1497 curproxy->srv = newsrv;
1498 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001499 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500
1501 LIST_INIT(&newsrv->pendconns);
1502 do_check = 0;
1503 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001504 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001505 newsrv->id = strdup(args[1]);
1506
1507 /* several ways to check the port component :
1508 * - IP => port=+0, relative
1509 * - IP: => port=+0, relative
1510 * - IP:N => port=N, absolute
1511 * - IP:+N => port=+N, relative
1512 * - IP:-N => port=-N, relative
1513 */
1514 raddr = strdup(args[2]);
1515 rport = strchr(raddr, ':');
1516 if (rport) {
1517 *rport++ = 0;
1518 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001519 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001520 newsrv->state |= SRV_MAPPORTS;
1521 } else {
1522 realport = 0;
1523 newsrv->state |= SRV_MAPPORTS;
1524 }
1525
1526 newsrv->addr = *str2sa(raddr);
1527 newsrv->addr.sin_port = htons(realport);
1528 free(raddr);
1529
1530 newsrv->curfd = -1; /* no health-check in progress */
1531 newsrv->inter = DEF_CHKINTR;
1532 newsrv->rise = DEF_RISETIME;
1533 newsrv->fall = DEF_FALLTIME;
1534 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001535 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001536 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001537 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001538
Willy Tarreaubaaee002006-06-26 02:48:02 +02001539 cur_arg = 3;
1540 while (*args[cur_arg]) {
1541 if (!strcmp(args[cur_arg], "cookie")) {
1542 newsrv->cookie = strdup(args[cur_arg + 1]);
1543 newsrv->cklen = strlen(args[cur_arg + 1]);
1544 cur_arg += 2;
1545 }
1546 else if (!strcmp(args[cur_arg], "rise")) {
1547 newsrv->rise = atol(args[cur_arg + 1]);
1548 newsrv->health = newsrv->rise;
1549 cur_arg += 2;
1550 }
1551 else if (!strcmp(args[cur_arg], "fall")) {
1552 newsrv->fall = atol(args[cur_arg + 1]);
1553 cur_arg += 2;
1554 }
1555 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001556 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1557 if (err) {
1558 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1559 file, linenum, *err, newsrv->id);
1560 return -1;
1561 }
1562 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 cur_arg += 2;
1564 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001565 else if (!strcmp(args[cur_arg], "addr")) {
1566 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001567 cur_arg += 2;
1568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001569 else if (!strcmp(args[cur_arg], "port")) {
1570 newsrv->check_port = atol(args[cur_arg + 1]);
1571 cur_arg += 2;
1572 }
1573 else if (!strcmp(args[cur_arg], "backup")) {
1574 newsrv->state |= SRV_BACKUP;
1575 cur_arg ++;
1576 }
1577 else if (!strcmp(args[cur_arg], "weight")) {
1578 int w;
1579 w = atol(args[cur_arg + 1]);
1580 if (w < 1 || w > 256) {
1581 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1582 file, linenum, newsrv->id, w);
1583 return -1;
1584 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001585 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 cur_arg += 2;
1587 }
1588 else if (!strcmp(args[cur_arg], "minconn")) {
1589 newsrv->minconn = atol(args[cur_arg + 1]);
1590 cur_arg += 2;
1591 }
1592 else if (!strcmp(args[cur_arg], "maxconn")) {
1593 newsrv->maxconn = atol(args[cur_arg + 1]);
1594 cur_arg += 2;
1595 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001596 else if (!strcmp(args[cur_arg], "maxqueue")) {
1597 newsrv->maxqueue = atol(args[cur_arg + 1]);
1598 cur_arg += 2;
1599 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001600 else if (!strcmp(args[cur_arg], "slowstart")) {
1601 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001602 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001603 if (err) {
1604 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1605 file, linenum, *err, newsrv->id);
1606 return -1;
1607 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001608 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001609 cur_arg += 2;
1610 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611 else if (!strcmp(args[cur_arg], "check")) {
1612 global.maxsock++;
1613 do_check = 1;
1614 cur_arg += 1;
1615 }
1616 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1617 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001618#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001619 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1620 file, linenum, "source", "usesrc");
1621#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1623 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001624#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625 return -1;
1626 }
1627 newsrv->state |= SRV_BIND_SRC;
1628 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1629 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001630 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001631#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1632#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001633 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001634 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1635 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001636 return -1;
1637 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001638#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001639 if (!*args[cur_arg + 1]) {
1640 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1641 file, linenum, "usesrc");
1642 return -1;
1643 }
1644 if (!strcmp(args[cur_arg + 1], "client")) {
1645 newsrv->state |= SRV_TPROXY_CLI;
1646 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1647 newsrv->state |= SRV_TPROXY_CIP;
1648 } else {
1649 newsrv->state |= SRV_TPROXY_ADDR;
1650 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1651 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001652 global.last_checks |= LSTCHK_NETADM;
1653#if !defined(CONFIG_HAP_LINUX_TPROXY)
1654 global.last_checks |= LSTCHK_CTTPROXY;
1655#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001656 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001657#else /* no TPROXY support */
1658 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001659 file, linenum, "usesrc");
1660 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001661#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001662 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001663 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001664 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1665 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1666 file, linenum, "usesrc", "source");
1667 return -1;
1668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001669 else {
Willy Tarreau9909fc12007-11-30 17:42:05 +01001670 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 +02001671 file, linenum, newsrv->id);
1672 return -1;
1673 }
1674 }
1675
1676 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001677 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1678 newsrv->check_port = newsrv->check_addr.sin_port;
1679
Willy Tarreaubaaee002006-06-26 02:48:02 +02001680 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1681 newsrv->check_port = realport; /* by default */
1682 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001683 /* not yet valid, because no port was set on
1684 * the server either. We'll check if we have
1685 * a known port on the first listener.
1686 */
1687 struct listener *l;
1688 l = curproxy->listen;
1689 if (l) {
1690 int port;
1691 port = (l->addr.ss_family == AF_INET6)
1692 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1693 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1694 newsrv->check_port = port;
1695 }
1696 }
1697 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1699 file, linenum, newsrv->id);
1700 return -1;
1701 }
1702 newsrv->state |= SRV_CHECKED;
1703 }
1704
1705 if (newsrv->state & SRV_BACKUP)
1706 curproxy->srv_bck++;
1707 else
1708 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001709
1710 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001711 }
1712 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001713 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 int facility;
1715
1716 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1717 curproxy->logfac1 = global.logfac1;
1718 curproxy->logsrv1 = global.logsrv1;
1719 curproxy->loglev1 = global.loglev1;
1720 curproxy->logfac2 = global.logfac2;
1721 curproxy->logsrv2 = global.logsrv2;
1722 curproxy->loglev2 = global.loglev2;
1723 }
1724 else if (*(args[1]) && *(args[2])) {
1725 int level;
1726
1727 facility = get_log_facility(args[2]);
1728 if (facility < 0) {
1729 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1730 exit(1);
1731 }
1732
1733 level = 7; /* max syslog level = debug */
1734 if (*(args[3])) {
1735 level = get_log_level(args[3]);
1736 if (level < 0) {
1737 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1738 exit(1);
1739 }
1740 }
1741
Robert Tsai81ae1952007-12-05 10:47:29 +01001742 if (args[1][0] == '/') {
1743 logsrv.u.addr.sa_family = AF_UNIX;
1744 logsrv.u.un = *str2sun(args[1]);
1745 } else {
1746 logsrv.u.addr.sa_family = AF_INET;
1747 logsrv.u.in = *str2sa(args[1]);
1748 if (!logsrv.u.in.sin_port) {
1749 logsrv.u.in.sin_port =
1750 htons(SYSLOG_PORT);
1751 }
1752 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001753
1754 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001755 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001756 curproxy->logfac1 = facility;
1757 curproxy->loglev1 = level;
1758 }
1759 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001760 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001761 curproxy->logfac2 = facility;
1762 curproxy->loglev2 = level;
1763 }
1764 else {
1765 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1766 return -1;
1767 }
1768 }
1769 else {
1770 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1771 file, linenum);
1772 return -1;
1773 }
1774 }
1775 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001776 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1777 return 0;
1778
Willy Tarreaubaaee002006-06-26 02:48:02 +02001779 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001780#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001781 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1782 file, linenum, "source", "usesrc");
1783#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001784 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1785 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001786#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001787 return -1;
1788 }
1789
1790 curproxy->source_addr = *str2sa(args[1]);
1791 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001792 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001793#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1794#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001795 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1796 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1797 file, linenum, "usesrc");
1798 return -1;
1799 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001800#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001801 if (!*args[3]) {
1802 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1803 file, linenum, "usesrc");
1804 return -1;
1805 }
1806
1807 if (!strcmp(args[3], "client")) {
1808 curproxy->options |= PR_O_TPXY_CLI;
1809 } else if (!strcmp(args[3], "clientip")) {
1810 curproxy->options |= PR_O_TPXY_CIP;
1811 } else {
1812 curproxy->options |= PR_O_TPXY_ADDR;
1813 curproxy->tproxy_addr = *str2sa(args[3]);
1814 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001815 global.last_checks |= LSTCHK_NETADM;
1816#if !defined(CONFIG_HAP_LINUX_TPROXY)
1817 global.last_checks |= LSTCHK_CTTPROXY;
1818#endif
1819#else /* no TPROXY support */
1820 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001821 file, linenum, "usesrc");
1822 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001823#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001824 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001825 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001826 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1827 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1828 file, linenum, "usesrc", "source");
1829 return -1;
1830 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001831 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace 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 || *(args[2]) == 0) {
1841 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1842 file, linenum, args[0]);
1843 return -1;
1844 }
1845
1846 preg = calloc(1, sizeof(regex_t));
1847 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1848 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1849 return -1;
1850 }
1851
1852 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1853 if (err) {
1854 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1855 file, linenum, *err);
1856 return -1;
1857 }
1858 }
1859 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1860 regex_t *preg;
1861 if (curproxy == &defproxy) {
1862 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1863 return -1;
1864 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001865 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1866 return 0;
1867
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 if (*(args[1]) == 0) {
1869 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1870 return -1;
1871 }
1872
1873 preg = calloc(1, sizeof(regex_t));
1874 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1875 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1876 return -1;
1877 }
1878
1879 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1880 }
1881 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1882 regex_t *preg;
1883 if (curproxy == &defproxy) {
1884 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1885 return -1;
1886 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001887 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1888 return 0;
1889
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890 if (*(args[1]) == 0) {
1891 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1892 return -1;
1893 }
1894
1895 preg = calloc(1, sizeof(regex_t));
1896 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1897 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1898 return -1;
1899 }
1900
1901 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1902 }
1903 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1904 regex_t *preg;
1905 if (curproxy == &defproxy) {
1906 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1907 return -1;
1908 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001909 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1910 return 0;
1911
Willy Tarreaubaaee002006-06-26 02:48:02 +02001912 if (*(args[1]) == 0) {
1913 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1914 return -1;
1915 }
1916
1917 preg = calloc(1, sizeof(regex_t));
1918 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1919 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1920 return -1;
1921 }
1922
1923 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1924 }
1925 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1926 regex_t *preg;
1927 if (curproxy == &defproxy) {
1928 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1929 return -1;
1930 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001931 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1932 return 0;
1933
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934 if (*(args[1]) == 0) {
1935 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1936 return -1;
1937 }
1938
1939 preg = calloc(1, sizeof(regex_t));
1940 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1941 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1942 return -1;
1943 }
1944
1945 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1946 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001947 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1948 regex_t *preg;
1949 if (curproxy == &defproxy) {
1950 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1951 return -1;
1952 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001953 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1954 return 0;
1955
Willy Tarreaub8750a82006-09-03 09:56:00 +02001956 if (*(args[1]) == 0) {
1957 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1958 return -1;
1959 }
1960
1961 preg = calloc(1, sizeof(regex_t));
1962 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1963 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1964 return -1;
1965 }
1966
1967 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1968 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001969 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1970 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001971 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001972 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1973 return -1;
1974 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001975 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1976 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001977
Willy Tarreau977b8e42006-12-29 14:19:17 +01001978 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001979 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1980 file, linenum, args[0]);
1981 return -1;
1982 }
1983
1984 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001985 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001986 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1987 }
1988
1989 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1990 }
1991 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1992 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001993 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001994 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1995 return -1;
1996 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001997 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1998 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001999
Willy Tarreau977b8e42006-12-29 14:19:17 +01002000 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002001 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2002 file, linenum, args[0]);
2003 return -1;
2004 }
2005
2006 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002007 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002008 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2009 }
2010
2011 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2012 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002013 else if (!strcmp(args[0], "reqirep")) { /* replace 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 || *(args[2]) == 0) {
2023 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2024 file, linenum, args[0]);
2025 return -1;
2026 }
2027
2028 preg = calloc(1, sizeof(regex_t));
2029 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2030 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2031 return -1;
2032 }
2033
2034 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2035 if (err) {
2036 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2037 file, linenum, *err);
2038 return -1;
2039 }
2040 }
2041 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2042 regex_t *preg;
2043 if (curproxy == &defproxy) {
2044 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2045 return -1;
2046 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002047 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2048 return 0;
2049
Willy Tarreaubaaee002006-06-26 02:48:02 +02002050 if (*(args[1]) == 0) {
2051 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2052 return -1;
2053 }
2054
2055 preg = calloc(1, sizeof(regex_t));
2056 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2057 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2058 return -1;
2059 }
2060
2061 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2062 }
2063 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2064 regex_t *preg;
2065 if (curproxy == &defproxy) {
2066 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2067 return -1;
2068 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002069 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2070 return 0;
2071
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072 if (*(args[1]) == 0) {
2073 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2074 return -1;
2075 }
2076
2077 preg = calloc(1, sizeof(regex_t));
2078 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2079 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2080 return -1;
2081 }
2082
2083 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2084 }
2085 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2086 regex_t *preg;
2087 if (curproxy == &defproxy) {
2088 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2089 return -1;
2090 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002091 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2092 return 0;
2093
Willy Tarreaubaaee002006-06-26 02:48:02 +02002094 if (*(args[1]) == 0) {
2095 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2096 return -1;
2097 }
2098
2099 preg = calloc(1, sizeof(regex_t));
2100 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2101 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2102 return -1;
2103 }
2104
2105 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2106 }
2107 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2108 regex_t *preg;
2109 if (curproxy == &defproxy) {
2110 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2111 return -1;
2112 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002113 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2114 return 0;
2115
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116 if (*(args[1]) == 0) {
2117 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2118 return -1;
2119 }
2120
2121 preg = calloc(1, sizeof(regex_t));
2122 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2123 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2124 return -1;
2125 }
2126
2127 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2128 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002129 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2130 regex_t *preg;
2131 if (curproxy == &defproxy) {
2132 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2133 return -1;
2134 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002135 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2136 return 0;
2137
Willy Tarreaub8750a82006-09-03 09:56:00 +02002138 if (*(args[1]) == 0) {
2139 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2140 return -1;
2141 }
2142
2143 preg = calloc(1, sizeof(regex_t));
2144 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2145 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2146 return -1;
2147 }
2148
2149 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2150 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002151 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2152 if (curproxy == &defproxy) {
2153 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2154 return -1;
2155 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002156 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2157 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002158
2159 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2160 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2161 return 0;
2162 }
2163
2164 if (*(args[1]) == 0) {
2165 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2166 return -1;
2167 }
2168
2169 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2170 }
2171 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2172 regex_t *preg;
2173
2174 if (*(args[1]) == 0 || *(args[2]) == 0) {
2175 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2176 file, linenum, args[0]);
2177 return -1;
2178 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002179 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2180 return 0;
2181
Willy Tarreaubaaee002006-06-26 02:48:02 +02002182 preg = calloc(1, sizeof(regex_t));
2183 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2184 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2185 return -1;
2186 }
2187
2188 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2189 if (err) {
2190 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2191 file, linenum, *err);
2192 return -1;
2193 }
2194 }
2195 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2196 regex_t *preg;
2197 if (curproxy == &defproxy) {
2198 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2199 return -1;
2200 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002201 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2202 return 0;
2203
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 if (*(args[1]) == 0) {
2205 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2206 return -1;
2207 }
2208
2209 preg = calloc(1, sizeof(regex_t));
2210 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2211 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2212 return -1;
2213 }
2214
2215 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2216 if (err) {
2217 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2218 file, linenum, *err);
2219 return -1;
2220 }
2221 }
2222 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2223 regex_t *preg;
2224 if (curproxy == &defproxy) {
2225 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2226 return -1;
2227 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002228 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2229 return 0;
2230
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 if (*(args[1]) == 0) {
2232 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2233 return -1;
2234 }
2235
2236 preg = calloc(1, sizeof(regex_t));
2237 if (regcomp(preg, args[1], REG_EXTENDED) != 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_DENY, 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], "rspirep")) { /* replace 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;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257
2258 if (*(args[1]) == 0 || *(args[2]) == 0) {
2259 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2260 file, linenum, args[0]);
2261 return -1;
2262 }
2263
2264 preg = calloc(1, sizeof(regex_t));
2265 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2266 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2267 return -1;
2268 }
2269
2270 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2271 if (err) {
2272 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2273 file, linenum, *err);
2274 return -1;
2275 }
2276 }
2277 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2278 regex_t *preg;
2279 if (curproxy == &defproxy) {
2280 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2281 return -1;
2282 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002283 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2284 return 0;
2285
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 if (*(args[1]) == 0) {
2287 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2288 return -1;
2289 }
2290
2291 preg = calloc(1, sizeof(regex_t));
2292 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2293 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2294 return -1;
2295 }
2296
2297 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2298 if (err) {
2299 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2300 file, linenum, *err);
2301 return -1;
2302 }
2303 }
2304 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2305 regex_t *preg;
2306 if (curproxy == &defproxy) {
2307 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2308 return -1;
2309 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002310 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2311 return 0;
2312
Willy Tarreaubaaee002006-06-26 02:48:02 +02002313 if (*(args[1]) == 0) {
2314 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2315 return -1;
2316 }
2317
2318 preg = calloc(1, sizeof(regex_t));
2319 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2320 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2321 return -1;
2322 }
2323
2324 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2325 if (err) {
2326 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2327 file, linenum, *err);
2328 return -1;
2329 }
2330 }
2331 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2332 if (curproxy == &defproxy) {
2333 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2334 return -1;
2335 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002336 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2337 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002338
2339 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2340 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2341 return 0;
2342 }
2343
2344 if (*(args[1]) == 0) {
2345 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2346 return -1;
2347 }
2348
2349 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2350 }
2351 else if (!strcmp(args[0], "errorloc") ||
2352 !strcmp(args[0], "errorloc302") ||
2353 !strcmp(args[0], "errorloc303")) { /* error location */
2354 int errnum, errlen;
2355 char *err;
2356
Willy Tarreau977b8e42006-12-29 14:19:17 +01002357 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2358 return 0;
2359
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002361 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 return -1;
2363 }
2364
2365 errnum = atol(args[1]);
2366 if (!strcmp(args[0], "errorloc303")) {
2367 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2368 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2369 } else {
2370 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2371 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2372 }
2373
Willy Tarreau0f772532006-12-23 20:51:41 +01002374 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2375 if (http_err_codes[rc] == errnum) {
2376 if (curproxy->errmsg[rc].str)
2377 free(curproxy->errmsg[rc].str);
2378 curproxy->errmsg[rc].str = err;
2379 curproxy->errmsg[rc].len = errlen;
2380 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002382 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002383
2384 if (rc >= HTTP_ERR_SIZE) {
2385 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2386 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387 free(err);
2388 }
2389 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002390 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2391 int errnum, errlen, fd;
2392 char *err;
2393 struct stat stat;
2394
2395 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2396 return 0;
2397
2398 if (*(args[2]) == 0) {
2399 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2400 return -1;
2401 }
2402
2403 fd = open(args[2], O_RDONLY);
2404 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2405 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2406 file, linenum, args[2], args[1]);
2407 if (fd >= 0)
2408 close(fd);
2409 return -1;
2410 }
2411
2412 if (stat.st_size <= BUFSIZE) {
2413 errlen = stat.st_size;
2414 } else {
2415 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2416 file, linenum, args[2], BUFSIZE);
2417 errlen = BUFSIZE;
2418 }
2419
2420 err = malloc(errlen); /* malloc() must succeed during parsing */
2421 errnum = read(fd, err, errlen);
2422 if (errnum != errlen) {
2423 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2424 file, linenum, args[2], args[1]);
2425 close(fd);
2426 free(err);
2427 return -1;
2428 }
2429 close(fd);
2430
2431 errnum = atol(args[1]);
2432 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2433 if (http_err_codes[rc] == errnum) {
2434 if (curproxy->errmsg[rc].str)
2435 free(curproxy->errmsg[rc].str);
2436 curproxy->errmsg[rc].str = err;
2437 curproxy->errmsg[rc].len = errlen;
2438 break;
2439 }
2440 }
2441
2442 if (rc >= HTTP_ERR_SIZE) {
2443 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2444 file, linenum, errnum);
2445 free(err);
2446 }
2447 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 else {
2449 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2450 return -1;
2451 }
2452 return 0;
2453}
2454
2455
2456/*
2457 * This function reads and parses the configuration file given in the argument.
2458 * returns 0 if OK, -1 if error.
2459 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002460int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002462 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 FILE *f;
2464 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002465 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 int confsect = CFG_NONE;
2467
2468 struct proxy *curproxy = NULL;
2469 struct server *newsrv = NULL;
2470
2471 if ((f=fopen(file,"r")) == NULL)
2472 return -1;
2473
2474 init_default_instance();
2475
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002476 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002477 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002478 char *end;
2479 char *args[MAX_LINE_ARGS + 1];
2480 char *line = thisline;
2481
Willy Tarreaubaaee002006-06-26 02:48:02 +02002482 linenum++;
2483
2484 end = line + strlen(line);
2485
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002486 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2487 /* Check if we reached the limit and the last char is not \n.
2488 * Watch out for the last line without the terminating '\n'!
2489 */
2490 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2491 file, linenum, sizeof(thisline)-1);
2492 return -1;
2493 }
2494
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002496 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497 line++;
2498
2499 arg = 0;
2500 args[arg] = line;
2501
2502 while (*line && arg < MAX_LINE_ARGS) {
2503 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2504 * C equivalent value. Other combinations left unchanged (eg: \1).
2505 */
2506 if (*line == '\\') {
2507 int skip = 0;
2508 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2509 *line = line[1];
2510 skip = 1;
2511 }
2512 else if (line[1] == 'r') {
2513 *line = '\r';
2514 skip = 1;
2515 }
2516 else if (line[1] == 'n') {
2517 *line = '\n';
2518 skip = 1;
2519 }
2520 else if (line[1] == 't') {
2521 *line = '\t';
2522 skip = 1;
2523 }
2524 else if (line[1] == 'x') {
2525 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2526 unsigned char hex1, hex2;
2527 hex1 = toupper(line[2]) - '0';
2528 hex2 = toupper(line[3]) - '0';
2529 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2530 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2531 *line = (hex1<<4) + hex2;
2532 skip = 3;
2533 }
2534 else {
2535 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2536 return -1;
2537 }
2538 }
2539 if (skip) {
2540 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2541 end -= skip;
2542 }
2543 line++;
2544 }
2545 else if (*line == '#' || *line == '\n' || *line == '\r') {
2546 /* end of string, end of loop */
2547 *line = 0;
2548 break;
2549 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002550 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002552 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002553 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554 line++;
2555 args[++arg] = line;
2556 }
2557 else {
2558 line++;
2559 }
2560 }
2561
2562 /* empty line */
2563 if (!**args)
2564 continue;
2565
Willy Tarreau540abe42007-05-02 20:50:16 +02002566 /* zero out remaining args and ensure that at least one entry
2567 * is zeroed out.
2568 */
2569 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 args[arg] = line;
2571 }
2572
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002573 if (!strcmp(args[0], "no")) {
2574 inv = 1;
2575 for (arg=0; *args[arg+1]; arg++)
2576 args[arg] = args[arg+1]; // shift args after inversion
2577 }
2578
2579 if (inv && strcmp(args[0], "option")) {
2580 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
2581 return -1;
2582 }
2583
Willy Tarreau977b8e42006-12-29 14:19:17 +01002584 if (!strcmp(args[0], "listen") ||
2585 !strcmp(args[0], "frontend") ||
2586 !strcmp(args[0], "backend") ||
2587 !strcmp(args[0], "ruleset") ||
2588 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 confsect = CFG_LISTEN;
2590 else if (!strcmp(args[0], "global")) /* global config */
2591 confsect = CFG_GLOBAL;
2592 /* else it's a section keyword */
2593
2594 switch (confsect) {
2595 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002596 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 return -1;
2598 break;
2599 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002600 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002601 return -1;
2602 break;
2603 default:
2604 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2605 return -1;
2606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 }
2608 fclose(f);
2609
2610 /*
2611 * Now, check for the integrity of all that we have collected.
2612 */
2613
2614 /* will be needed further to delay some tasks */
2615 tv_now(&now);
2616
2617 if ((curproxy = proxy) == NULL) {
2618 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2619 file);
2620 return -1;
2621 }
2622
2623 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002624 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002625 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002626
Willy Tarreaubaaee002006-06-26 02:48:02 +02002627 if (curproxy->state == PR_STSTOPPED) {
2628 curproxy = curproxy->next;
2629 continue;
2630 }
2631
Willy Tarreau977b8e42006-12-29 14:19:17 +01002632 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2633 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 +01002634 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002635 cfgerr++;
2636 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002637 else if (curproxy->cap & PR_CAP_BE &&
2638 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002639 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002640 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002641 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2642 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 +01002643 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002644 cfgerr++;
2645 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002646
Willy Tarreau31682232007-11-29 15:38:04 +01002647 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002648 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002649 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002650 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651 cfgerr++;
2652 }
2653#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2654 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002655 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002656 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657 cfgerr++;
2658 }
2659#endif
2660 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002661 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002662 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002663 }
2664 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002665
2666 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002668 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002669 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002670 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002671 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002672 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002673 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002674 }
2675 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002676 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002677 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002678 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002679 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002680 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002681 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002682 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002683 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002684 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2685 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002686
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002687 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002688 file, proxy_type_str(curproxy), curproxy->id);
2689 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002690 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002691
2692 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2693 if ((newsrv = curproxy->srv) != NULL) {
2694 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2695 file, proxy_type_str(curproxy), curproxy->id);
2696 }
2697 }
2698
2699 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2701 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2702 file, curproxy->id);
2703 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002704 }
2705 }
2706
Willy Tarreau82936582007-11-30 15:20:09 +01002707 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2708 curproxy->options &= ~PR_O_DISABLE404;
2709 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2710 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2711 }
2712
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002713 /* if a default backend was specified, let's find it */
2714 if (curproxy->defbe.name) {
2715 struct proxy *target;
2716
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002717 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2718 if (!target) {
2719 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2720 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002721 cfgerr++;
2722 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002723 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2724 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002725 } else {
2726 free(curproxy->defbe.name);
2727 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728 }
2729 }
2730
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002731 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002732 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2733 /* map jump target for ACT_SETBE in req_rep chain */
2734 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002735 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002736 struct proxy *target;
2737
Willy Tarreaua496b602006-12-17 23:15:24 +01002738 if (exp->action != ACT_SETBE)
2739 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002740
2741 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2742 if (!target) {
2743 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2744 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002745 cfgerr++;
2746 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002747 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2748 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002749 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002750 } else {
2751 free((void *)exp->replace);
2752 exp->replace = (const char *)target;
2753 }
2754 }
2755 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002756
2757 /* find the target proxy for 'use_backend' rules */
2758 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002759 struct proxy *target;
2760
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002761 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002762
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002763 if (!target) {
2764 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2765 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002766 cfgerr++;
2767 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002768 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2769 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002770 cfgerr++;
2771 } else {
2772 free((void *)rule->be.name);
2773 rule->be.backend = target;
2774 }
2775 }
2776
Willy Tarreau2738a142006-07-08 17:28:09 +02002777 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002778 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->timeout.client)) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02002779 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002780 (!tv_isset(&curproxy->timeout.connect) || !tv_isset(&curproxy->timeout.server))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002781 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002782 " | While not properly invalid, you will certainly encounter various problems\n"
2783 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01002784 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002785 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002786 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002787
Willy Tarreau1fa31262007-12-03 00:36:16 +01002788 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
2789 * We must still support older configurations, so let's find out whether those
2790 * parameters have been set or must be copied from contimeouts.
2791 */
2792 if (curproxy != &defproxy) {
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002793 if (!tv_isset(&curproxy->timeout.tarpit) ||
2794 __tv_iseq(&curproxy->timeout.tarpit, &defproxy.timeout.tarpit)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01002795 /* tarpit timeout not set. We search in the following order:
2796 * default.tarpit, curr.connect, default.connect.
2797 */
2798 if (tv_isset(&defproxy.timeout.tarpit))
2799 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002800 else if (tv_isset(&curproxy->timeout.connect))
2801 curproxy->timeout.tarpit = curproxy->timeout.connect;
2802 else if (tv_isset(&defproxy.timeout.connect))
2803 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002804 }
2805 if ((curproxy->cap & PR_CAP_BE) &&
2806 (!tv_isset(&curproxy->timeout.queue) ||
2807 __tv_iseq(&curproxy->timeout.queue, &defproxy.timeout.queue))) {
2808 /* queue timeout not set. We search in the following order:
2809 * default.queue, curr.connect, default.connect.
2810 */
2811 if (tv_isset(&defproxy.timeout.queue))
2812 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002813 else if (tv_isset(&curproxy->timeout.connect))
2814 curproxy->timeout.queue = curproxy->timeout.connect;
2815 else if (tv_isset(&defproxy.timeout.connect))
2816 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002817 }
2818 }
2819
Willy Tarreauf3c69202006-07-09 16:42:34 +02002820 if (curproxy->options & PR_O_SSL3_CHK) {
2821 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2822 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2823 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2824 }
2825
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002826 /* The small pools required for the capture lists */
2827 if (curproxy->nb_req_cap)
2828 curproxy->req_cap_pool = create_pool("ptrcap",
2829 curproxy->nb_req_cap * sizeof(char *),
2830 MEM_F_SHARED);
2831 if (curproxy->nb_rsp_cap)
2832 curproxy->rsp_cap_pool = create_pool("ptrcap",
2833 curproxy->nb_rsp_cap * sizeof(char *),
2834 MEM_F_SHARED);
2835
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002836 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2837 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2838 MEM_F_SHARED);
2839
Willy Tarreau86034312006-12-29 00:10:33 +01002840 /* for backwards compatibility with "listen" instances, if
2841 * fullconn is not set but maxconn is set, then maxconn
2842 * is used.
2843 */
2844 if (!curproxy->fullconn)
2845 curproxy->fullconn = curproxy->maxconn;
2846
Willy Tarreaubaaee002006-06-26 02:48:02 +02002847 /* first, we will invert the servers list order */
2848 newsrv = NULL;
2849 while (curproxy->srv) {
2850 struct server *next;
2851
2852 next = curproxy->srv->next;
2853 curproxy->srv->next = newsrv;
2854 newsrv = curproxy->srv;
2855 if (!next)
2856 break;
2857 curproxy->srv = next;
2858 }
2859
Willy Tarreau20697042007-11-15 23:26:18 +01002860 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01002861 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002862
Willy Tarreaub625a082007-11-26 01:15:43 +01002863 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01002864 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01002865 fwrr_init_server_groups(curproxy);
2866 else
2867 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002868
2869 if (curproxy->options & PR_O_LOGASAP)
2870 curproxy->to_log &= ~LW_BYTES;
2871
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 /*
2873 * If this server supports a maxconn parameter, it needs a dedicated
2874 * tasks to fill the emptied slots when a connection leaves.
2875 */
2876 newsrv = curproxy->srv;
2877 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002878 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879 /* Only 'minconn' was specified, or it was higher than or equal
2880 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2881 * this will avoid further useless expensive computations.
2882 */
2883 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002884 } else if (newsrv->maxconn && !newsrv->minconn) {
2885 /* minconn was not specified, so we set it to maxconn */
2886 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002887 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2888 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002889 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002890 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 }
2892
2893 if (newsrv->maxconn > 0) {
2894 struct task *t;
2895
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002896 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2898 return -1;
2899 }
2900
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002901 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002902 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002903 t->state = TASK_IDLE;
2904 t->process = process_srv_queue;
2905 t->context = newsrv;
2906 newsrv->queue_mgt = t;
2907
2908 /* never run it unless specifically woken up */
2909 tv_eternity(&t->expire);
2910 task_queue(t);
2911 }
2912 newsrv = newsrv->next;
2913 }
2914
Willy Tarreaue6b98942007-10-29 01:09:36 +01002915 /* adjust this proxy's listeners */
2916 listener = curproxy->listen;
2917 while (listener) {
2918 if (curproxy->options & PR_O_TCP_NOLING)
2919 listener->options |= LI_O_NOLINGER;
2920 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002921 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002922 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002923 listener->accept = event_accept;
2924 listener->private = curproxy;
2925
2926 listener = listener->next;
2927 }
2928
Willy Tarreaubaaee002006-06-26 02:48:02 +02002929 curproxy = curproxy->next;
2930 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002931
Willy Tarreaubaaee002006-06-26 02:48:02 +02002932 if (cfgerr > 0) {
2933 Alert("Errors found in configuration file, aborting.\n");
2934 return -1;
2935 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002936
2937 /*
2938 * Recount currently required checks.
2939 */
2940
2941 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
2942 int optnum;
2943
2944 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2945 if (!(curproxy->options & cfg_opts[optnum].val))
2946 continue;
2947
2948 global.last_checks |= cfg_opts[optnum].checks;
2949 }
2950 }
2951
2952 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002953}
2954
2955
2956
2957/*
2958 * Local variables:
2959 * c-indent-level: 8
2960 * c-basic-offset: 8
2961 * End:
2962 */