blob: f34d0e31170f5170246b5d2d34ff31563348256f [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau7c669d72008-06-20 15:04:11 +02004 * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
27#include <common/config.h>
28#include <common/memory.h>
29#include <common/standard.h>
30#include <common/time.h>
31#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020032
33#include <types/capture.h>
34#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreaueb0c6142007-05-07 00:53:22 +020036#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010038#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020040#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010041#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010043#include <proto/protocols.h>
44#include <proto/proto_tcp.h>
45#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010046#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010048#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <proto/task.h>
50
51
Willy Tarreauf3c69202006-07-09 16:42:34 +020052/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
53 * ssl-hello-chk option to ensure that the remote server speaks SSL.
54 *
55 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
56 */
57const char sslv3_client_hello_pkt[] = {
58 "\x16" /* ContentType : 0x16 = Hanshake */
59 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
60 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
61 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
62 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
63 "\x03\x00" /* Hello Version : 0x0300 = v3 */
64 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
65 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
66 "\x00" /* Session ID length : empty (no session ID) */
67 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
68 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
69 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
70 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
71 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
72 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
73 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
74 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
75 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
76 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
77 "\x00\x38" "\x00\x39" "\x00\x3A"
78 "\x01" /* Compression Length : 0x01 = 1 byte for types */
79 "\x00" /* Compression Type : 0x00 = NULL compression */
80};
81
Willy Tarreau13943ab2006-12-31 00:24:10 +010082/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010083struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010084 const char *name;
85 unsigned int val;
86 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010087 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +010088};
89
90/* proxy->options */
91static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +010092{
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
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100112 { "transparent", PR_O_TRANSP, PR_CAP_BE, 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 Tarreau66aa61f2009-01-18 21:44:07 +0100118/* proxy->options2 */
119static const struct cfg_opt cfg_opts2[] =
120{
121#ifdef CONFIG_HAP_LINUX_SPLICE
122 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
123 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
124 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
125#endif
126 { NULL, 0, 0, 0 }
127};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200128
Willy Tarreau6daf3432008-01-22 16:44:08 +0100129static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200130static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
131int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
132int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
133
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200134/* List head of all known configuration keywords */
135static struct cfg_kw_list cfg_keywords = {
136 .list = LIST_HEAD_INIT(cfg_keywords.list)
137};
138
Willy Tarreaubaaee002006-06-26 02:48:02 +0200139/*
140 * converts <str> to a list of listeners which are dynamically allocated.
141 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
142 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
143 * - <port> is a numerical port from 1 to 65535 ;
144 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
145 * This can be repeated as many times as necessary, separated by a coma.
146 * The <tail> argument is a pointer to a current list which should be appended
147 * to the tail of the new list. The pointer to the new list is returned.
148 */
149static struct listener *str2listener(char *str, struct listener *tail)
150{
151 struct listener *l;
152 char *c, *next, *range, *dupstr;
153 int port, end;
154
155 next = dupstr = strdup(str);
156
157 while (next && *next) {
158 struct sockaddr_storage ss;
159
160 str = next;
161 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100162 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200163 *next++ = 0;
164 }
165
166 /* 2) look for the addr/port delimiter, it's the last colon. */
167 if ((range = strrchr(str, ':')) == NULL) {
168 Alert("Missing port number: '%s'\n", str);
169 goto fail;
170 }
171
172 *range++ = 0;
173
174 if (strrchr(str, ':') != NULL) {
175 /* IPv6 address contains ':' */
176 memset(&ss, 0, sizeof(ss));
177 ss.ss_family = AF_INET6;
178
179 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
180 Alert("Invalid server address: '%s'\n", str);
181 goto fail;
182 }
183 }
184 else {
185 memset(&ss, 0, sizeof(ss));
186 ss.ss_family = AF_INET;
187
188 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
189 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
190 }
191 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
192 struct hostent *he;
193
194 if ((he = gethostbyname(str)) == NULL) {
195 Alert("Invalid server name: '%s'\n", str);
196 goto fail;
197 }
198 else
199 ((struct sockaddr_in *)&ss)->sin_addr =
200 *(struct in_addr *) *(he->h_addr_list);
201 }
202 }
203
204 /* 3) look for the port-end delimiter */
205 if ((c = strchr(range, '-')) != NULL) {
206 *c++ = 0;
207 end = atol(c);
208 }
209 else {
210 end = atol(range);
211 }
212
213 port = atol(range);
214
215 if (port < 1 || port > 65535) {
216 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
217 goto fail;
218 }
219
220 if (end < 1 || end > 65535) {
221 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
222 goto fail;
223 }
224
225 for (; port <= end; port++) {
226 l = (struct listener *)calloc(1, sizeof(struct listener));
227 l->next = tail;
228 tail = l;
229
230 l->fd = -1;
231 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100232 l->state = LI_INIT;
233
234 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100236 tcpv6_add_listener(l);
237 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100239 tcpv4_add_listener(l);
240 }
241 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242 } /* end for(port) */
243 } /* end while(next) */
244 free(dupstr);
245 return tail;
246 fail:
247 free(dupstr);
248 return NULL;
249}
250
Willy Tarreau977b8e42006-12-29 14:19:17 +0100251/*
252 * Sends a warning if proxy <proxy> does not have at least one of the
253 * capabilities in <cap>. An optionnal <hint> may be added at the end
254 * of the warning to help the user. Returns 1 if a warning was emitted
255 * or 0 if the condition is valid.
256 */
257int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
258{
259 char *msg;
260
261 switch (cap) {
262 case PR_CAP_BE: msg = "no backend"; break;
263 case PR_CAP_FE: msg = "no frontend"; break;
264 case PR_CAP_RS: msg = "no ruleset"; break;
265 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
266 default: msg = "not enough"; break;
267 }
268
269 if (!(proxy->cap & cap)) {
270 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100271 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100272 return 1;
273 }
274 return 0;
275}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200276
277/*
278 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
279 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100280int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281{
282
283 if (!strcmp(args[0], "global")) { /* new section */
284 /* no option, nothing special to do */
285 return 0;
286 }
287 else if (!strcmp(args[0], "daemon")) {
288 global.mode |= MODE_DAEMON;
289 }
290 else if (!strcmp(args[0], "debug")) {
291 global.mode |= MODE_DEBUG;
292 }
293 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100294 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200296 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100297 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200298 }
299 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100300 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100303 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100305 else if (!strcmp(args[0], "nosplice")) {
306 global.tune.options &= ~GTUNE_USE_SPLICE;
307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308 else if (!strcmp(args[0], "quiet")) {
309 global.mode |= MODE_QUIET;
310 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200311 else if (!strcmp(args[0], "tune.maxpollevents")) {
312 if (global.tune.maxpollevents != 0) {
313 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
314 return 0;
315 }
316 if (*(args[1]) == 0) {
317 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
318 return -1;
319 }
320 global.tune.maxpollevents = atol(args[1]);
321 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100322 else if (!strcmp(args[0], "tune.maxaccept")) {
323 if (global.tune.maxaccept != 0) {
324 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
325 return 0;
326 }
327 if (*(args[1]) == 0) {
328 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
329 return -1;
330 }
331 global.tune.maxaccept = atol(args[1]);
332 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200333 else if (!strcmp(args[0], "uid")) {
334 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200335 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200336 return 0;
337 }
338 if (*(args[1]) == 0) {
339 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
340 return -1;
341 }
342 global.uid = atol(args[1]);
343 }
344 else if (!strcmp(args[0], "gid")) {
345 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200346 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200347 return 0;
348 }
349 if (*(args[1]) == 0) {
350 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
351 return -1;
352 }
353 global.gid = atol(args[1]);
354 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200355 /* user/group name handling */
356 else if (!strcmp(args[0], "user")) {
357 struct passwd *ha_user;
358 if (global.uid != 0) {
359 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
360 return 0;
361 }
362 errno = 0;
363 ha_user = getpwnam(args[1]);
364 if (ha_user != NULL) {
365 global.uid = (int)ha_user->pw_uid;
366 }
367 else {
368 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
369 exit(1);
370 }
371 }
372 else if (!strcmp(args[0], "group")) {
373 struct group *ha_group;
374 if (global.gid != 0) {
375 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
376 return 0;
377 }
378 errno = 0;
379 ha_group = getgrnam(args[1]);
380 if (ha_group != NULL) {
381 global.gid = (int)ha_group->gr_gid;
382 }
383 else {
384 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
385 exit(1);
386 }
387 }
388 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200389 else if (!strcmp(args[0], "nbproc")) {
390 if (global.nbproc != 0) {
391 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
392 return 0;
393 }
394 if (*(args[1]) == 0) {
395 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
396 return -1;
397 }
398 global.nbproc = atol(args[1]);
399 }
400 else if (!strcmp(args[0], "maxconn")) {
401 if (global.maxconn != 0) {
402 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
403 return 0;
404 }
405 if (*(args[1]) == 0) {
406 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
407 return -1;
408 }
409 global.maxconn = atol(args[1]);
410#ifdef SYSTEM_MAXCONN
411 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
412 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);
413 global.maxconn = DEFAULT_MAXCONN;
414 }
415#endif /* SYSTEM_MAXCONN */
416 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100417 else if (!strcmp(args[0], "maxpipes")) {
418 if (global.maxpipes != 0) {
419 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
420 return 0;
421 }
422 if (*(args[1]) == 0) {
423 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
424 return -1;
425 }
426 global.maxpipes = atol(args[1]);
427 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200428 else if (!strcmp(args[0], "ulimit-n")) {
429 if (global.rlimit_nofile != 0) {
430 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
431 return 0;
432 }
433 if (*(args[1]) == 0) {
434 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
435 return -1;
436 }
437 global.rlimit_nofile = atol(args[1]);
438 }
439 else if (!strcmp(args[0], "chroot")) {
440 if (global.chroot != NULL) {
441 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
442 return 0;
443 }
444 if (*(args[1]) == 0) {
445 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
446 return -1;
447 }
448 global.chroot = strdup(args[1]);
449 }
450 else if (!strcmp(args[0], "pidfile")) {
451 if (global.pidfile != NULL) {
452 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
453 return 0;
454 }
455 if (*(args[1]) == 0) {
456 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
457 return -1;
458 }
459 global.pidfile = strdup(args[1]);
460 }
461 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100462 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463 int facility, level;
464
465 if (*(args[1]) == 0 || *(args[2]) == 0) {
466 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
467 return -1;
468 }
469
470 facility = get_log_facility(args[2]);
471 if (facility < 0) {
472 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
473 exit(1);
474 }
475
476 level = 7; /* max syslog level = debug */
477 if (*(args[3])) {
478 level = get_log_level(args[3]);
479 if (level < 0) {
480 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
481 exit(1);
482 }
483 }
484
Robert Tsai81ae1952007-12-05 10:47:29 +0100485 if (args[1][0] == '/') {
486 logsrv.u.addr.sa_family = AF_UNIX;
487 logsrv.u.un = *str2sun(args[1]);
488 } else {
489 logsrv.u.addr.sa_family = AF_INET;
490 logsrv.u.in = *str2sa(args[1]);
491 if (!logsrv.u.in.sin_port)
492 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
493 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200494
495 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100496 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200497 global.logfac1 = facility;
498 global.loglev1 = level;
499 }
500 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100501 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200502 global.logfac2 = facility;
503 global.loglev2 = level;
504 }
505 else {
506 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
507 return -1;
508 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200509 }
510 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
511 if (global.spread_checks != 0) {
512 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
513 return 0;
514 }
515 if (*(args[1]) == 0) {
516 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
517 return -1;
518 }
519 global.spread_checks = atol(args[1]);
520 if (global.spread_checks < 0 || global.spread_checks > 50) {
521 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
522 return -1;
523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200524 }
525 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200526 struct cfg_kw_list *kwl;
527 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200528 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200529
530 list_for_each_entry(kwl, &cfg_keywords.list, list) {
531 for (index = 0; kwl->kw[index].kw != NULL; index++) {
532 if (kwl->kw[index].section != CFG_GLOBAL)
533 continue;
534 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
535 /* prepare error message just in case */
536 snprintf(trash, sizeof(trash),
537 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200538 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
539 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200540 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
541 return -1;
542 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200543 else if (rc > 0) {
544 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
545 return 0;
546 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200547 return 0;
548 }
549 }
550 }
551
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
553 return -1;
554 }
555 return 0;
556}
557
558
559static void init_default_instance()
560{
561 memset(&defproxy, 0, sizeof(defproxy));
562 defproxy.mode = PR_MODE_TCP;
563 defproxy.state = PR_STNEW;
564 defproxy.maxconn = cfg_maxpconn;
565 defproxy.conn_retries = CONN_RETRIES;
566 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200567
568 LIST_INIT(&defproxy.pendconns);
569 LIST_INIT(&defproxy.acl);
570 LIST_INIT(&defproxy.block_cond);
571 LIST_INIT(&defproxy.mon_fail_cond);
572 LIST_INIT(&defproxy.switching_rules);
573
Willy Tarreau3a70f942008-02-15 11:15:34 +0100574 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575}
576
577/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100578 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
579 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100581int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582{
583 static struct proxy *curproxy = NULL;
584 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200585 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100586 int rc;
587 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200588
Willy Tarreau977b8e42006-12-29 14:19:17 +0100589 if (!strcmp(args[0], "listen"))
590 rc = PR_CAP_LISTEN;
591 else if (!strcmp(args[0], "frontend"))
592 rc = PR_CAP_FE | PR_CAP_RS;
593 else if (!strcmp(args[0], "backend"))
594 rc = PR_CAP_BE | PR_CAP_RS;
595 else if (!strcmp(args[0], "ruleset"))
596 rc = PR_CAP_RS;
597 else
598 rc = PR_CAP_NONE;
599
600 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 if (!*args[1]) {
602 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
603 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
604 file, linenum, args[0]);
605 return -1;
606 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200607
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100608 err = invalid_char(args[1]);
609 if (err) {
610 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
611 file, linenum, *err, args[0], args[1]);
612 return -1;
613 }
614
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200615 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
616 /*
617 * If there are two proxies with the same name only following
618 * combinations are allowed:
619 *
620 * listen backend frontend ruleset
621 * listen - - - -
622 * backend - - OK -
623 * frontend - OK - -
624 * ruleset - - - -
625 */
626
627 if (!strcmp(curproxy->id, args[1]) &&
628 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
629 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100630 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
631 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200632 }
633 }
634
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
636 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
637 return -1;
638 }
639
640 curproxy->next = proxy;
641 proxy = curproxy;
642 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200643 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200644 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200645 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100646 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200647 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200648 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200649
Willy Tarreauee991362007-05-14 14:37:50 +0200650 /* Timeouts are defined as -1, so we cannot use the zeroed area
651 * as a default value.
652 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100653 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200654
655 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100657 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658
659 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100660 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 curproxy->listen = str2listener(args[2], curproxy->listen);
662 if (!curproxy->listen)
663 return -1;
664 global.maxsock++;
665 }
666
667 /* set default values */
668 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100670 curproxy->options2 = defproxy.options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100671 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100672 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200673 curproxy->except_net = defproxy.except_net;
674 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200676 if (defproxy.fwdfor_hdr_len) {
677 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
678 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
679 }
680
Willy Tarreau977b8e42006-12-29 14:19:17 +0100681 if (curproxy->cap & PR_CAP_FE) {
682 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100683 curproxy->backlog = defproxy.backlog;
Willy Tarreau39af0f62009-03-07 11:53:44 +0100684 curproxy->fe_maxsps = defproxy.fe_maxsps;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100685
686 /* initialize error relocations */
687 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
688 if (defproxy.errmsg[rc].str)
689 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
690 }
691
692 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200694
Willy Tarreau977b8e42006-12-29 14:19:17 +0100695 if (curproxy->cap & PR_CAP_BE) {
696 curproxy->fullconn = defproxy.fullconn;
697 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698
Willy Tarreau977b8e42006-12-29 14:19:17 +0100699 if (defproxy.check_req)
700 curproxy->check_req = strdup(defproxy.check_req);
701 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200702
Willy Tarreau977b8e42006-12-29 14:19:17 +0100703 if (defproxy.cookie_name)
704 curproxy->cookie_name = strdup(defproxy.cookie_name);
705 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100706
707 if (defproxy.url_param_name)
708 curproxy->url_param_name = strdup(defproxy.url_param_name);
709 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100710
711 if (defproxy.iface_name)
712 curproxy->iface_name = strdup(defproxy.iface_name);
713 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100714 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200715
Willy Tarreau977b8e42006-12-29 14:19:17 +0100716 if (curproxy->cap & PR_CAP_RS) {
717 if (defproxy.capture_name)
718 curproxy->capture_name = strdup(defproxy.capture_name);
719 curproxy->capture_namelen = defproxy.capture_namelen;
720 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200722
Willy Tarreau977b8e42006-12-29 14:19:17 +0100723 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100724 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100725 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100726 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100727 curproxy->uri_auth = defproxy.uri_auth;
728 curproxy->mon_net = defproxy.mon_net;
729 curproxy->mon_mask = defproxy.mon_mask;
730 if (defproxy.monitor_uri)
731 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
732 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100733 if (defproxy.defbe.name)
734 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100735 }
736
737 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100738 curproxy->timeout.connect = defproxy.timeout.connect;
739 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100740 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100741 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100742 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100743 curproxy->source_addr = defproxy.source_addr;
744 }
745
Willy Tarreaubaaee002006-06-26 02:48:02 +0200746 curproxy->mode = defproxy.mode;
747 curproxy->logfac1 = defproxy.logfac1;
748 curproxy->logsrv1 = defproxy.logsrv1;
749 curproxy->loglev1 = defproxy.loglev1;
750 curproxy->logfac2 = defproxy.logfac2;
751 curproxy->logsrv2 = defproxy.logsrv2;
752 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200753 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100754 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
755 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200756
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 return 0;
758 }
759 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
760 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100761 /* FIXME-20070101: we should do this too at the end of the
762 * config parsing to free all default values.
763 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200764 free(defproxy.check_req);
765 free(defproxy.cookie_name);
766 free(defproxy.url_param_name);
767 free(defproxy.capture_name);
768 free(defproxy.monitor_uri);
769 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100770 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200771 free(defproxy.fwdfor_hdr_name);
772 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100773
Willy Tarreaua534fea2008-08-03 12:19:50 +0200774 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
775 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100776
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 /* we cannot free uri_auth because it might already be used */
778 init_default_instance();
779 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100780 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 return 0;
782 }
783 else if (curproxy == NULL) {
784 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
785 return -1;
786 }
787
Willy Tarreau977b8e42006-12-29 14:19:17 +0100788
789 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200790 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100791 struct listener *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100792 int cur_arg;
793
Willy Tarreaubaaee002006-06-26 02:48:02 +0200794 if (curproxy == &defproxy) {
795 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
796 return -1;
797 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100798 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
799 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200800
801 if (strchr(args[1], ':') == NULL) {
802 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
803 file, linenum, args[0]);
804 return -1;
805 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100806
807 last_listen = curproxy->listen;
808 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 if (!curproxy->listen)
810 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100811
812 cur_arg = 2;
813 while (*(args[cur_arg])) {
814 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
815#ifdef SO_BINDTODEVICE
816 struct listener *l;
817
818 if (!*args[cur_arg + 1]) {
819 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
820 file, linenum, args[0]);
821 return -1;
822 }
823
824 for (l = curproxy->listen; l != last_listen; l = l->next)
825 l->interface = strdup(args[cur_arg + 1]);
826
827 global.last_checks |= LSTCHK_NETADM;
828
829 cur_arg += 2;
830 continue;
831#else
832 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
833 file, linenum, args[0], args[cur_arg]);
834 return -1;
835#endif
836 }
837 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100838#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100839 struct listener *l;
840
841 for (l = curproxy->listen; l != last_listen; l = l->next)
842 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100843
844 cur_arg ++;
845 continue;
846#else
847 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
848 file, linenum, args[0], args[cur_arg]);
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100849 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100850#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100851 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100852 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100853 file, linenum, args[0]);
854 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100855 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200856 global.maxsock++;
857 return 0;
858 }
859 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
860 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
861 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
862 file, linenum, args[0]);
863 return -1;
864 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100865 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
866 return 0;
867
Willy Tarreaubaaee002006-06-26 02:48:02 +0200868 /* flush useless bits */
869 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
870 return 0;
871 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200872 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100873 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
874 return 0;
875
Willy Tarreau1c47f852006-07-09 08:22:27 +0200876 if (!*args[1]) {
877 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
878 file, linenum, args[0]);
879 return -1;
880 }
881
Willy Tarreaua534fea2008-08-03 12:19:50 +0200882 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100883 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200884 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100885 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200886 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
887
888 return 0;
889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200890 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
891 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
892 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
893 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
894 else {
895 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
896 return -1;
897 }
898 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100899 else if (!strcmp(args[0], "id")) {
900 struct proxy *target;
901
902 if (curproxy == &defproxy) {
903 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
904 file, linenum, args[0]);
905 return -1;
906 }
907
908 if (!*args[1]) {
909 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
910 file, linenum, args[0]);
911 return -1;
912 }
913
914 curproxy->uuid = atol(args[1]);
915
916 if (curproxy->uuid < 1001) {
917 Alert("parsing [%s:%d]: custom id has to be > 1000",
918 file, linenum);
919 return -1;
920 }
921
922 for (target = proxy; target; target = target->next)
923 if (curproxy != target && curproxy->uuid == target->uuid) {
924 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
925 file, linenum, curproxy->id, target->id);
926 return -1;
927 }
928 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
930 curproxy->state = PR_STSTOPPED;
931 }
932 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
933 curproxy->state = PR_STNEW;
934 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100935 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
936 int cur_arg = 1;
937 unsigned int set = 0;
938
939 while (*args[cur_arg]) {
940 int u;
941 if (strcmp(args[cur_arg], "all") == 0) {
942 set = 0;
943 break;
944 }
945 else if (strcmp(args[cur_arg], "odd") == 0) {
946 set |= 0x55555555;
947 }
948 else if (strcmp(args[cur_arg], "even") == 0) {
949 set |= 0xAAAAAAAA;
950 }
951 else {
952 u = str2uic(args[cur_arg]);
953 if (u < 1 || u > 32) {
954 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
955 file, linenum, args[0]);
956 return -1;
957 }
958 if (u > global.nbproc) {
959 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
960 file, linenum, args[0]);
961 }
962 set |= 1 << (u - 1);
963 }
964 cur_arg++;
965 }
966 curproxy->bind_proc = set;
967 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200968 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200969 if (curproxy == &defproxy) {
970 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
971 return -1;
972 }
973
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100974 err = invalid_char(args[1]);
975 if (err) {
976 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
977 file, linenum, *err, args[1]);
978 return -1;
979 }
980
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200981 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
982 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
983 file, linenum, args[1]);
984 return -1;
985 }
986 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200987 else if (!strcmp(args[0], "cookie")) { /* cookie name */
988 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200989
Willy Tarreau977b8e42006-12-29 14:19:17 +0100990 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
991 return 0;
992
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 if (*(args[1]) == 0) {
994 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
995 file, linenum, args[0]);
996 return -1;
997 }
Willy Tarreaua534fea2008-08-03 12:19:50 +0200998
999 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001000 curproxy->cookie_name = strdup(args[1]);
1001 curproxy->cookie_len = strlen(curproxy->cookie_name);
1002
1003 cur_arg = 2;
1004 while (*(args[cur_arg])) {
1005 if (!strcmp(args[cur_arg], "rewrite")) {
1006 curproxy->options |= PR_O_COOK_RW;
1007 }
1008 else if (!strcmp(args[cur_arg], "indirect")) {
1009 curproxy->options |= PR_O_COOK_IND;
1010 }
1011 else if (!strcmp(args[cur_arg], "insert")) {
1012 curproxy->options |= PR_O_COOK_INS;
1013 }
1014 else if (!strcmp(args[cur_arg], "nocache")) {
1015 curproxy->options |= PR_O_COOK_NOC;
1016 }
1017 else if (!strcmp(args[cur_arg], "postonly")) {
1018 curproxy->options |= PR_O_COOK_POST;
1019 }
1020 else if (!strcmp(args[cur_arg], "prefix")) {
1021 curproxy->options |= PR_O_COOK_PFX;
1022 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001023 else if (!strcmp(args[cur_arg], "domain")) {
1024 if (!*args[cur_arg + 1]) {
1025 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1026 file, linenum, args[cur_arg]);
1027 return -1;
1028 }
1029
1030 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1031 /* rfc2109, 4.3.2 Rejecting Cookies */
1032 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1033 " dots or does not start with a dot.\n",
1034 file, linenum, args[cur_arg + 1]);
1035 return -1;
1036 }
1037
1038 err = invalid_domainchar(args[cur_arg + 1]);
1039 if (err) {
1040 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1041 file, linenum, *err, args[cur_arg + 1]);
1042 return -1;
1043 }
1044
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001045 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001046 cur_arg++;
1047 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001049 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 file, linenum, args[0]);
1051 return -1;
1052 }
1053 cur_arg++;
1054 }
1055 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1056 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1057 file, linenum);
1058 return -1;
1059 }
1060
1061 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1062 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1063 file, linenum);
1064 return -1;
1065 }
1066 }/* end else if (!strcmp(args[0], "cookie")) */
1067 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068
Willy Tarreau977b8e42006-12-29 14:19:17 +01001069 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1070 return 0;
1071
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 if (*(args[5]) == 0) {
1073 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1074 file, linenum, args[0]);
1075 return -1;
1076 }
1077 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001078 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079 curproxy->appsession_name = strdup(args[1]);
1080 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1081 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001082 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1083 if (err) {
1084 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1085 file, linenum, *err, args[0]);
1086 return -1;
1087 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001088 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001089
Willy Tarreau51041c72007-09-09 21:56:53 +02001090 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1091 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 return -1;
1093 }
1094 } /* Url App Session */
1095 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001096 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1097 return 0;
1098
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001100 if (*(args[4]) == 0) {
1101 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1102 file, linenum, args[0]);
1103 return -1;
1104 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001105 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 curproxy->capture_name = strdup(args[2]);
1107 curproxy->capture_namelen = strlen(curproxy->capture_name);
1108 curproxy->capture_len = atol(args[4]);
1109 if (curproxy->capture_len >= CAPTURE_LEN) {
1110 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1111 file, linenum, CAPTURE_LEN - 1);
1112 curproxy->capture_len = CAPTURE_LEN - 1;
1113 }
1114 curproxy->to_log |= LW_COOKIE;
1115 }
1116 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1117 struct cap_hdr *hdr;
1118
1119 if (curproxy == &defproxy) {
1120 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1121 return -1;
1122 }
1123
1124 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1125 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1126 file, linenum, args[0], args[1]);
1127 return -1;
1128 }
1129
1130 hdr = calloc(sizeof(struct cap_hdr), 1);
1131 hdr->next = curproxy->req_cap;
1132 hdr->name = strdup(args[3]);
1133 hdr->namelen = strlen(args[3]);
1134 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001135 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001136 hdr->index = curproxy->nb_req_cap++;
1137 curproxy->req_cap = hdr;
1138 curproxy->to_log |= LW_REQHDR;
1139 }
1140 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1141 struct cap_hdr *hdr;
1142
1143 if (curproxy == &defproxy) {
1144 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1145 return -1;
1146 }
1147
1148 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1149 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1150 file, linenum, args[0], args[1]);
1151 return -1;
1152 }
1153 hdr = calloc(sizeof(struct cap_hdr), 1);
1154 hdr->next = curproxy->rsp_cap;
1155 hdr->name = strdup(args[3]);
1156 hdr->namelen = strlen(args[3]);
1157 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001158 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159 hdr->index = curproxy->nb_rsp_cap++;
1160 curproxy->rsp_cap = hdr;
1161 curproxy->to_log |= LW_RSPHDR;
1162 }
1163 else {
1164 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1165 file, linenum, args[0]);
1166 return -1;
1167 }
1168 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001170 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1171 return 0;
1172
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 if (*(args[1]) == 0) {
1174 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1175 file, linenum, args[0]);
1176 return -1;
1177 }
1178 curproxy->conn_retries = atol(args[1]);
1179 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001180 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1181 int pol = ACL_COND_NONE;
1182 struct acl_cond *cond;
1183
Willy Tarreaub099aca2008-10-12 17:26:37 +02001184 if (curproxy == &defproxy) {
1185 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1186 return -1;
1187 }
1188
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001189 if (!strcmp(args[1], "if"))
1190 pol = ACL_COND_IF;
1191 else if (!strcmp(args[1], "unless"))
1192 pol = ACL_COND_UNLESS;
1193
1194 if (pol == ACL_COND_NONE) {
1195 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1196 file, linenum, args[0]);
1197 return -1;
1198 }
1199
1200 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1201 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1202 file, linenum);
1203 return -1;
1204 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001205 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001206 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1207 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001208 else if (!strcmp(args[0], "redirect")) {
1209 int pol = ACL_COND_NONE;
1210 struct acl_cond *cond;
1211 struct redirect_rule *rule;
1212 int cur_arg;
1213 int type = REDIRECT_TYPE_NONE;
1214 int code = 302;
1215 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001216 char *cookie = NULL;
1217 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001218 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001219
1220 cur_arg = 1;
1221 while (*(args[cur_arg])) {
1222 if (!strcmp(args[cur_arg], "location")) {
1223 if (!*args[cur_arg + 1]) {
1224 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1225 file, linenum, args[0], args[cur_arg]);
1226 return -1;
1227 }
1228
1229 type = REDIRECT_TYPE_LOCATION;
1230 cur_arg++;
1231 destination = args[cur_arg];
1232 }
1233 else if (!strcmp(args[cur_arg], "prefix")) {
1234 if (!*args[cur_arg + 1]) {
1235 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1236 file, linenum, args[0], args[cur_arg]);
1237 return -1;
1238 }
1239
1240 type = REDIRECT_TYPE_PREFIX;
1241 cur_arg++;
1242 destination = args[cur_arg];
1243 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001244 else if (!strcmp(args[cur_arg], "set-cookie")) {
1245 if (!*args[cur_arg + 1]) {
1246 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1247 file, linenum, args[0], args[cur_arg]);
1248 return -1;
1249 }
1250
1251 cur_arg++;
1252 cookie = args[cur_arg];
1253 cookie_set = 1;
1254 }
1255 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1256 if (!*args[cur_arg + 1]) {
1257 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1258 file, linenum, args[0], args[cur_arg]);
1259 return -1;
1260 }
1261
1262 cur_arg++;
1263 cookie = args[cur_arg];
1264 cookie_set = 0;
1265 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001266 else if (!strcmp(args[cur_arg],"code")) {
1267 if (!*args[cur_arg + 1]) {
1268 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1269 file, linenum, args[0]);
1270 return -1;
1271 }
1272 cur_arg++;
1273 code = atol(args[cur_arg]);
1274 if (code < 301 || code > 303) {
1275 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1276 file, linenum, args[0], code);
1277 return -1;
1278 }
1279 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001280 else if (!strcmp(args[cur_arg],"drop-query")) {
1281 flags |= REDIRECT_FLAG_DROP_QS;
1282 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001283 else if (!strcmp(args[cur_arg], "if")) {
1284 pol = ACL_COND_IF;
1285 cur_arg++;
1286 break;
1287 }
1288 else if (!strcmp(args[cur_arg], "unless")) {
1289 pol = ACL_COND_UNLESS;
1290 cur_arg++;
1291 break;
1292 }
1293 else {
1294 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1295 file, linenum, args[0], args[cur_arg]);
1296 return -1;
1297 }
1298 cur_arg++;
1299 }
1300
1301 if (type == REDIRECT_TYPE_NONE) {
1302 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1303 file, linenum, args[0]);
1304 return -1;
1305 }
1306
1307 if (pol == ACL_COND_NONE) {
1308 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1309 file, linenum, args[0]);
1310 return -1;
1311 }
1312
1313 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1314 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1315 file, linenum, args[0]);
1316 return -1;
1317 }
1318
Willy Tarreaua9802632008-07-25 19:13:19 +02001319 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001320 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1321 rule->cond = cond;
1322 rule->rdr_str = strdup(destination);
1323 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001324 if (cookie) {
1325 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1326 * a clear consists in appending "; Max-Age=0" at the end.
1327 */
1328 rule->cookie_len = strlen(cookie);
1329 if (cookie_set)
1330 rule->cookie_str = strdup(cookie);
1331 else {
1332 rule->cookie_str = malloc(rule->cookie_len + 12);
1333 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1334 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1335 rule->cookie_len += 11;
1336 }
1337 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001338 rule->type = type;
1339 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001340 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001341 LIST_INIT(&rule->list);
1342 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1343 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001344 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001345 int pol = ACL_COND_NONE;
1346 struct acl_cond *cond;
1347 struct switching_rule *rule;
1348
Willy Tarreaub099aca2008-10-12 17:26:37 +02001349 if (curproxy == &defproxy) {
1350 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1351 return -1;
1352 }
1353
Willy Tarreau55ea7572007-06-17 19:56:27 +02001354 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1355 return 0;
1356
1357 if (*(args[1]) == 0) {
1358 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1359 return -1;
1360 }
1361
1362 if (!strcmp(args[2], "if"))
1363 pol = ACL_COND_IF;
1364 else if (!strcmp(args[2], "unless"))
1365 pol = ACL_COND_UNLESS;
1366
1367 if (pol == ACL_COND_NONE) {
1368 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1369 file, linenum, args[0]);
1370 return -1;
1371 }
1372
1373 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001374 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001375 file, linenum);
1376 return -1;
1377 }
1378
Willy Tarreaua9802632008-07-25 19:13:19 +02001379 cond->line = linenum;
1380 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001381 struct acl *acl;
1382 const char *name;
1383
1384 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1385 name = acl ? acl->name : "(unknown)";
1386 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1387 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001388 }
1389
Willy Tarreau55ea7572007-06-17 19:56:27 +02001390 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1391 rule->cond = cond;
1392 rule->be.name = strdup(args[1]);
1393 LIST_INIT(&rule->list);
1394 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1395 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001396 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001397 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1398 return 0;
1399
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1401 curproxy->uri_auth = NULL; /* we must detach from the default config */
1402
1403 if (*(args[1]) == 0) {
1404 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1405 return -1;
1406 } else if (!strcmp(args[1], "uri")) {
1407 if (*(args[2]) == 0) {
1408 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1409 return -1;
1410 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1411 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1412 return -1;
1413 }
1414 } else if (!strcmp(args[1], "realm")) {
1415 if (*(args[2]) == 0) {
1416 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1417 return -1;
1418 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1419 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1420 return -1;
1421 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001422 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001423 unsigned interval;
1424
1425 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1426 if (err) {
1427 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1428 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001429 return -1;
1430 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1431 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1432 return -1;
1433 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001434 } else if (!strcmp(args[1], "auth")) {
1435 if (*(args[2]) == 0) {
1436 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1437 return -1;
1438 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1439 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1440 return -1;
1441 }
1442 } else if (!strcmp(args[1], "scope")) {
1443 if (*(args[2]) == 0) {
1444 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1445 return -1;
1446 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1447 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1448 return -1;
1449 }
1450 } else if (!strcmp(args[1], "enable")) {
1451 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1452 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1453 return -1;
1454 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001455 } else if (!strcmp(args[1], "hide-version")) {
1456 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1457 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1458 return -1;
1459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001460 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001461 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462 file, linenum, args[0]);
1463 return -1;
1464 }
1465 }
1466 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001467 int optnum;
1468
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001469 if (*(args[1]) == '\0') {
1470 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1471 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472 return -1;
1473 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001474
1475 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1476 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1477 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1478 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001479
1480 if (!inv)
1481 curproxy->options |= cfg_opts[optnum].val;
1482 else
1483 curproxy->options &= ~cfg_opts[optnum].val;
1484
Willy Tarreau13943ab2006-12-31 00:24:10 +01001485 return 0;
1486 }
1487 }
1488
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001489 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1490 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
1491 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
1492 return 0;
1493
1494 if (!inv)
1495 curproxy->options2 |= cfg_opts2[optnum].val;
1496 else
1497 curproxy->options2 &= ~cfg_opts2[optnum].val;
1498
1499 return 0;
1500 }
1501 }
1502
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001503 if (inv) {
1504 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1505 file, linenum, args[1]);
1506 return -1;
1507 }
1508
Willy Tarreau13943ab2006-12-31 00:24:10 +01001509 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001510 /* generate a complete HTTP log */
1511 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1512 else if (!strcmp(args[1], "tcplog"))
1513 /* generate a detailed TCP log */
1514 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515 else if (!strcmp(args[1], "tcpka")) {
1516 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001517 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1518 return 0;
1519
1520 if (curproxy->cap & PR_CAP_FE)
1521 curproxy->options |= PR_O_TCP_CLI_KA;
1522 if (curproxy->cap & PR_CAP_BE)
1523 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001524 }
1525 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001526 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1527 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001528 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001529 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001530 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001531 curproxy->options &= ~PR_O_SMTP_CHK;
1532 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001533 if (!*args[2]) { /* no argument */
1534 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1535 curproxy->check_len = strlen(DEF_CHECK_REQ);
1536 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001537 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001538 curproxy->check_req = (char *)malloc(reqlen);
1539 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1540 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1541 } else { /* more arguments : METHOD URI [HTTP_VER] */
1542 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1543 if (*args[4])
1544 reqlen += strlen(args[4]);
1545 else
1546 reqlen += strlen("HTTP/1.0");
1547
1548 curproxy->check_req = (char *)malloc(reqlen);
1549 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1550 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1551 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001552 }
1553 else if (!strcmp(args[1], "ssl-hello-chk")) {
1554 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001555 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1556 return 0;
1557
Willy Tarreaua534fea2008-08-03 12:19:50 +02001558 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001559 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001560 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001561 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562 }
Willy Tarreau23677902007-05-08 23:50:35 +02001563 else if (!strcmp(args[1], "smtpchk")) {
1564 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001565 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001566 curproxy->options &= ~PR_O_HTTP_CHK;
1567 curproxy->options &= ~PR_O_SSL3_CHK;
1568 curproxy->options |= PR_O_SMTP_CHK;
1569
1570 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1571 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1572 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1573 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1574 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1575 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1576 curproxy->check_req = (char *)malloc(reqlen);
1577 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1578 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1579 } else {
1580 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1581 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1582 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1583 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1584 }
1585 }
1586 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001587 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001588 int cur_arg;
1589
1590 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1591 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001592 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001593
1594 curproxy->options |= PR_O_FWDFOR;
1595
1596 free(curproxy->fwdfor_hdr_name);
1597 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1598 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1599
1600 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1601 cur_arg = 2;
1602 while (*(args[cur_arg])) {
1603 if (!strcmp(args[cur_arg], "except")) {
1604 /* suboption except - needs additional argument for it */
1605 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1606 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1607 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001608 return -1;
1609 }
1610 /* flush useless bits */
1611 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001612 cur_arg += 2;
1613 } else if (!strcmp(args[cur_arg], "header")) {
1614 /* suboption header - needs additional argument for it */
1615 if (*(args[cur_arg+1]) == 0) {
1616 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1617 file, linenum, args[0], args[1], args[cur_arg]);
1618 return -1;
1619 }
1620 free(curproxy->fwdfor_hdr_name);
1621 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1622 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1623 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001624 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001625 /* unknown suboption - catchall */
1626 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1627 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001628 return -1;
1629 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001630 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001632 else {
1633 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1634 return -1;
1635 }
1636 return 0;
1637 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001638 else if (!strcmp(args[0], "default_backend")) {
1639 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1640 return 0;
1641
1642 if (*(args[1]) == 0) {
1643 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1644 return -1;
1645 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001646 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001647 curproxy->defbe.name = strdup(args[1]);
1648 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001650 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1651 return 0;
1652
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001653 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1654 file, linenum, args[0]);
1655
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 /* enable reconnections to dispatch */
1657 curproxy->options |= PR_O_REDISP;
1658 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001659 else if (!strcmp(args[0], "http-check")) {
1660 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1661 return 0;
1662
1663 if (strcmp(args[1], "disable-on-404") == 0) {
1664 /* enable a graceful server shutdown on an HTTP 404 response */
1665 curproxy->options |= PR_O_DISABLE404;
1666 }
1667 else {
1668 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1669 return -1;
1670 }
1671 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001672 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001673 if (curproxy == &defproxy) {
1674 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1675 return -1;
1676 }
1677
Willy Tarreaub80c2302007-11-30 20:51:32 +01001678 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1679 return 0;
1680
1681 if (strcmp(args[1], "fail") == 0) {
1682 /* add a condition to fail monitor requests */
1683 int pol = ACL_COND_NONE;
1684 struct acl_cond *cond;
1685
1686 if (!strcmp(args[2], "if"))
1687 pol = ACL_COND_IF;
1688 else if (!strcmp(args[2], "unless"))
1689 pol = ACL_COND_UNLESS;
1690
1691 if (pol == ACL_COND_NONE) {
1692 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1693 file, linenum, args[0], args[1]);
1694 return -1;
1695 }
1696
1697 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1698 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1699 file, linenum, args[0], args[1]);
1700 return -1;
1701 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001702 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001703 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1704 }
1705 else {
1706 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1707 return -1;
1708 }
1709 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710#ifdef TPROXY
1711 else if (!strcmp(args[0], "transparent")) {
1712 /* enable transparent proxy connections */
1713 curproxy->options |= PR_O_TRANSP;
1714 }
1715#endif
1716 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001717 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1718 return 0;
1719
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 if (*(args[1]) == 0) {
1721 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1722 return -1;
1723 }
1724 curproxy->maxconn = atol(args[1]);
1725 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001726 else if (!strcmp(args[0], "backlog")) { /* backlog */
1727 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1728 return 0;
1729
1730 if (*(args[1]) == 0) {
1731 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1732 return -1;
1733 }
1734 curproxy->backlog = atol(args[1]);
1735 }
Willy Tarreau86034312006-12-29 00:10:33 +01001736 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001737 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1738 return 0;
1739
Willy Tarreau86034312006-12-29 00:10:33 +01001740 if (*(args[1]) == 0) {
1741 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1742 return -1;
1743 }
1744 curproxy->fullconn = atol(args[1]);
1745 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1747 if (*(args[1]) == 0) {
1748 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1749 return -1;
1750 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001751 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1752 if (err) {
1753 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1754 file, linenum, *err);
1755 return -1;
1756 }
1757 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001758 }
1759 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1760 if (curproxy == &defproxy) {
1761 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1762 return -1;
1763 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001764 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1765 return 0;
1766
Willy Tarreaubaaee002006-06-26 02:48:02 +02001767 if (strchr(args[1], ':') == NULL) {
1768 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1769 return -1;
1770 }
1771 curproxy->dispatch_addr = *str2sa(args[1]);
1772 }
1773 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001774 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1775 return 0;
1776
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02001777 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001778 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1779 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1780 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001782 }
1783 else if (!strcmp(args[0], "server")) { /* server address */
1784 int cur_arg;
1785 char *rport;
1786 char *raddr;
1787 short realport;
1788 int do_check;
1789
1790 if (curproxy == &defproxy) {
1791 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1792 return -1;
1793 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001794 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1795 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001796
1797 if (!*args[2]) {
1798 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1799 file, linenum, args[0]);
1800 return -1;
1801 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001802
1803 err = invalid_char(args[1]);
1804 if (err) {
1805 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1806 file, linenum, *err, args[1]);
1807 return -1;
1808 }
1809
Willy Tarreaubaaee002006-06-26 02:48:02 +02001810 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1811 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1812 return -1;
1813 }
1814
1815 /* the servers are linked backwards first */
1816 newsrv->next = curproxy->srv;
1817 curproxy->srv = newsrv;
1818 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001819 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001820
1821 LIST_INIT(&newsrv->pendconns);
1822 do_check = 0;
1823 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001824 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001825 newsrv->id = strdup(args[1]);
1826
1827 /* several ways to check the port component :
1828 * - IP => port=+0, relative
1829 * - IP: => port=+0, relative
1830 * - IP:N => port=N, absolute
1831 * - IP:+N => port=+N, relative
1832 * - IP:-N => port=-N, relative
1833 */
1834 raddr = strdup(args[2]);
1835 rport = strchr(raddr, ':');
1836 if (rport) {
1837 *rport++ = 0;
1838 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001839 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001840 newsrv->state |= SRV_MAPPORTS;
1841 } else {
1842 realport = 0;
1843 newsrv->state |= SRV_MAPPORTS;
1844 }
1845
1846 newsrv->addr = *str2sa(raddr);
1847 newsrv->addr.sin_port = htons(realport);
1848 free(raddr);
1849
1850 newsrv->curfd = -1; /* no health-check in progress */
1851 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001852 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1853 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001854 newsrv->rise = DEF_RISETIME;
1855 newsrv->fall = DEF_FALLTIME;
1856 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001857 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001858 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001859 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001860
Willy Tarreaubaaee002006-06-26 02:48:02 +02001861 cur_arg = 3;
1862 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001863 if (!strcmp(args[cur_arg], "id")) {
1864 struct server *target;
1865
1866 if (!*args[cur_arg + 1]) {
1867 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1868 file, linenum, args[cur_arg]);
1869 return -1;
1870 }
1871
1872 newsrv->puid = atol(args[cur_arg + 1]);
1873
1874 if (newsrv->puid< 1001) {
1875 Alert("parsing [%s:%d]: custom id has to be > 1000",
1876 file, linenum);
1877 return -1;
1878 }
1879
1880 for (target = proxy->srv; target; target = target->next)
1881 if (newsrv != target && newsrv->puid == target->puid) {
1882 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1883 file, linenum, newsrv->id, target->id);
1884 return -1;
1885 }
1886 cur_arg += 2;
1887 }
1888 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889 newsrv->cookie = strdup(args[cur_arg + 1]);
1890 newsrv->cklen = strlen(args[cur_arg + 1]);
1891 cur_arg += 2;
1892 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001893 else if (!strcmp(args[cur_arg], "redir")) {
1894 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1895 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1896 cur_arg += 2;
1897 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001898 else if (!strcmp(args[cur_arg], "rise")) {
1899 newsrv->rise = atol(args[cur_arg + 1]);
1900 newsrv->health = newsrv->rise;
1901 cur_arg += 2;
1902 }
1903 else if (!strcmp(args[cur_arg], "fall")) {
1904 newsrv->fall = atol(args[cur_arg + 1]);
1905 cur_arg += 2;
1906 }
1907 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001908 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1909 if (err) {
1910 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1911 file, linenum, *err, newsrv->id);
1912 return -1;
1913 }
1914 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 cur_arg += 2;
1916 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001917 else if (!strcmp(args[cur_arg], "fastinter")) {
1918 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1919 if (err) {
1920 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1921 file, linenum, *err, newsrv->id);
1922 return -1;
1923 }
1924 newsrv->fastinter = val;
1925 cur_arg += 2;
1926 }
1927 else if (!strcmp(args[cur_arg], "downinter")) {
1928 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1929 if (err) {
1930 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1931 file, linenum, *err, newsrv->id);
1932 return -1;
1933 }
1934 newsrv->downinter = val;
1935 cur_arg += 2;
1936 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001937 else if (!strcmp(args[cur_arg], "addr")) {
1938 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001939 cur_arg += 2;
1940 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001941 else if (!strcmp(args[cur_arg], "port")) {
1942 newsrv->check_port = atol(args[cur_arg + 1]);
1943 cur_arg += 2;
1944 }
1945 else if (!strcmp(args[cur_arg], "backup")) {
1946 newsrv->state |= SRV_BACKUP;
1947 cur_arg ++;
1948 }
1949 else if (!strcmp(args[cur_arg], "weight")) {
1950 int w;
1951 w = atol(args[cur_arg + 1]);
1952 if (w < 1 || w > 256) {
1953 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1954 file, linenum, newsrv->id, w);
1955 return -1;
1956 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001957 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001958 cur_arg += 2;
1959 }
1960 else if (!strcmp(args[cur_arg], "minconn")) {
1961 newsrv->minconn = atol(args[cur_arg + 1]);
1962 cur_arg += 2;
1963 }
1964 else if (!strcmp(args[cur_arg], "maxconn")) {
1965 newsrv->maxconn = atol(args[cur_arg + 1]);
1966 cur_arg += 2;
1967 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001968 else if (!strcmp(args[cur_arg], "maxqueue")) {
1969 newsrv->maxqueue = atol(args[cur_arg + 1]);
1970 cur_arg += 2;
1971 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001972 else if (!strcmp(args[cur_arg], "slowstart")) {
1973 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001974 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001975 if (err) {
1976 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1977 file, linenum, *err, newsrv->id);
1978 return -1;
1979 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001980 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001981 cur_arg += 2;
1982 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001983 else if (!strcmp(args[cur_arg], "track")) {
1984
1985 if (!*args[cur_arg + 1]) {
1986 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1987 file, linenum);
1988 return -1;
1989 }
1990
1991 newsrv->trackit = strdup(args[cur_arg + 1]);
1992
1993 cur_arg += 2;
1994 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001995 else if (!strcmp(args[cur_arg], "check")) {
1996 global.maxsock++;
1997 do_check = 1;
1998 cur_arg += 1;
1999 }
2000 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
2001 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002002#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002003 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2004 file, linenum, "source", "usesrc");
2005#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002006 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2007 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002008#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002009 return -1;
2010 }
2011 newsrv->state |= SRV_BIND_SRC;
2012 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
2013 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002014 while (*(args[cur_arg])) {
2015 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002016#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2017#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002018 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2019 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2020 file, linenum, "usesrc", "source");
2021 return -1;
2022 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002023#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002024 if (!*args[cur_arg + 1]) {
2025 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2026 file, linenum, "usesrc");
2027 return -1;
2028 }
2029 if (!strcmp(args[cur_arg + 1], "client")) {
2030 newsrv->state |= SRV_TPROXY_CLI;
2031 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2032 newsrv->state |= SRV_TPROXY_CIP;
2033 } else {
2034 newsrv->state |= SRV_TPROXY_ADDR;
2035 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2036 }
2037 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002038#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002039 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002040#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002041 cur_arg += 2;
2042 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002043#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002044 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002045 file, linenum, "usesrc");
2046 return -1;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002047#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2048 } /* "usesrc" */
2049
2050 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2051#ifdef SO_BINDTODEVICE
2052 if (!*args[cur_arg + 1]) {
2053 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2054 file, linenum, args[0]);
2055 return -1;
2056 }
2057 if (newsrv->iface_name)
2058 free(newsrv->iface_name);
2059
2060 newsrv->iface_name = strdup(args[cur_arg + 1]);
2061 newsrv->iface_len = strlen(newsrv->iface_name);
2062 global.last_checks |= LSTCHK_NETADM;
2063#else
2064 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2065 file, linenum, args[0], args[cur_arg]);
2066 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002067#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002068 cur_arg += 2;
2069 continue;
2070 }
2071 /* this keyword in not an option of "source" */
2072 break;
2073 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002075 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2076 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2077 file, linenum, "usesrc", "source");
2078 return -1;
2079 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002080 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002081 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'check', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002082 file, linenum, newsrv->id);
2083 return -1;
2084 }
2085 }
2086
2087 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002088 if (newsrv->trackit) {
2089 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2090 file, linenum);
2091 return -1;
2092 }
2093
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002094 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2095 newsrv->check_port = newsrv->check_addr.sin_port;
2096
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2098 newsrv->check_port = realport; /* by default */
2099 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002100 /* not yet valid, because no port was set on
2101 * the server either. We'll check if we have
2102 * a known port on the first listener.
2103 */
2104 struct listener *l;
2105 l = curproxy->listen;
2106 if (l) {
2107 int port;
2108 port = (l->addr.ss_family == AF_INET6)
2109 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2110 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2111 newsrv->check_port = port;
2112 }
2113 }
2114 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002115 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2116 file, linenum, newsrv->id);
2117 return -1;
2118 }
2119 newsrv->state |= SRV_CHECKED;
2120 }
2121
2122 if (newsrv->state & SRV_BACKUP)
2123 curproxy->srv_bck++;
2124 else
2125 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002126
2127 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002128 }
2129 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002130 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002131 int facility;
2132
2133 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2134 curproxy->logfac1 = global.logfac1;
2135 curproxy->logsrv1 = global.logsrv1;
2136 curproxy->loglev1 = global.loglev1;
2137 curproxy->logfac2 = global.logfac2;
2138 curproxy->logsrv2 = global.logsrv2;
2139 curproxy->loglev2 = global.loglev2;
2140 }
2141 else if (*(args[1]) && *(args[2])) {
2142 int level;
2143
2144 facility = get_log_facility(args[2]);
2145 if (facility < 0) {
2146 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2147 exit(1);
2148 }
2149
2150 level = 7; /* max syslog level = debug */
2151 if (*(args[3])) {
2152 level = get_log_level(args[3]);
2153 if (level < 0) {
2154 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2155 exit(1);
2156 }
2157 }
2158
Robert Tsai81ae1952007-12-05 10:47:29 +01002159 if (args[1][0] == '/') {
2160 logsrv.u.addr.sa_family = AF_UNIX;
2161 logsrv.u.un = *str2sun(args[1]);
2162 } else {
2163 logsrv.u.addr.sa_family = AF_INET;
2164 logsrv.u.in = *str2sa(args[1]);
2165 if (!logsrv.u.in.sin_port) {
2166 logsrv.u.in.sin_port =
2167 htons(SYSLOG_PORT);
2168 }
2169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002170
2171 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002172 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002173 curproxy->logfac1 = facility;
2174 curproxy->loglev1 = level;
2175 }
2176 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002177 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002178 curproxy->logfac2 = facility;
2179 curproxy->loglev2 = level;
2180 }
2181 else {
2182 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2183 return -1;
2184 }
2185 }
2186 else {
2187 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2188 file, linenum);
2189 return -1;
2190 }
2191 }
2192 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002193 int cur_arg;
2194
Willy Tarreau977b8e42006-12-29 14:19:17 +01002195 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2196 return 0;
2197
Willy Tarreaubaaee002006-06-26 02:48:02 +02002198 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002199 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2200 file, linenum, "source", "usesrc", "interface");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002201 return -1;
2202 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002203
2204 /* we must first clear any optional default setting */
2205 curproxy->options &= ~PR_O_TPXY_MASK;
2206 free(curproxy->iface_name);
2207 curproxy->iface_name = NULL;
2208 curproxy->iface_len = 0;
2209
Willy Tarreaubaaee002006-06-26 02:48:02 +02002210 curproxy->source_addr = *str2sa(args[1]);
2211 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002212
2213 cur_arg = 2;
2214 while (*(args[cur_arg])) {
2215 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002216#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2217#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002218 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2219 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2220 file, linenum, "usesrc");
2221 return -1;
2222 }
2223#endif
2224 if (!*args[cur_arg + 1]) {
2225 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2226 file, linenum, "usesrc");
2227 return -1;
2228 }
2229
2230 if (!strcmp(args[cur_arg + 1], "client")) {
2231 curproxy->options |= PR_O_TPXY_CLI;
2232 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2233 curproxy->options |= PR_O_TPXY_CIP;
2234 } else {
2235 curproxy->options |= PR_O_TPXY_ADDR;
2236 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2237 }
2238 global.last_checks |= LSTCHK_NETADM;
2239#if !defined(CONFIG_HAP_LINUX_TPROXY)
2240 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002241#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002242#else /* no TPROXY support */
2243 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002244 file, linenum, "usesrc");
2245 return -1;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002246#endif
2247 cur_arg += 2;
2248 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002249 }
2250
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002251 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2252#ifdef SO_BINDTODEVICE
2253 if (!*args[cur_arg + 1]) {
2254 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2255 file, linenum, args[0]);
2256 return -1;
2257 }
2258 if (curproxy->iface_name)
2259 free(curproxy->iface_name);
2260
2261 curproxy->iface_name = strdup(args[cur_arg + 1]);
2262 curproxy->iface_len = strlen(curproxy->iface_name);
2263 global.last_checks |= LSTCHK_NETADM;
2264#else
2265 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2266 file, linenum, args[0], args[cur_arg]);
2267 return -1;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002268#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002269 cur_arg += 2;
2270 continue;
2271 }
2272 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2273 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002274 return -1;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002277 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2278 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2279 file, linenum, "usesrc", "source");
2280 return -1;
2281 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2283 regex_t *preg;
2284 if (curproxy == &defproxy) {
2285 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2286 return -1;
2287 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002288 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2289 return 0;
2290
Willy Tarreaubaaee002006-06-26 02:48:02 +02002291 if (*(args[1]) == 0 || *(args[2]) == 0) {
2292 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2293 file, linenum, args[0]);
2294 return -1;
2295 }
2296
2297 preg = calloc(1, sizeof(regex_t));
2298 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2299 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2300 return -1;
2301 }
2302
2303 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2304 if (err) {
2305 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2306 file, linenum, *err);
2307 return -1;
2308 }
2309 }
2310 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2311 regex_t *preg;
2312 if (curproxy == &defproxy) {
2313 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2314 return -1;
2315 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002316 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2317 return 0;
2318
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 if (*(args[1]) == 0) {
2320 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2321 return -1;
2322 }
2323
2324 preg = calloc(1, sizeof(regex_t));
2325 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2326 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2327 return -1;
2328 }
2329
2330 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2331 }
2332 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2333 regex_t *preg;
2334 if (curproxy == &defproxy) {
2335 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2336 return -1;
2337 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002338 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2339 return 0;
2340
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 if (*(args[1]) == 0) {
2342 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2343 return -1;
2344 }
2345
2346 preg = calloc(1, sizeof(regex_t));
2347 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2348 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2349 return -1;
2350 }
2351
2352 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2353 }
2354 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2355 regex_t *preg;
2356 if (curproxy == &defproxy) {
2357 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2358 return -1;
2359 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002360 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2361 return 0;
2362
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 if (*(args[1]) == 0) {
2364 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2365 return -1;
2366 }
2367
2368 preg = calloc(1, sizeof(regex_t));
2369 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2370 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2371 return -1;
2372 }
2373
2374 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2375 }
2376 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2377 regex_t *preg;
2378 if (curproxy == &defproxy) {
2379 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2380 return -1;
2381 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002382 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2383 return 0;
2384
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385 if (*(args[1]) == 0) {
2386 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2387 return -1;
2388 }
2389
2390 preg = calloc(1, sizeof(regex_t));
2391 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2392 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2393 return -1;
2394 }
2395
2396 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2397 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002398 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2399 regex_t *preg;
2400 if (curproxy == &defproxy) {
2401 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2402 return -1;
2403 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002404 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2405 return 0;
2406
Willy Tarreaub8750a82006-09-03 09:56:00 +02002407 if (*(args[1]) == 0) {
2408 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2409 return -1;
2410 }
2411
2412 preg = calloc(1, sizeof(regex_t));
2413 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2414 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2415 return -1;
2416 }
2417
2418 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2419 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002420 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2421 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002422 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002423 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2424 return -1;
2425 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002426 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2427 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002428
Willy Tarreau977b8e42006-12-29 14:19:17 +01002429 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002430 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2431 file, linenum, args[0]);
2432 return -1;
2433 }
2434
2435 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002436 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002437 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2438 }
2439
2440 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2441 }
2442 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2443 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002444 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002445 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2446 return -1;
2447 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002448 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2449 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002450
Willy Tarreau977b8e42006-12-29 14:19:17 +01002451 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002452 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2453 file, linenum, args[0]);
2454 return -1;
2455 }
2456
2457 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002458 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002459 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2460 }
2461
2462 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2463 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002464 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2465 regex_t *preg;
2466 if (curproxy == &defproxy) {
2467 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2468 return -1;
2469 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002470 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2471 return 0;
2472
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 if (*(args[1]) == 0 || *(args[2]) == 0) {
2474 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2475 file, linenum, args[0]);
2476 return -1;
2477 }
2478
2479 preg = calloc(1, sizeof(regex_t));
2480 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2481 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2482 return -1;
2483 }
2484
2485 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2486 if (err) {
2487 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2488 file, linenum, *err);
2489 return -1;
2490 }
2491 }
2492 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2493 regex_t *preg;
2494 if (curproxy == &defproxy) {
2495 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2496 return -1;
2497 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002498 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2499 return 0;
2500
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 if (*(args[1]) == 0) {
2502 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2503 return -1;
2504 }
2505
2506 preg = calloc(1, sizeof(regex_t));
2507 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2508 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2509 return -1;
2510 }
2511
2512 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2513 }
2514 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2515 regex_t *preg;
2516 if (curproxy == &defproxy) {
2517 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2518 return -1;
2519 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002520 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2521 return 0;
2522
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 if (*(args[1]) == 0) {
2524 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2525 return -1;
2526 }
2527
2528 preg = calloc(1, sizeof(regex_t));
2529 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2530 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2531 return -1;
2532 }
2533
2534 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2535 }
2536 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2537 regex_t *preg;
2538 if (curproxy == &defproxy) {
2539 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2540 return -1;
2541 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002542 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2543 return 0;
2544
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 if (*(args[1]) == 0) {
2546 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2547 return -1;
2548 }
2549
2550 preg = calloc(1, sizeof(regex_t));
2551 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2552 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2553 return -1;
2554 }
2555
2556 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2557 }
2558 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2559 regex_t *preg;
2560 if (curproxy == &defproxy) {
2561 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2562 return -1;
2563 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002564 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2565 return 0;
2566
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 if (*(args[1]) == 0) {
2568 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2569 return -1;
2570 }
2571
2572 preg = calloc(1, sizeof(regex_t));
2573 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2574 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2575 return -1;
2576 }
2577
2578 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2579 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002580 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2581 regex_t *preg;
2582 if (curproxy == &defproxy) {
2583 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2584 return -1;
2585 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002586 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2587 return 0;
2588
Willy Tarreaub8750a82006-09-03 09:56:00 +02002589 if (*(args[1]) == 0) {
2590 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2591 return -1;
2592 }
2593
2594 preg = calloc(1, sizeof(regex_t));
2595 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2596 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2597 return -1;
2598 }
2599
2600 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2601 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2603 if (curproxy == &defproxy) {
2604 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2605 return -1;
2606 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002607 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2608 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609
2610 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2611 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2612 return 0;
2613 }
2614
2615 if (*(args[1]) == 0) {
2616 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2617 return -1;
2618 }
2619
2620 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2621 }
2622 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2623 regex_t *preg;
2624
2625 if (*(args[1]) == 0 || *(args[2]) == 0) {
2626 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2627 file, linenum, args[0]);
2628 return -1;
2629 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002630 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2631 return 0;
2632
Willy Tarreaubaaee002006-06-26 02:48:02 +02002633 preg = calloc(1, sizeof(regex_t));
2634 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2635 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2636 return -1;
2637 }
2638
2639 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2640 if (err) {
2641 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2642 file, linenum, *err);
2643 return -1;
2644 }
2645 }
2646 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2647 regex_t *preg;
2648 if (curproxy == &defproxy) {
2649 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2650 return -1;
2651 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002652 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2653 return 0;
2654
Willy Tarreaubaaee002006-06-26 02:48:02 +02002655 if (*(args[1]) == 0) {
2656 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2657 return -1;
2658 }
2659
2660 preg = calloc(1, sizeof(regex_t));
2661 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2662 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2663 return -1;
2664 }
2665
2666 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2667 if (err) {
2668 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2669 file, linenum, *err);
2670 return -1;
2671 }
2672 }
2673 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2674 regex_t *preg;
2675 if (curproxy == &defproxy) {
2676 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2677 return -1;
2678 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002679 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2680 return 0;
2681
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682 if (*(args[1]) == 0) {
2683 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2684 return -1;
2685 }
2686
2687 preg = calloc(1, sizeof(regex_t));
2688 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2689 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2690 return -1;
2691 }
2692
2693 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2694 if (err) {
2695 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2696 file, linenum, *err);
2697 return -1;
2698 }
2699 }
2700 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2701 regex_t *preg;
2702 if (curproxy == &defproxy) {
2703 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2704 return -1;
2705 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002706 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2707 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002708
2709 if (*(args[1]) == 0 || *(args[2]) == 0) {
2710 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2711 file, linenum, args[0]);
2712 return -1;
2713 }
2714
2715 preg = calloc(1, sizeof(regex_t));
2716 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2717 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2718 return -1;
2719 }
2720
2721 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2722 if (err) {
2723 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2724 file, linenum, *err);
2725 return -1;
2726 }
2727 }
2728 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2729 regex_t *preg;
2730 if (curproxy == &defproxy) {
2731 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2732 return -1;
2733 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002734 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2735 return 0;
2736
Willy Tarreaubaaee002006-06-26 02:48:02 +02002737 if (*(args[1]) == 0) {
2738 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2739 return -1;
2740 }
2741
2742 preg = calloc(1, sizeof(regex_t));
2743 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2744 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2745 return -1;
2746 }
2747
2748 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2749 if (err) {
2750 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2751 file, linenum, *err);
2752 return -1;
2753 }
2754 }
2755 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2756 regex_t *preg;
2757 if (curproxy == &defproxy) {
2758 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2759 return -1;
2760 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002761 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2762 return 0;
2763
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764 if (*(args[1]) == 0) {
2765 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2766 return -1;
2767 }
2768
2769 preg = calloc(1, sizeof(regex_t));
2770 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2771 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2772 return -1;
2773 }
2774
2775 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2776 if (err) {
2777 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2778 file, linenum, *err);
2779 return -1;
2780 }
2781 }
2782 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2783 if (curproxy == &defproxy) {
2784 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2785 return -1;
2786 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002787 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2788 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789
2790 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2791 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2792 return 0;
2793 }
2794
2795 if (*(args[1]) == 0) {
2796 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2797 return -1;
2798 }
2799
2800 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2801 }
2802 else if (!strcmp(args[0], "errorloc") ||
2803 !strcmp(args[0], "errorloc302") ||
2804 !strcmp(args[0], "errorloc303")) { /* error location */
2805 int errnum, errlen;
2806 char *err;
2807
Willy Tarreau977b8e42006-12-29 14:19:17 +01002808 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2809 return 0;
2810
Willy Tarreaubaaee002006-06-26 02:48:02 +02002811 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002812 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002813 return -1;
2814 }
2815
2816 errnum = atol(args[1]);
2817 if (!strcmp(args[0], "errorloc303")) {
2818 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2819 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2820 } else {
2821 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2822 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2823 }
2824
Willy Tarreau0f772532006-12-23 20:51:41 +01002825 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2826 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002827 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002828 curproxy->errmsg[rc].str = err;
2829 curproxy->errmsg[rc].len = errlen;
2830 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002831 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002833
2834 if (rc >= HTTP_ERR_SIZE) {
2835 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2836 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 free(err);
2838 }
2839 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002840 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2841 int errnum, errlen, fd;
2842 char *err;
2843 struct stat stat;
2844
2845 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2846 return 0;
2847
2848 if (*(args[2]) == 0) {
2849 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2850 return -1;
2851 }
2852
2853 fd = open(args[2], O_RDONLY);
2854 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2855 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2856 file, linenum, args[2], args[1]);
2857 if (fd >= 0)
2858 close(fd);
2859 return -1;
2860 }
2861
2862 if (stat.st_size <= BUFSIZE) {
2863 errlen = stat.st_size;
2864 } else {
2865 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2866 file, linenum, args[2], BUFSIZE);
2867 errlen = BUFSIZE;
2868 }
2869
2870 err = malloc(errlen); /* malloc() must succeed during parsing */
2871 errnum = read(fd, err, errlen);
2872 if (errnum != errlen) {
2873 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2874 file, linenum, args[2], args[1]);
2875 close(fd);
2876 free(err);
2877 return -1;
2878 }
2879 close(fd);
2880
2881 errnum = atol(args[1]);
2882 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2883 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002884 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002885 curproxy->errmsg[rc].str = err;
2886 curproxy->errmsg[rc].len = errlen;
2887 break;
2888 }
2889 }
2890
2891 if (rc >= HTTP_ERR_SIZE) {
2892 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2893 file, linenum, errnum);
2894 free(err);
2895 }
2896 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002898 struct cfg_kw_list *kwl;
2899 int index;
2900
2901 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2902 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2903 if (kwl->kw[index].section != CFG_LISTEN)
2904 continue;
2905 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2906 /* prepare error message just in case */
2907 snprintf(trash, sizeof(trash),
2908 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002909 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2910 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002911 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2912 return -1;
2913 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002914 else if (rc > 0) {
2915 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2916 return 0;
2917 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002918 return 0;
2919 }
2920 }
2921 }
2922
Willy Tarreau6daf3432008-01-22 16:44:08 +01002923 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002924 return -1;
2925 }
2926 return 0;
2927}
2928
2929
2930/*
2931 * This function reads and parses the configuration file given in the argument.
2932 * returns 0 if OK, -1 if error.
2933 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002934int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002935{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002936 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002937 FILE *f;
2938 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002939 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940 int confsect = CFG_NONE;
2941
2942 struct proxy *curproxy = NULL;
2943 struct server *newsrv = NULL;
2944
2945 if ((f=fopen(file,"r")) == NULL)
2946 return -1;
2947
2948 init_default_instance();
2949
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002950 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002951 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002952 char *end;
2953 char *args[MAX_LINE_ARGS + 1];
2954 char *line = thisline;
2955
Willy Tarreaubaaee002006-06-26 02:48:02 +02002956 linenum++;
2957
2958 end = line + strlen(line);
2959
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002960 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2961 /* Check if we reached the limit and the last char is not \n.
2962 * Watch out for the last line without the terminating '\n'!
2963 */
2964 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2965 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002966 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002967 }
2968
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002970 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 line++;
2972
2973 arg = 0;
2974 args[arg] = line;
2975
2976 while (*line && arg < MAX_LINE_ARGS) {
2977 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2978 * C equivalent value. Other combinations left unchanged (eg: \1).
2979 */
2980 if (*line == '\\') {
2981 int skip = 0;
2982 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2983 *line = line[1];
2984 skip = 1;
2985 }
2986 else if (line[1] == 'r') {
2987 *line = '\r';
2988 skip = 1;
2989 }
2990 else if (line[1] == 'n') {
2991 *line = '\n';
2992 skip = 1;
2993 }
2994 else if (line[1] == 't') {
2995 *line = '\t';
2996 skip = 1;
2997 }
2998 else if (line[1] == 'x') {
2999 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3000 unsigned char hex1, hex2;
3001 hex1 = toupper(line[2]) - '0';
3002 hex2 = toupper(line[3]) - '0';
3003 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3004 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3005 *line = (hex1<<4) + hex2;
3006 skip = 3;
3007 }
3008 else {
3009 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003010 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003011 }
3012 }
3013 if (skip) {
3014 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3015 end -= skip;
3016 }
3017 line++;
3018 }
3019 else if (*line == '#' || *line == '\n' || *line == '\r') {
3020 /* end of string, end of loop */
3021 *line = 0;
3022 break;
3023 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003024 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003025 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003026 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003027 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003028 line++;
3029 args[++arg] = line;
3030 }
3031 else {
3032 line++;
3033 }
3034 }
3035
3036 /* empty line */
3037 if (!**args)
3038 continue;
3039
Willy Tarreau540abe42007-05-02 20:50:16 +02003040 /* zero out remaining args and ensure that at least one entry
3041 * is zeroed out.
3042 */
3043 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003044 args[arg] = line;
3045 }
3046
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003047 if (!strcmp(args[0], "no")) {
3048 inv = 1;
3049 for (arg=0; *args[arg+1]; arg++)
3050 args[arg] = args[arg+1]; // shift args after inversion
3051 }
3052
3053 if (inv && strcmp(args[0], "option")) {
3054 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003055 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003056 }
3057
Willy Tarreau977b8e42006-12-29 14:19:17 +01003058 if (!strcmp(args[0], "listen") ||
3059 !strcmp(args[0], "frontend") ||
3060 !strcmp(args[0], "backend") ||
3061 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003062 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003064 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003065 cursection = strdup(args[0]);
3066 }
3067 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003068 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003069 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003070 cursection = strdup(args[0]);
3071 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003072 /* else it's a section keyword */
3073
3074 switch (confsect) {
3075 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003076 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003077 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078 break;
3079 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003080 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003081 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 break;
3083 default:
3084 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003085 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003087 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003088 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003089 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090 fclose(f);
3091
3092 /*
3093 * Now, check for the integrity of all that we have collected.
3094 */
3095
3096 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003097 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098
3099 if ((curproxy = proxy) == NULL) {
3100 Alert("parsing %s : no <listen> line. Nothing to do !\n",
3101 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003102 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 }
3104
3105 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003106 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003107 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003108
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003110 /* ensure we don't keep listeners uselessly bound */
3111 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 curproxy = curproxy->next;
3113 continue;
3114 }
3115
Willy Tarreau977b8e42006-12-29 14:19:17 +01003116 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
3117 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 +01003118 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003119 cfgerr++;
3120 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003121 else if (curproxy->cap & PR_CAP_BE &&
3122 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01003123 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01003124 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01003125 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
3126 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 +01003127 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003128 cfgerr++;
3129 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003130
Willy Tarreau31682232007-11-29 15:38:04 +01003131 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003133 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003134 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 cfgerr++;
3136 }
3137#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
3138 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003139 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003140 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141 cfgerr++;
3142 }
3143#endif
3144 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003145 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003146 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 }
3148 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003149
3150 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003152 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003153 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003156 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003157 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 }
3159 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003160 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003161 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003163 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003164 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003165 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003166 }
Willy Tarreaudf366142007-11-30 16:23:20 +01003167 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01003168 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3169 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003170
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01003171 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003172 file, proxy_type_str(curproxy), curproxy->id);
3173 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003174 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003175
3176 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
3177 if ((newsrv = curproxy->srv) != NULL) {
3178 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
3179 file, proxy_type_str(curproxy), curproxy->id);
3180 }
3181 }
3182
3183 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
3185 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
3186 file, curproxy->id);
3187 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003188 }
3189 }
3190
Willy Tarreau82936582007-11-30 15:20:09 +01003191 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3192 curproxy->options &= ~PR_O_DISABLE404;
3193 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3194 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
3195 }
3196
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003197 /* if a default backend was specified, let's find it */
3198 if (curproxy->defbe.name) {
3199 struct proxy *target;
3200
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003201 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3202 if (!target) {
3203 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3204 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003205 cfgerr++;
3206 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003207 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3208 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003209 } else {
3210 free(curproxy->defbe.name);
3211 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003212 /* we force the backend to be present on at least all of
3213 * the frontend's processes.
3214 */
3215 target->bind_proc = curproxy->bind_proc ?
3216 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 }
3218 }
3219
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003220 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003221 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3222 /* map jump target for ACT_SETBE in req_rep chain */
3223 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003224 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003225 struct proxy *target;
3226
Willy Tarreaua496b602006-12-17 23:15:24 +01003227 if (exp->action != ACT_SETBE)
3228 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003229
3230 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3231 if (!target) {
3232 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3233 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003234 cfgerr++;
3235 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003236 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3237 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003238 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003239 } else {
3240 free((void *)exp->replace);
3241 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003242 /* we force the backend to be present on at least all of
3243 * the frontend's processes.
3244 */
3245 target->bind_proc = curproxy->bind_proc ?
3246 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01003247 }
3248 }
3249 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003250
3251 /* find the target proxy for 'use_backend' rules */
3252 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003253 struct proxy *target;
3254
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003255 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003256
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003257 if (!target) {
3258 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3259 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003260 cfgerr++;
3261 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003262 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3263 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003264 cfgerr++;
3265 } else {
3266 free((void *)rule->be.name);
3267 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003268 /* we force the backend to be present on at least all of
3269 * the frontend's processes.
3270 */
3271 target->bind_proc = curproxy->bind_proc ?
3272 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003273 }
3274 }
3275
Willy Tarreau2738a142006-07-08 17:28:09 +02003276 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003277 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003278 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003279 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003280 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003281 " | While not properly invalid, you will certainly encounter various problems\n"
3282 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003283 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003284 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003285 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003286
Willy Tarreau1fa31262007-12-03 00:36:16 +01003287 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3288 * We must still support older configurations, so let's find out whether those
3289 * parameters have been set or must be copied from contimeouts.
3290 */
3291 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003292 if (!curproxy->timeout.tarpit ||
3293 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003294 /* tarpit timeout not set. We search in the following order:
3295 * default.tarpit, curr.connect, default.connect.
3296 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003297 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003298 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003299 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003300 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003301 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003302 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003303 }
3304 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003305 (!curproxy->timeout.queue ||
3306 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003307 /* queue timeout not set. We search in the following order:
3308 * default.queue, curr.connect, default.connect.
3309 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003310 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003311 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003312 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003313 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003314 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003315 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003316 }
3317 }
3318
Willy Tarreauf3c69202006-07-09 16:42:34 +02003319 if (curproxy->options & PR_O_SSL3_CHK) {
3320 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3321 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3322 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3323 }
3324
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003325 /* The small pools required for the capture lists */
3326 if (curproxy->nb_req_cap)
3327 curproxy->req_cap_pool = create_pool("ptrcap",
3328 curproxy->nb_req_cap * sizeof(char *),
3329 MEM_F_SHARED);
3330 if (curproxy->nb_rsp_cap)
3331 curproxy->rsp_cap_pool = create_pool("ptrcap",
3332 curproxy->nb_rsp_cap * sizeof(char *),
3333 MEM_F_SHARED);
3334
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003335 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3336 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3337 MEM_F_SHARED);
3338
Willy Tarreau86034312006-12-29 00:10:33 +01003339 /* for backwards compatibility with "listen" instances, if
3340 * fullconn is not set but maxconn is set, then maxconn
3341 * is used.
3342 */
3343 if (!curproxy->fullconn)
3344 curproxy->fullconn = curproxy->maxconn;
3345
Willy Tarreaubaaee002006-06-26 02:48:02 +02003346 /* first, we will invert the servers list order */
3347 newsrv = NULL;
3348 while (curproxy->srv) {
3349 struct server *next;
3350
3351 next = curproxy->srv->next;
3352 curproxy->srv->next = newsrv;
3353 newsrv = curproxy->srv;
3354 if (!next)
3355 break;
3356 curproxy->srv = next;
3357 }
3358
Willy Tarreau20697042007-11-15 23:26:18 +01003359 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003360 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003361
Willy Tarreaub625a082007-11-26 01:15:43 +01003362 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003363 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003364 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003365 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3366 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003367 else
3368 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369
3370 if (curproxy->options & PR_O_LOGASAP)
3371 curproxy->to_log &= ~LW_BYTES;
3372
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003374 * ensure that we're not cross-dressing a TCP server into HTTP.
3375 */
3376 newsrv = curproxy->srv;
3377 while (newsrv != NULL) {
3378 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3379 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3380 file, proxy_type_str(curproxy), curproxy->id, linenum);
3381 goto err;
3382 }
3383 newsrv = newsrv->next;
3384 }
3385
3386 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 * If this server supports a maxconn parameter, it needs a dedicated
3388 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003389 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 */
3391 newsrv = curproxy->srv;
3392 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003393 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 /* Only 'minconn' was specified, or it was higher than or equal
3395 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3396 * this will avoid further useless expensive computations.
3397 */
3398 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003399 } else if (newsrv->maxconn && !newsrv->minconn) {
3400 /* minconn was not specified, so we set it to maxconn */
3401 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003402 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3403 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003404 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003405 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406 }
3407
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003408 if (newsrv->trackit) {
3409 struct proxy *px;
3410 struct server *srv;
3411 char *pname, *sname;
3412
3413 pname = newsrv->trackit;
3414 sname = strrchr(pname, '/');
3415
3416 if (sname)
3417 *sname++ = '\0';
3418 else {
3419 sname = pname;
3420 pname = NULL;
3421 }
3422
3423 if (pname) {
3424 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3425 if (!px) {
3426 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3427 file, proxy_type_str(curproxy), curproxy->id,
3428 newsrv->id, pname);
3429 return -1;
3430 }
3431 } else
3432 px = curproxy;
3433
3434 srv = findserver(px, sname);
3435 if (!srv) {
3436 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3437 file, proxy_type_str(curproxy), curproxy->id,
3438 newsrv->id, sname);
3439 return -1;
3440 }
3441
3442 if (!(srv->state & SRV_CHECKED)) {
3443 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3444 "tracing as it does not have checks enabled.\n",
3445 file, proxy_type_str(curproxy), curproxy->id,
3446 newsrv->id, px->id, srv->id);
3447 return -1;
3448 }
3449
3450 if (curproxy != px &&
3451 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3452 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3453 "tracing: disable-on-404 option inconsistency.\n",
3454 file, proxy_type_str(curproxy), curproxy->id,
3455 newsrv->id, px->id, srv->id);
3456 return -1;
3457 }
3458
3459 newsrv->tracked = srv;
3460 newsrv->tracknext = srv->tracknext;
3461 srv->tracknext = newsrv;
3462
3463 free(newsrv->trackit);
3464 }
3465
Willy Tarreaubaaee002006-06-26 02:48:02 +02003466 newsrv = newsrv->next;
3467 }
3468
Willy Tarreaue6b98942007-10-29 01:09:36 +01003469 /* adjust this proxy's listeners */
3470 listener = curproxy->listen;
3471 while (listener) {
3472 if (curproxy->options & PR_O_TCP_NOLING)
3473 listener->options |= LI_O_NOLINGER;
3474 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003475 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003476 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003477 listener->accept = event_accept;
3478 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003479 listener->handler = process_session;
3480
3481 if (curproxy->mode == PR_MODE_HTTP)
3482 listener->analysers |= AN_REQ_HTTP_HDR;
3483
3484 if (curproxy->tcp_req.inspect_delay)
3485 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003486
3487 listener = listener->next;
3488 }
3489
Willy Tarreaubaaee002006-06-26 02:48:02 +02003490 curproxy = curproxy->next;
3491 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003492
Willy Tarreaubaaee002006-06-26 02:48:02 +02003493 if (cfgerr > 0) {
3494 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003495 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003496 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003497
3498 /*
3499 * Recount currently required checks.
3500 */
3501
3502 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3503 int optnum;
3504
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003505 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3506 if (curproxy->options & cfg_opts[optnum].val)
3507 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003508
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003509 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3510 if (curproxy->options2 & cfg_opts2[optnum].val)
3511 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003512 }
3513
Willy Tarreaua534fea2008-08-03 12:19:50 +02003514 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003515 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003516 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003517
3518 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003519 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003520 cursection = NULL;
3521 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003522}
3523
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003524/*
3525 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3526 * parsing sessions.
3527 */
3528void cfg_register_keywords(struct cfg_kw_list *kwl)
3529{
3530 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3531}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003533/*
3534 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3535 */
3536void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3537{
3538 LIST_DEL(&kwl->list);
3539 LIST_INIT(&kwl->list);
3540}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003541
3542/*
3543 * Local variables:
3544 * c-indent-level: 8
3545 * c-basic-offset: 8
3546 * End:
3547 */