blob: 5f1f0bb53ba8a2085c793d80f9a73fbd4fb5ba8f [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 Tarreau977b8e42006-12-29 14:19:17 +0100684
685 /* initialize error relocations */
686 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
687 if (defproxy.errmsg[rc].str)
688 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
689 }
690
691 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
692 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693
Willy Tarreau977b8e42006-12-29 14:19:17 +0100694 if (curproxy->cap & PR_CAP_BE) {
695 curproxy->fullconn = defproxy.fullconn;
696 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200697
Willy Tarreau977b8e42006-12-29 14:19:17 +0100698 if (defproxy.check_req)
699 curproxy->check_req = strdup(defproxy.check_req);
700 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701
Willy Tarreau977b8e42006-12-29 14:19:17 +0100702 if (defproxy.cookie_name)
703 curproxy->cookie_name = strdup(defproxy.cookie_name);
704 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100705
706 if (defproxy.url_param_name)
707 curproxy->url_param_name = strdup(defproxy.url_param_name);
708 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100709
710 if (defproxy.iface_name)
711 curproxy->iface_name = strdup(defproxy.iface_name);
712 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714
Willy Tarreau977b8e42006-12-29 14:19:17 +0100715 if (curproxy->cap & PR_CAP_RS) {
716 if (defproxy.capture_name)
717 curproxy->capture_name = strdup(defproxy.capture_name);
718 curproxy->capture_namelen = defproxy.capture_namelen;
719 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100720 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721
Willy Tarreau977b8e42006-12-29 14:19:17 +0100722 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100723 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100724 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100725 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100726 curproxy->uri_auth = defproxy.uri_auth;
727 curproxy->mon_net = defproxy.mon_net;
728 curproxy->mon_mask = defproxy.mon_mask;
729 if (defproxy.monitor_uri)
730 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
731 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100732 if (defproxy.defbe.name)
733 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100734 }
735
736 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100737 curproxy->timeout.connect = defproxy.timeout.connect;
738 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100739 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100740 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100741 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100742 curproxy->source_addr = defproxy.source_addr;
743 }
744
Willy Tarreaubaaee002006-06-26 02:48:02 +0200745 curproxy->mode = defproxy.mode;
746 curproxy->logfac1 = defproxy.logfac1;
747 curproxy->logsrv1 = defproxy.logsrv1;
748 curproxy->loglev1 = defproxy.loglev1;
749 curproxy->logfac2 = defproxy.logfac2;
750 curproxy->logsrv2 = defproxy.logsrv2;
751 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100753 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
754 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200755
Willy Tarreaubaaee002006-06-26 02:48:02 +0200756 return 0;
757 }
758 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
759 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100760 /* FIXME-20070101: we should do this too at the end of the
761 * config parsing to free all default values.
762 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200763 free(defproxy.check_req);
764 free(defproxy.cookie_name);
765 free(defproxy.url_param_name);
766 free(defproxy.capture_name);
767 free(defproxy.monitor_uri);
768 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100769 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200770 free(defproxy.fwdfor_hdr_name);
771 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100772
Willy Tarreaua534fea2008-08-03 12:19:50 +0200773 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
774 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100775
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 /* we cannot free uri_auth because it might already be used */
777 init_default_instance();
778 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100779 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780 return 0;
781 }
782 else if (curproxy == NULL) {
783 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
784 return -1;
785 }
786
Willy Tarreau977b8e42006-12-29 14:19:17 +0100787
788 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100790 struct listener *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100791 int cur_arg;
792
Willy Tarreaubaaee002006-06-26 02:48:02 +0200793 if (curproxy == &defproxy) {
794 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
795 return -1;
796 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100797 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
798 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200799
800 if (strchr(args[1], ':') == NULL) {
801 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
802 file, linenum, args[0]);
803 return -1;
804 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100805
806 last_listen = curproxy->listen;
807 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200808 if (!curproxy->listen)
809 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100810
811 cur_arg = 2;
812 while (*(args[cur_arg])) {
813 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
814#ifdef SO_BINDTODEVICE
815 struct listener *l;
816
817 if (!*args[cur_arg + 1]) {
818 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
819 file, linenum, args[0]);
820 return -1;
821 }
822
823 for (l = curproxy->listen; l != last_listen; l = l->next)
824 l->interface = strdup(args[cur_arg + 1]);
825
826 global.last_checks |= LSTCHK_NETADM;
827
828 cur_arg += 2;
829 continue;
830#else
831 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
832 file, linenum, args[0], args[cur_arg]);
833 return -1;
834#endif
835 }
836 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100837#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100838 struct listener *l;
839
840 for (l = curproxy->listen; l != last_listen; l = l->next)
841 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100842
843 cur_arg ++;
844 continue;
845#else
846 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
847 file, linenum, args[0], args[cur_arg]);
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100848 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100849#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100850 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100851 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100852 file, linenum, args[0]);
853 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200855 global.maxsock++;
856 return 0;
857 }
858 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
859 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
860 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
861 file, linenum, args[0]);
862 return -1;
863 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100864 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
865 return 0;
866
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867 /* flush useless bits */
868 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
869 return 0;
870 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200871 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100872 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
873 return 0;
874
Willy Tarreau1c47f852006-07-09 08:22:27 +0200875 if (!*args[1]) {
876 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
877 file, linenum, args[0]);
878 return -1;
879 }
880
Willy Tarreaua534fea2008-08-03 12:19:50 +0200881 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100882 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200883 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100884 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200885 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
886
887 return 0;
888 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200889 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
890 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
891 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
892 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
893 else {
894 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
895 return -1;
896 }
897 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100898 else if (!strcmp(args[0], "id")) {
899 struct proxy *target;
900
901 if (curproxy == &defproxy) {
902 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
903 file, linenum, args[0]);
904 return -1;
905 }
906
907 if (!*args[1]) {
908 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
909 file, linenum, args[0]);
910 return -1;
911 }
912
913 curproxy->uuid = atol(args[1]);
914
915 if (curproxy->uuid < 1001) {
916 Alert("parsing [%s:%d]: custom id has to be > 1000",
917 file, linenum);
918 return -1;
919 }
920
921 for (target = proxy; target; target = target->next)
922 if (curproxy != target && curproxy->uuid == target->uuid) {
923 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
924 file, linenum, curproxy->id, target->id);
925 return -1;
926 }
927 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200928 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
929 curproxy->state = PR_STSTOPPED;
930 }
931 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
932 curproxy->state = PR_STNEW;
933 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100934 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
935 int cur_arg = 1;
936 unsigned int set = 0;
937
938 while (*args[cur_arg]) {
939 int u;
940 if (strcmp(args[cur_arg], "all") == 0) {
941 set = 0;
942 break;
943 }
944 else if (strcmp(args[cur_arg], "odd") == 0) {
945 set |= 0x55555555;
946 }
947 else if (strcmp(args[cur_arg], "even") == 0) {
948 set |= 0xAAAAAAAA;
949 }
950 else {
951 u = str2uic(args[cur_arg]);
952 if (u < 1 || u > 32) {
953 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
954 file, linenum, args[0]);
955 return -1;
956 }
957 if (u > global.nbproc) {
958 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
959 file, linenum, args[0]);
960 }
961 set |= 1 << (u - 1);
962 }
963 cur_arg++;
964 }
965 curproxy->bind_proc = set;
966 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200967 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200968 if (curproxy == &defproxy) {
969 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
970 return -1;
971 }
972
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100973 err = invalid_char(args[1]);
974 if (err) {
975 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
976 file, linenum, *err, args[1]);
977 return -1;
978 }
979
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200980 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
981 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
982 file, linenum, args[1]);
983 return -1;
984 }
985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 else if (!strcmp(args[0], "cookie")) { /* cookie name */
987 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988
Willy Tarreau977b8e42006-12-29 14:19:17 +0100989 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
990 return 0;
991
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 if (*(args[1]) == 0) {
993 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
994 file, linenum, args[0]);
995 return -1;
996 }
Willy Tarreaua534fea2008-08-03 12:19:50 +0200997
998 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 curproxy->cookie_name = strdup(args[1]);
1000 curproxy->cookie_len = strlen(curproxy->cookie_name);
1001
1002 cur_arg = 2;
1003 while (*(args[cur_arg])) {
1004 if (!strcmp(args[cur_arg], "rewrite")) {
1005 curproxy->options |= PR_O_COOK_RW;
1006 }
1007 else if (!strcmp(args[cur_arg], "indirect")) {
1008 curproxy->options |= PR_O_COOK_IND;
1009 }
1010 else if (!strcmp(args[cur_arg], "insert")) {
1011 curproxy->options |= PR_O_COOK_INS;
1012 }
1013 else if (!strcmp(args[cur_arg], "nocache")) {
1014 curproxy->options |= PR_O_COOK_NOC;
1015 }
1016 else if (!strcmp(args[cur_arg], "postonly")) {
1017 curproxy->options |= PR_O_COOK_POST;
1018 }
1019 else if (!strcmp(args[cur_arg], "prefix")) {
1020 curproxy->options |= PR_O_COOK_PFX;
1021 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001022 else if (!strcmp(args[cur_arg], "domain")) {
1023 if (!*args[cur_arg + 1]) {
1024 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1025 file, linenum, args[cur_arg]);
1026 return -1;
1027 }
1028
1029 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1030 /* rfc2109, 4.3.2 Rejecting Cookies */
1031 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1032 " dots or does not start with a dot.\n",
1033 file, linenum, args[cur_arg + 1]);
1034 return -1;
1035 }
1036
1037 err = invalid_domainchar(args[cur_arg + 1]);
1038 if (err) {
1039 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1040 file, linenum, *err, args[cur_arg + 1]);
1041 return -1;
1042 }
1043
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001044 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001045 cur_arg++;
1046 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001048 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 file, linenum, args[0]);
1050 return -1;
1051 }
1052 cur_arg++;
1053 }
1054 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1055 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1056 file, linenum);
1057 return -1;
1058 }
1059
1060 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1061 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1062 file, linenum);
1063 return -1;
1064 }
1065 }/* end else if (!strcmp(args[0], "cookie")) */
1066 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001067
Willy Tarreau977b8e42006-12-29 14:19:17 +01001068 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1069 return 0;
1070
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 if (*(args[5]) == 0) {
1072 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1073 file, linenum, args[0]);
1074 return -1;
1075 }
1076 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001077 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078 curproxy->appsession_name = strdup(args[1]);
1079 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1080 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001081 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1082 if (err) {
1083 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1084 file, linenum, *err, args[0]);
1085 return -1;
1086 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001087 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001088
Willy Tarreau51041c72007-09-09 21:56:53 +02001089 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1090 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 return -1;
1092 }
1093 } /* Url App Session */
1094 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001095 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1096 return 0;
1097
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 if (*(args[4]) == 0) {
1100 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1101 file, linenum, args[0]);
1102 return -1;
1103 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001104 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001105 curproxy->capture_name = strdup(args[2]);
1106 curproxy->capture_namelen = strlen(curproxy->capture_name);
1107 curproxy->capture_len = atol(args[4]);
1108 if (curproxy->capture_len >= CAPTURE_LEN) {
1109 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1110 file, linenum, CAPTURE_LEN - 1);
1111 curproxy->capture_len = CAPTURE_LEN - 1;
1112 }
1113 curproxy->to_log |= LW_COOKIE;
1114 }
1115 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1116 struct cap_hdr *hdr;
1117
1118 if (curproxy == &defproxy) {
1119 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1120 return -1;
1121 }
1122
1123 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1124 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1125 file, linenum, args[0], args[1]);
1126 return -1;
1127 }
1128
1129 hdr = calloc(sizeof(struct cap_hdr), 1);
1130 hdr->next = curproxy->req_cap;
1131 hdr->name = strdup(args[3]);
1132 hdr->namelen = strlen(args[3]);
1133 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001134 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 hdr->index = curproxy->nb_req_cap++;
1136 curproxy->req_cap = hdr;
1137 curproxy->to_log |= LW_REQHDR;
1138 }
1139 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1140 struct cap_hdr *hdr;
1141
1142 if (curproxy == &defproxy) {
1143 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1144 return -1;
1145 }
1146
1147 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1148 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1149 file, linenum, args[0], args[1]);
1150 return -1;
1151 }
1152 hdr = calloc(sizeof(struct cap_hdr), 1);
1153 hdr->next = curproxy->rsp_cap;
1154 hdr->name = strdup(args[3]);
1155 hdr->namelen = strlen(args[3]);
1156 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001157 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158 hdr->index = curproxy->nb_rsp_cap++;
1159 curproxy->rsp_cap = hdr;
1160 curproxy->to_log |= LW_RSPHDR;
1161 }
1162 else {
1163 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1164 file, linenum, args[0]);
1165 return -1;
1166 }
1167 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001169 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1170 return 0;
1171
Willy Tarreaubaaee002006-06-26 02:48:02 +02001172 if (*(args[1]) == 0) {
1173 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1174 file, linenum, args[0]);
1175 return -1;
1176 }
1177 curproxy->conn_retries = atol(args[1]);
1178 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001179 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1180 int pol = ACL_COND_NONE;
1181 struct acl_cond *cond;
1182
Willy Tarreaub099aca2008-10-12 17:26:37 +02001183 if (curproxy == &defproxy) {
1184 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1185 return -1;
1186 }
1187
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001188 if (!strcmp(args[1], "if"))
1189 pol = ACL_COND_IF;
1190 else if (!strcmp(args[1], "unless"))
1191 pol = ACL_COND_UNLESS;
1192
1193 if (pol == ACL_COND_NONE) {
1194 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1195 file, linenum, args[0]);
1196 return -1;
1197 }
1198
1199 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1200 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1201 file, linenum);
1202 return -1;
1203 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001204 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001205 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1206 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001207 else if (!strcmp(args[0], "redirect")) {
1208 int pol = ACL_COND_NONE;
1209 struct acl_cond *cond;
1210 struct redirect_rule *rule;
1211 int cur_arg;
1212 int type = REDIRECT_TYPE_NONE;
1213 int code = 302;
1214 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001215 char *cookie = NULL;
1216 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001217 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001218
1219 cur_arg = 1;
1220 while (*(args[cur_arg])) {
1221 if (!strcmp(args[cur_arg], "location")) {
1222 if (!*args[cur_arg + 1]) {
1223 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1224 file, linenum, args[0], args[cur_arg]);
1225 return -1;
1226 }
1227
1228 type = REDIRECT_TYPE_LOCATION;
1229 cur_arg++;
1230 destination = args[cur_arg];
1231 }
1232 else if (!strcmp(args[cur_arg], "prefix")) {
1233 if (!*args[cur_arg + 1]) {
1234 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1235 file, linenum, args[0], args[cur_arg]);
1236 return -1;
1237 }
1238
1239 type = REDIRECT_TYPE_PREFIX;
1240 cur_arg++;
1241 destination = args[cur_arg];
1242 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001243 else if (!strcmp(args[cur_arg], "set-cookie")) {
1244 if (!*args[cur_arg + 1]) {
1245 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1246 file, linenum, args[0], args[cur_arg]);
1247 return -1;
1248 }
1249
1250 cur_arg++;
1251 cookie = args[cur_arg];
1252 cookie_set = 1;
1253 }
1254 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1255 if (!*args[cur_arg + 1]) {
1256 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1257 file, linenum, args[0], args[cur_arg]);
1258 return -1;
1259 }
1260
1261 cur_arg++;
1262 cookie = args[cur_arg];
1263 cookie_set = 0;
1264 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001265 else if (!strcmp(args[cur_arg],"code")) {
1266 if (!*args[cur_arg + 1]) {
1267 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1268 file, linenum, args[0]);
1269 return -1;
1270 }
1271 cur_arg++;
1272 code = atol(args[cur_arg]);
1273 if (code < 301 || code > 303) {
1274 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1275 file, linenum, args[0], code);
1276 return -1;
1277 }
1278 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001279 else if (!strcmp(args[cur_arg],"drop-query")) {
1280 flags |= REDIRECT_FLAG_DROP_QS;
1281 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001282 else if (!strcmp(args[cur_arg], "if")) {
1283 pol = ACL_COND_IF;
1284 cur_arg++;
1285 break;
1286 }
1287 else if (!strcmp(args[cur_arg], "unless")) {
1288 pol = ACL_COND_UNLESS;
1289 cur_arg++;
1290 break;
1291 }
1292 else {
1293 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1294 file, linenum, args[0], args[cur_arg]);
1295 return -1;
1296 }
1297 cur_arg++;
1298 }
1299
1300 if (type == REDIRECT_TYPE_NONE) {
1301 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1302 file, linenum, args[0]);
1303 return -1;
1304 }
1305
1306 if (pol == ACL_COND_NONE) {
1307 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1308 file, linenum, args[0]);
1309 return -1;
1310 }
1311
1312 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1313 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1314 file, linenum, args[0]);
1315 return -1;
1316 }
1317
Willy Tarreaua9802632008-07-25 19:13:19 +02001318 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001319 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1320 rule->cond = cond;
1321 rule->rdr_str = strdup(destination);
1322 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001323 if (cookie) {
1324 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1325 * a clear consists in appending "; Max-Age=0" at the end.
1326 */
1327 rule->cookie_len = strlen(cookie);
1328 if (cookie_set)
1329 rule->cookie_str = strdup(cookie);
1330 else {
1331 rule->cookie_str = malloc(rule->cookie_len + 12);
1332 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1333 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1334 rule->cookie_len += 11;
1335 }
1336 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001337 rule->type = type;
1338 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001339 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001340 LIST_INIT(&rule->list);
1341 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1342 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001343 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001344 int pol = ACL_COND_NONE;
1345 struct acl_cond *cond;
1346 struct switching_rule *rule;
1347
Willy Tarreaub099aca2008-10-12 17:26:37 +02001348 if (curproxy == &defproxy) {
1349 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1350 return -1;
1351 }
1352
Willy Tarreau55ea7572007-06-17 19:56:27 +02001353 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1354 return 0;
1355
1356 if (*(args[1]) == 0) {
1357 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1358 return -1;
1359 }
1360
1361 if (!strcmp(args[2], "if"))
1362 pol = ACL_COND_IF;
1363 else if (!strcmp(args[2], "unless"))
1364 pol = ACL_COND_UNLESS;
1365
1366 if (pol == ACL_COND_NONE) {
1367 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1368 file, linenum, args[0]);
1369 return -1;
1370 }
1371
1372 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001373 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001374 file, linenum);
1375 return -1;
1376 }
1377
Willy Tarreaua9802632008-07-25 19:13:19 +02001378 cond->line = linenum;
1379 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001380 struct acl *acl;
1381 const char *name;
1382
1383 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1384 name = acl ? acl->name : "(unknown)";
1385 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1386 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001387 }
1388
Willy Tarreau55ea7572007-06-17 19:56:27 +02001389 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1390 rule->cond = cond;
1391 rule->be.name = strdup(args[1]);
1392 LIST_INIT(&rule->list);
1393 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001396 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1397 return 0;
1398
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1400 curproxy->uri_auth = NULL; /* we must detach from the default config */
1401
1402 if (*(args[1]) == 0) {
1403 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1404 return -1;
1405 } else if (!strcmp(args[1], "uri")) {
1406 if (*(args[2]) == 0) {
1407 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1408 return -1;
1409 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1410 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1411 return -1;
1412 }
1413 } else if (!strcmp(args[1], "realm")) {
1414 if (*(args[2]) == 0) {
1415 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1416 return -1;
1417 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1418 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1419 return -1;
1420 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001421 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001422 unsigned interval;
1423
1424 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1425 if (err) {
1426 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1427 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001428 return -1;
1429 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1430 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1431 return -1;
1432 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 } else if (!strcmp(args[1], "auth")) {
1434 if (*(args[2]) == 0) {
1435 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1436 return -1;
1437 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1438 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1439 return -1;
1440 }
1441 } else if (!strcmp(args[1], "scope")) {
1442 if (*(args[2]) == 0) {
1443 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1444 return -1;
1445 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1446 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1447 return -1;
1448 }
1449 } else if (!strcmp(args[1], "enable")) {
1450 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1451 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1452 return -1;
1453 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001454 } else if (!strcmp(args[1], "hide-version")) {
1455 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1456 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1457 return -1;
1458 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001460 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001461 file, linenum, args[0]);
1462 return -1;
1463 }
1464 }
1465 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001466 int optnum;
1467
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001468 if (*(args[1]) == '\0') {
1469 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1470 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001471 return -1;
1472 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001473
1474 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1475 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1476 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1477 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001478
1479 if (!inv)
1480 curproxy->options |= cfg_opts[optnum].val;
1481 else
1482 curproxy->options &= ~cfg_opts[optnum].val;
1483
Willy Tarreau13943ab2006-12-31 00:24:10 +01001484 return 0;
1485 }
1486 }
1487
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001488 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1489 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
1490 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
1491 return 0;
1492
1493 if (!inv)
1494 curproxy->options2 |= cfg_opts2[optnum].val;
1495 else
1496 curproxy->options2 &= ~cfg_opts2[optnum].val;
1497
1498 return 0;
1499 }
1500 }
1501
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001502 if (inv) {
1503 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1504 file, linenum, args[1]);
1505 return -1;
1506 }
1507
Willy Tarreau13943ab2006-12-31 00:24:10 +01001508 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001509 /* generate a complete HTTP log */
1510 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1511 else if (!strcmp(args[1], "tcplog"))
1512 /* generate a detailed TCP log */
1513 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001514 else if (!strcmp(args[1], "tcpka")) {
1515 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001516 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1517 return 0;
1518
1519 if (curproxy->cap & PR_CAP_FE)
1520 curproxy->options |= PR_O_TCP_CLI_KA;
1521 if (curproxy->cap & PR_CAP_BE)
1522 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523 }
1524 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001525 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1526 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001528 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001529 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001530 curproxy->options &= ~PR_O_SMTP_CHK;
1531 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532 if (!*args[2]) { /* no argument */
1533 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1534 curproxy->check_len = strlen(DEF_CHECK_REQ);
1535 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001536 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537 curproxy->check_req = (char *)malloc(reqlen);
1538 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1539 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1540 } else { /* more arguments : METHOD URI [HTTP_VER] */
1541 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1542 if (*args[4])
1543 reqlen += strlen(args[4]);
1544 else
1545 reqlen += strlen("HTTP/1.0");
1546
1547 curproxy->check_req = (char *)malloc(reqlen);
1548 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1549 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1550 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001551 }
1552 else if (!strcmp(args[1], "ssl-hello-chk")) {
1553 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001554 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1555 return 0;
1556
Willy Tarreaua534fea2008-08-03 12:19:50 +02001557 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001558 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001559 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001560 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561 }
Willy Tarreau23677902007-05-08 23:50:35 +02001562 else if (!strcmp(args[1], "smtpchk")) {
1563 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001564 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001565 curproxy->options &= ~PR_O_HTTP_CHK;
1566 curproxy->options &= ~PR_O_SSL3_CHK;
1567 curproxy->options |= PR_O_SMTP_CHK;
1568
1569 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1570 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1571 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1572 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1573 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1574 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1575 curproxy->check_req = (char *)malloc(reqlen);
1576 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1577 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1578 } else {
1579 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1580 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1581 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1582 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1583 }
1584 }
1585 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001586 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001587 int cur_arg;
1588
1589 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1590 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001591 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001592
1593 curproxy->options |= PR_O_FWDFOR;
1594
1595 free(curproxy->fwdfor_hdr_name);
1596 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1597 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1598
1599 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1600 cur_arg = 2;
1601 while (*(args[cur_arg])) {
1602 if (!strcmp(args[cur_arg], "except")) {
1603 /* suboption except - needs additional argument for it */
1604 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1605 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1606 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001607 return -1;
1608 }
1609 /* flush useless bits */
1610 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001611 cur_arg += 2;
1612 } else if (!strcmp(args[cur_arg], "header")) {
1613 /* suboption header - needs additional argument for it */
1614 if (*(args[cur_arg+1]) == 0) {
1615 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1616 file, linenum, args[0], args[1], args[cur_arg]);
1617 return -1;
1618 }
1619 free(curproxy->fwdfor_hdr_name);
1620 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1621 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1622 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001623 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001624 /* unknown suboption - catchall */
1625 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1626 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001627 return -1;
1628 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001629 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001630 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 else {
1632 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1633 return -1;
1634 }
1635 return 0;
1636 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001637 else if (!strcmp(args[0], "default_backend")) {
1638 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1639 return 0;
1640
1641 if (*(args[1]) == 0) {
1642 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1643 return -1;
1644 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001645 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001646 curproxy->defbe.name = strdup(args[1]);
1647 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001648 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001649 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1650 return 0;
1651
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001652 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1653 file, linenum, args[0]);
1654
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 /* enable reconnections to dispatch */
1656 curproxy->options |= PR_O_REDISP;
1657 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001658 else if (!strcmp(args[0], "http-check")) {
1659 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1660 return 0;
1661
1662 if (strcmp(args[1], "disable-on-404") == 0) {
1663 /* enable a graceful server shutdown on an HTTP 404 response */
1664 curproxy->options |= PR_O_DISABLE404;
1665 }
1666 else {
1667 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1668 return -1;
1669 }
1670 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001671 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001672 if (curproxy == &defproxy) {
1673 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1674 return -1;
1675 }
1676
Willy Tarreaub80c2302007-11-30 20:51:32 +01001677 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1678 return 0;
1679
1680 if (strcmp(args[1], "fail") == 0) {
1681 /* add a condition to fail monitor requests */
1682 int pol = ACL_COND_NONE;
1683 struct acl_cond *cond;
1684
1685 if (!strcmp(args[2], "if"))
1686 pol = ACL_COND_IF;
1687 else if (!strcmp(args[2], "unless"))
1688 pol = ACL_COND_UNLESS;
1689
1690 if (pol == ACL_COND_NONE) {
1691 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1692 file, linenum, args[0], args[1]);
1693 return -1;
1694 }
1695
1696 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1697 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1698 file, linenum, args[0], args[1]);
1699 return -1;
1700 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001701 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001702 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1703 }
1704 else {
1705 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1706 return -1;
1707 }
1708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001709#ifdef TPROXY
1710 else if (!strcmp(args[0], "transparent")) {
1711 /* enable transparent proxy connections */
1712 curproxy->options |= PR_O_TRANSP;
1713 }
1714#endif
1715 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001716 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1717 return 0;
1718
Willy Tarreaubaaee002006-06-26 02:48:02 +02001719 if (*(args[1]) == 0) {
1720 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1721 return -1;
1722 }
1723 curproxy->maxconn = atol(args[1]);
1724 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001725 else if (!strcmp(args[0], "backlog")) { /* backlog */
1726 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1727 return 0;
1728
1729 if (*(args[1]) == 0) {
1730 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1731 return -1;
1732 }
1733 curproxy->backlog = atol(args[1]);
1734 }
Willy Tarreau86034312006-12-29 00:10:33 +01001735 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001736 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1737 return 0;
1738
Willy Tarreau86034312006-12-29 00:10:33 +01001739 if (*(args[1]) == 0) {
1740 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1741 return -1;
1742 }
1743 curproxy->fullconn = atol(args[1]);
1744 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001745 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1746 if (*(args[1]) == 0) {
1747 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1748 return -1;
1749 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001750 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1751 if (err) {
1752 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1753 file, linenum, *err);
1754 return -1;
1755 }
1756 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001757 }
1758 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1759 if (curproxy == &defproxy) {
1760 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1761 return -1;
1762 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001763 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1764 return 0;
1765
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766 if (strchr(args[1], ':') == NULL) {
1767 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1768 return -1;
1769 }
1770 curproxy->dispatch_addr = *str2sa(args[1]);
1771 }
1772 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001773 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1774 return 0;
1775
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02001776 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001777 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1778 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1779 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001781 }
1782 else if (!strcmp(args[0], "server")) { /* server address */
1783 int cur_arg;
1784 char *rport;
1785 char *raddr;
1786 short realport;
1787 int do_check;
1788
1789 if (curproxy == &defproxy) {
1790 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1791 return -1;
1792 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001793 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1794 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001795
1796 if (!*args[2]) {
1797 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1798 file, linenum, args[0]);
1799 return -1;
1800 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001801
1802 err = invalid_char(args[1]);
1803 if (err) {
1804 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1805 file, linenum, *err, args[1]);
1806 return -1;
1807 }
1808
Willy Tarreaubaaee002006-06-26 02:48:02 +02001809 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1810 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1811 return -1;
1812 }
1813
1814 /* the servers are linked backwards first */
1815 newsrv->next = curproxy->srv;
1816 curproxy->srv = newsrv;
1817 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001818 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001819
1820 LIST_INIT(&newsrv->pendconns);
1821 do_check = 0;
1822 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001823 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001824 newsrv->id = strdup(args[1]);
1825
1826 /* several ways to check the port component :
1827 * - IP => port=+0, relative
1828 * - IP: => port=+0, relative
1829 * - IP:N => port=N, absolute
1830 * - IP:+N => port=+N, relative
1831 * - IP:-N => port=-N, relative
1832 */
1833 raddr = strdup(args[2]);
1834 rport = strchr(raddr, ':');
1835 if (rport) {
1836 *rport++ = 0;
1837 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001838 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001839 newsrv->state |= SRV_MAPPORTS;
1840 } else {
1841 realport = 0;
1842 newsrv->state |= SRV_MAPPORTS;
1843 }
1844
1845 newsrv->addr = *str2sa(raddr);
1846 newsrv->addr.sin_port = htons(realport);
1847 free(raddr);
1848
1849 newsrv->curfd = -1; /* no health-check in progress */
1850 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001851 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1852 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001853 newsrv->rise = DEF_RISETIME;
1854 newsrv->fall = DEF_FALLTIME;
1855 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001856 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001857 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001858 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001859
Willy Tarreaubaaee002006-06-26 02:48:02 +02001860 cur_arg = 3;
1861 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001862 if (!strcmp(args[cur_arg], "id")) {
1863 struct server *target;
1864
1865 if (!*args[cur_arg + 1]) {
1866 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1867 file, linenum, args[cur_arg]);
1868 return -1;
1869 }
1870
1871 newsrv->puid = atol(args[cur_arg + 1]);
1872
1873 if (newsrv->puid< 1001) {
1874 Alert("parsing [%s:%d]: custom id has to be > 1000",
1875 file, linenum);
1876 return -1;
1877 }
1878
1879 for (target = proxy->srv; target; target = target->next)
1880 if (newsrv != target && newsrv->puid == target->puid) {
1881 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1882 file, linenum, newsrv->id, target->id);
1883 return -1;
1884 }
1885 cur_arg += 2;
1886 }
1887 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001888 newsrv->cookie = strdup(args[cur_arg + 1]);
1889 newsrv->cklen = strlen(args[cur_arg + 1]);
1890 cur_arg += 2;
1891 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001892 else if (!strcmp(args[cur_arg], "redir")) {
1893 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1894 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1895 cur_arg += 2;
1896 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001897 else if (!strcmp(args[cur_arg], "rise")) {
1898 newsrv->rise = atol(args[cur_arg + 1]);
1899 newsrv->health = newsrv->rise;
1900 cur_arg += 2;
1901 }
1902 else if (!strcmp(args[cur_arg], "fall")) {
1903 newsrv->fall = atol(args[cur_arg + 1]);
1904 cur_arg += 2;
1905 }
1906 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001907 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1908 if (err) {
1909 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1910 file, linenum, *err, newsrv->id);
1911 return -1;
1912 }
1913 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914 cur_arg += 2;
1915 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001916 else if (!strcmp(args[cur_arg], "fastinter")) {
1917 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1918 if (err) {
1919 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1920 file, linenum, *err, newsrv->id);
1921 return -1;
1922 }
1923 newsrv->fastinter = val;
1924 cur_arg += 2;
1925 }
1926 else if (!strcmp(args[cur_arg], "downinter")) {
1927 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1928 if (err) {
1929 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1930 file, linenum, *err, newsrv->id);
1931 return -1;
1932 }
1933 newsrv->downinter = val;
1934 cur_arg += 2;
1935 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001936 else if (!strcmp(args[cur_arg], "addr")) {
1937 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001938 cur_arg += 2;
1939 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 else if (!strcmp(args[cur_arg], "port")) {
1941 newsrv->check_port = atol(args[cur_arg + 1]);
1942 cur_arg += 2;
1943 }
1944 else if (!strcmp(args[cur_arg], "backup")) {
1945 newsrv->state |= SRV_BACKUP;
1946 cur_arg ++;
1947 }
1948 else if (!strcmp(args[cur_arg], "weight")) {
1949 int w;
1950 w = atol(args[cur_arg + 1]);
1951 if (w < 1 || w > 256) {
1952 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1953 file, linenum, newsrv->id, w);
1954 return -1;
1955 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001956 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001957 cur_arg += 2;
1958 }
1959 else if (!strcmp(args[cur_arg], "minconn")) {
1960 newsrv->minconn = atol(args[cur_arg + 1]);
1961 cur_arg += 2;
1962 }
1963 else if (!strcmp(args[cur_arg], "maxconn")) {
1964 newsrv->maxconn = atol(args[cur_arg + 1]);
1965 cur_arg += 2;
1966 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001967 else if (!strcmp(args[cur_arg], "maxqueue")) {
1968 newsrv->maxqueue = atol(args[cur_arg + 1]);
1969 cur_arg += 2;
1970 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001971 else if (!strcmp(args[cur_arg], "slowstart")) {
1972 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001973 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001974 if (err) {
1975 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1976 file, linenum, *err, newsrv->id);
1977 return -1;
1978 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001979 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001980 cur_arg += 2;
1981 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001982 else if (!strcmp(args[cur_arg], "track")) {
1983
1984 if (!*args[cur_arg + 1]) {
1985 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1986 file, linenum);
1987 return -1;
1988 }
1989
1990 newsrv->trackit = strdup(args[cur_arg + 1]);
1991
1992 cur_arg += 2;
1993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994 else if (!strcmp(args[cur_arg], "check")) {
1995 global.maxsock++;
1996 do_check = 1;
1997 cur_arg += 1;
1998 }
1999 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
2000 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002001#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002002 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2003 file, linenum, "source", "usesrc");
2004#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002005 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2006 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002007#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 return -1;
2009 }
2010 newsrv->state |= SRV_BIND_SRC;
2011 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
2012 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002013 while (*(args[cur_arg])) {
2014 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002015#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2016#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002017 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2018 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2019 file, linenum, "usesrc", "source");
2020 return -1;
2021 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002022#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002023 if (!*args[cur_arg + 1]) {
2024 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2025 file, linenum, "usesrc");
2026 return -1;
2027 }
2028 if (!strcmp(args[cur_arg + 1], "client")) {
2029 newsrv->state |= SRV_TPROXY_CLI;
2030 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2031 newsrv->state |= SRV_TPROXY_CIP;
2032 } else {
2033 newsrv->state |= SRV_TPROXY_ADDR;
2034 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2035 }
2036 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002037#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002038 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002039#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002040 cur_arg += 2;
2041 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002042#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002043 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002044 file, linenum, "usesrc");
2045 return -1;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002046#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2047 } /* "usesrc" */
2048
2049 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2050#ifdef SO_BINDTODEVICE
2051 if (!*args[cur_arg + 1]) {
2052 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2053 file, linenum, args[0]);
2054 return -1;
2055 }
2056 if (newsrv->iface_name)
2057 free(newsrv->iface_name);
2058
2059 newsrv->iface_name = strdup(args[cur_arg + 1]);
2060 newsrv->iface_len = strlen(newsrv->iface_name);
2061 global.last_checks |= LSTCHK_NETADM;
2062#else
2063 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2064 file, linenum, args[0], args[cur_arg]);
2065 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002066#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002067 cur_arg += 2;
2068 continue;
2069 }
2070 /* this keyword in not an option of "source" */
2071 break;
2072 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002073 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002074 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2075 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2076 file, linenum, "usesrc", "source");
2077 return -1;
2078 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002079 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002080 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 +02002081 file, linenum, newsrv->id);
2082 return -1;
2083 }
2084 }
2085
2086 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002087 if (newsrv->trackit) {
2088 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2089 file, linenum);
2090 return -1;
2091 }
2092
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002093 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2094 newsrv->check_port = newsrv->check_addr.sin_port;
2095
Willy Tarreaubaaee002006-06-26 02:48:02 +02002096 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2097 newsrv->check_port = realport; /* by default */
2098 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002099 /* not yet valid, because no port was set on
2100 * the server either. We'll check if we have
2101 * a known port on the first listener.
2102 */
2103 struct listener *l;
2104 l = curproxy->listen;
2105 if (l) {
2106 int port;
2107 port = (l->addr.ss_family == AF_INET6)
2108 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2109 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2110 newsrv->check_port = port;
2111 }
2112 }
2113 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2115 file, linenum, newsrv->id);
2116 return -1;
2117 }
2118 newsrv->state |= SRV_CHECKED;
2119 }
2120
2121 if (newsrv->state & SRV_BACKUP)
2122 curproxy->srv_bck++;
2123 else
2124 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002125
2126 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002127 }
2128 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002129 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002130 int facility;
2131
2132 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2133 curproxy->logfac1 = global.logfac1;
2134 curproxy->logsrv1 = global.logsrv1;
2135 curproxy->loglev1 = global.loglev1;
2136 curproxy->logfac2 = global.logfac2;
2137 curproxy->logsrv2 = global.logsrv2;
2138 curproxy->loglev2 = global.loglev2;
2139 }
2140 else if (*(args[1]) && *(args[2])) {
2141 int level;
2142
2143 facility = get_log_facility(args[2]);
2144 if (facility < 0) {
2145 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2146 exit(1);
2147 }
2148
2149 level = 7; /* max syslog level = debug */
2150 if (*(args[3])) {
2151 level = get_log_level(args[3]);
2152 if (level < 0) {
2153 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2154 exit(1);
2155 }
2156 }
2157
Robert Tsai81ae1952007-12-05 10:47:29 +01002158 if (args[1][0] == '/') {
2159 logsrv.u.addr.sa_family = AF_UNIX;
2160 logsrv.u.un = *str2sun(args[1]);
2161 } else {
2162 logsrv.u.addr.sa_family = AF_INET;
2163 logsrv.u.in = *str2sa(args[1]);
2164 if (!logsrv.u.in.sin_port) {
2165 logsrv.u.in.sin_port =
2166 htons(SYSLOG_PORT);
2167 }
2168 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002169
2170 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002171 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002172 curproxy->logfac1 = facility;
2173 curproxy->loglev1 = level;
2174 }
2175 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002176 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 curproxy->logfac2 = facility;
2178 curproxy->loglev2 = level;
2179 }
2180 else {
2181 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2182 return -1;
2183 }
2184 }
2185 else {
2186 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2187 file, linenum);
2188 return -1;
2189 }
2190 }
2191 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002192 int cur_arg;
2193
Willy Tarreau977b8e42006-12-29 14:19:17 +01002194 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2195 return 0;
2196
Willy Tarreaubaaee002006-06-26 02:48:02 +02002197 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002198 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2199 file, linenum, "source", "usesrc", "interface");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002200 return -1;
2201 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002202
2203 /* we must first clear any optional default setting */
2204 curproxy->options &= ~PR_O_TPXY_MASK;
2205 free(curproxy->iface_name);
2206 curproxy->iface_name = NULL;
2207 curproxy->iface_len = 0;
2208
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 curproxy->source_addr = *str2sa(args[1]);
2210 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002211
2212 cur_arg = 2;
2213 while (*(args[cur_arg])) {
2214 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002215#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2216#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002217 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2218 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2219 file, linenum, "usesrc");
2220 return -1;
2221 }
2222#endif
2223 if (!*args[cur_arg + 1]) {
2224 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2225 file, linenum, "usesrc");
2226 return -1;
2227 }
2228
2229 if (!strcmp(args[cur_arg + 1], "client")) {
2230 curproxy->options |= PR_O_TPXY_CLI;
2231 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2232 curproxy->options |= PR_O_TPXY_CIP;
2233 } else {
2234 curproxy->options |= PR_O_TPXY_ADDR;
2235 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2236 }
2237 global.last_checks |= LSTCHK_NETADM;
2238#if !defined(CONFIG_HAP_LINUX_TPROXY)
2239 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002240#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002241#else /* no TPROXY support */
2242 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002243 file, linenum, "usesrc");
2244 return -1;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002245#endif
2246 cur_arg += 2;
2247 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002248 }
2249
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002250 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2251#ifdef SO_BINDTODEVICE
2252 if (!*args[cur_arg + 1]) {
2253 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2254 file, linenum, args[0]);
2255 return -1;
2256 }
2257 if (curproxy->iface_name)
2258 free(curproxy->iface_name);
2259
2260 curproxy->iface_name = strdup(args[cur_arg + 1]);
2261 curproxy->iface_len = strlen(curproxy->iface_name);
2262 global.last_checks |= LSTCHK_NETADM;
2263#else
2264 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2265 file, linenum, args[0], args[cur_arg]);
2266 return -1;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002267#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002268 cur_arg += 2;
2269 continue;
2270 }
2271 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2272 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002273 return -1;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002276 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2277 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2278 file, linenum, "usesrc", "source");
2279 return -1;
2280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002281 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2282 regex_t *preg;
2283 if (curproxy == &defproxy) {
2284 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2285 return -1;
2286 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002287 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2288 return 0;
2289
Willy Tarreaubaaee002006-06-26 02:48:02 +02002290 if (*(args[1]) == 0 || *(args[2]) == 0) {
2291 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2292 file, linenum, args[0]);
2293 return -1;
2294 }
2295
2296 preg = calloc(1, sizeof(regex_t));
2297 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2298 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2299 return -1;
2300 }
2301
2302 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2303 if (err) {
2304 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2305 file, linenum, *err);
2306 return -1;
2307 }
2308 }
2309 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2310 regex_t *preg;
2311 if (curproxy == &defproxy) {
2312 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2313 return -1;
2314 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002315 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2316 return 0;
2317
Willy Tarreaubaaee002006-06-26 02:48:02 +02002318 if (*(args[1]) == 0) {
2319 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2320 return -1;
2321 }
2322
2323 preg = calloc(1, sizeof(regex_t));
2324 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2325 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2326 return -1;
2327 }
2328
2329 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2330 }
2331 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2332 regex_t *preg;
2333 if (curproxy == &defproxy) {
2334 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2335 return -1;
2336 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002337 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2338 return 0;
2339
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 if (*(args[1]) == 0) {
2341 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2342 return -1;
2343 }
2344
2345 preg = calloc(1, sizeof(regex_t));
2346 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2347 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2348 return -1;
2349 }
2350
2351 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2352 }
2353 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2354 regex_t *preg;
2355 if (curproxy == &defproxy) {
2356 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2357 return -1;
2358 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002359 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2360 return 0;
2361
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 if (*(args[1]) == 0) {
2363 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2364 return -1;
2365 }
2366
2367 preg = calloc(1, sizeof(regex_t));
2368 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2369 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2370 return -1;
2371 }
2372
2373 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2374 }
2375 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2376 regex_t *preg;
2377 if (curproxy == &defproxy) {
2378 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2379 return -1;
2380 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002381 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2382 return 0;
2383
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 if (*(args[1]) == 0) {
2385 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2386 return -1;
2387 }
2388
2389 preg = calloc(1, sizeof(regex_t));
2390 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2391 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2392 return -1;
2393 }
2394
2395 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2396 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002397 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2398 regex_t *preg;
2399 if (curproxy == &defproxy) {
2400 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2401 return -1;
2402 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002403 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2404 return 0;
2405
Willy Tarreaub8750a82006-09-03 09:56:00 +02002406 if (*(args[1]) == 0) {
2407 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2408 return -1;
2409 }
2410
2411 preg = calloc(1, sizeof(regex_t));
2412 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2413 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2414 return -1;
2415 }
2416
2417 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2418 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002419 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2420 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002421 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002422 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2423 return -1;
2424 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002425 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2426 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002427
Willy Tarreau977b8e42006-12-29 14:19:17 +01002428 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002429 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2430 file, linenum, args[0]);
2431 return -1;
2432 }
2433
2434 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002435 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002436 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2437 }
2438
2439 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2440 }
2441 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2442 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002443 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002444 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2445 return -1;
2446 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002447 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2448 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002449
Willy Tarreau977b8e42006-12-29 14:19:17 +01002450 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002451 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2452 file, linenum, args[0]);
2453 return -1;
2454 }
2455
2456 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002457 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002458 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2459 }
2460
2461 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2462 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2464 regex_t *preg;
2465 if (curproxy == &defproxy) {
2466 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2467 return -1;
2468 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002469 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2470 return 0;
2471
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 if (*(args[1]) == 0 || *(args[2]) == 0) {
2473 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2474 file, linenum, args[0]);
2475 return -1;
2476 }
2477
2478 preg = calloc(1, sizeof(regex_t));
2479 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2480 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2481 return -1;
2482 }
2483
2484 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2485 if (err) {
2486 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2487 file, linenum, *err);
2488 return -1;
2489 }
2490 }
2491 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2492 regex_t *preg;
2493 if (curproxy == &defproxy) {
2494 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2495 return -1;
2496 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002497 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2498 return 0;
2499
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500 if (*(args[1]) == 0) {
2501 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2502 return -1;
2503 }
2504
2505 preg = calloc(1, sizeof(regex_t));
2506 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2507 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2508 return -1;
2509 }
2510
2511 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2512 }
2513 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2514 regex_t *preg;
2515 if (curproxy == &defproxy) {
2516 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2517 return -1;
2518 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002519 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2520 return 0;
2521
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522 if (*(args[1]) == 0) {
2523 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2524 return -1;
2525 }
2526
2527 preg = calloc(1, sizeof(regex_t));
2528 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2529 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2530 return -1;
2531 }
2532
2533 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2534 }
2535 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2536 regex_t *preg;
2537 if (curproxy == &defproxy) {
2538 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2539 return -1;
2540 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002541 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2542 return 0;
2543
Willy Tarreaubaaee002006-06-26 02:48:02 +02002544 if (*(args[1]) == 0) {
2545 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2546 return -1;
2547 }
2548
2549 preg = calloc(1, sizeof(regex_t));
2550 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2551 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2552 return -1;
2553 }
2554
2555 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2556 }
2557 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2558 regex_t *preg;
2559 if (curproxy == &defproxy) {
2560 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2561 return -1;
2562 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002563 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2564 return 0;
2565
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 if (*(args[1]) == 0) {
2567 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2568 return -1;
2569 }
2570
2571 preg = calloc(1, sizeof(regex_t));
2572 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2573 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2574 return -1;
2575 }
2576
2577 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2578 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002579 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2580 regex_t *preg;
2581 if (curproxy == &defproxy) {
2582 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2583 return -1;
2584 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002585 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2586 return 0;
2587
Willy Tarreaub8750a82006-09-03 09:56:00 +02002588 if (*(args[1]) == 0) {
2589 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2590 return -1;
2591 }
2592
2593 preg = calloc(1, sizeof(regex_t));
2594 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2595 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2596 return -1;
2597 }
2598
2599 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2600 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002601 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2602 if (curproxy == &defproxy) {
2603 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2604 return -1;
2605 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002606 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2607 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002608
2609 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2610 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2611 return 0;
2612 }
2613
2614 if (*(args[1]) == 0) {
2615 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2616 return -1;
2617 }
2618
2619 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2620 }
2621 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2622 regex_t *preg;
2623
2624 if (*(args[1]) == 0 || *(args[2]) == 0) {
2625 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2626 file, linenum, args[0]);
2627 return -1;
2628 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002629 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2630 return 0;
2631
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632 preg = calloc(1, sizeof(regex_t));
2633 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2634 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2635 return -1;
2636 }
2637
2638 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2639 if (err) {
2640 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2641 file, linenum, *err);
2642 return -1;
2643 }
2644 }
2645 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2646 regex_t *preg;
2647 if (curproxy == &defproxy) {
2648 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2649 return -1;
2650 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002651 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2652 return 0;
2653
Willy Tarreaubaaee002006-06-26 02:48:02 +02002654 if (*(args[1]) == 0) {
2655 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2656 return -1;
2657 }
2658
2659 preg = calloc(1, sizeof(regex_t));
2660 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2661 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2662 return -1;
2663 }
2664
2665 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2666 if (err) {
2667 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2668 file, linenum, *err);
2669 return -1;
2670 }
2671 }
2672 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2673 regex_t *preg;
2674 if (curproxy == &defproxy) {
2675 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2676 return -1;
2677 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002678 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2679 return 0;
2680
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681 if (*(args[1]) == 0) {
2682 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2683 return -1;
2684 }
2685
2686 preg = calloc(1, sizeof(regex_t));
2687 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2688 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2689 return -1;
2690 }
2691
2692 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2693 if (err) {
2694 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2695 file, linenum, *err);
2696 return -1;
2697 }
2698 }
2699 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2700 regex_t *preg;
2701 if (curproxy == &defproxy) {
2702 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2703 return -1;
2704 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002705 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2706 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002707
2708 if (*(args[1]) == 0 || *(args[2]) == 0) {
2709 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2710 file, linenum, args[0]);
2711 return -1;
2712 }
2713
2714 preg = calloc(1, sizeof(regex_t));
2715 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2716 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2717 return -1;
2718 }
2719
2720 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2721 if (err) {
2722 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2723 file, linenum, *err);
2724 return -1;
2725 }
2726 }
2727 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2728 regex_t *preg;
2729 if (curproxy == &defproxy) {
2730 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2731 return -1;
2732 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002733 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2734 return 0;
2735
Willy Tarreaubaaee002006-06-26 02:48:02 +02002736 if (*(args[1]) == 0) {
2737 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2738 return -1;
2739 }
2740
2741 preg = calloc(1, sizeof(regex_t));
2742 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2743 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2744 return -1;
2745 }
2746
2747 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2748 if (err) {
2749 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2750 file, linenum, *err);
2751 return -1;
2752 }
2753 }
2754 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2755 regex_t *preg;
2756 if (curproxy == &defproxy) {
2757 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2758 return -1;
2759 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002760 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2761 return 0;
2762
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 if (*(args[1]) == 0) {
2764 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2765 return -1;
2766 }
2767
2768 preg = calloc(1, sizeof(regex_t));
2769 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2770 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2771 return -1;
2772 }
2773
2774 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2775 if (err) {
2776 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2777 file, linenum, *err);
2778 return -1;
2779 }
2780 }
2781 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2782 if (curproxy == &defproxy) {
2783 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2784 return -1;
2785 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002786 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2787 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002788
2789 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2790 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2791 return 0;
2792 }
2793
2794 if (*(args[1]) == 0) {
2795 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2796 return -1;
2797 }
2798
2799 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2800 }
2801 else if (!strcmp(args[0], "errorloc") ||
2802 !strcmp(args[0], "errorloc302") ||
2803 !strcmp(args[0], "errorloc303")) { /* error location */
2804 int errnum, errlen;
2805 char *err;
2806
Willy Tarreau977b8e42006-12-29 14:19:17 +01002807 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2808 return 0;
2809
Willy Tarreaubaaee002006-06-26 02:48:02 +02002810 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002811 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002812 return -1;
2813 }
2814
2815 errnum = atol(args[1]);
2816 if (!strcmp(args[0], "errorloc303")) {
2817 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2818 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2819 } else {
2820 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2821 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2822 }
2823
Willy Tarreau0f772532006-12-23 20:51:41 +01002824 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2825 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002826 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002827 curproxy->errmsg[rc].str = err;
2828 curproxy->errmsg[rc].len = errlen;
2829 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002830 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002831 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002832
2833 if (rc >= HTTP_ERR_SIZE) {
2834 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2835 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002836 free(err);
2837 }
2838 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002839 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2840 int errnum, errlen, fd;
2841 char *err;
2842 struct stat stat;
2843
2844 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2845 return 0;
2846
2847 if (*(args[2]) == 0) {
2848 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2849 return -1;
2850 }
2851
2852 fd = open(args[2], O_RDONLY);
2853 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2854 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2855 file, linenum, args[2], args[1]);
2856 if (fd >= 0)
2857 close(fd);
2858 return -1;
2859 }
2860
2861 if (stat.st_size <= BUFSIZE) {
2862 errlen = stat.st_size;
2863 } else {
2864 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2865 file, linenum, args[2], BUFSIZE);
2866 errlen = BUFSIZE;
2867 }
2868
2869 err = malloc(errlen); /* malloc() must succeed during parsing */
2870 errnum = read(fd, err, errlen);
2871 if (errnum != errlen) {
2872 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2873 file, linenum, args[2], args[1]);
2874 close(fd);
2875 free(err);
2876 return -1;
2877 }
2878 close(fd);
2879
2880 errnum = atol(args[1]);
2881 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2882 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002883 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002884 curproxy->errmsg[rc].str = err;
2885 curproxy->errmsg[rc].len = errlen;
2886 break;
2887 }
2888 }
2889
2890 if (rc >= HTTP_ERR_SIZE) {
2891 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2892 file, linenum, errnum);
2893 free(err);
2894 }
2895 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002897 struct cfg_kw_list *kwl;
2898 int index;
2899
2900 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2901 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2902 if (kwl->kw[index].section != CFG_LISTEN)
2903 continue;
2904 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2905 /* prepare error message just in case */
2906 snprintf(trash, sizeof(trash),
2907 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002908 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2909 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002910 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2911 return -1;
2912 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002913 else if (rc > 0) {
2914 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2915 return 0;
2916 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002917 return 0;
2918 }
2919 }
2920 }
2921
Willy Tarreau6daf3432008-01-22 16:44:08 +01002922 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002923 return -1;
2924 }
2925 return 0;
2926}
2927
2928
2929/*
2930 * This function reads and parses the configuration file given in the argument.
2931 * returns 0 if OK, -1 if error.
2932 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002933int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002935 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002936 FILE *f;
2937 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002938 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002939 int confsect = CFG_NONE;
2940
2941 struct proxy *curproxy = NULL;
2942 struct server *newsrv = NULL;
2943
2944 if ((f=fopen(file,"r")) == NULL)
2945 return -1;
2946
2947 init_default_instance();
2948
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002949 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002950 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002951 char *end;
2952 char *args[MAX_LINE_ARGS + 1];
2953 char *line = thisline;
2954
Willy Tarreaubaaee002006-06-26 02:48:02 +02002955 linenum++;
2956
2957 end = line + strlen(line);
2958
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002959 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2960 /* Check if we reached the limit and the last char is not \n.
2961 * Watch out for the last line without the terminating '\n'!
2962 */
2963 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2964 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002965 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002966 }
2967
Willy Tarreaubaaee002006-06-26 02:48:02 +02002968 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002969 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002970 line++;
2971
2972 arg = 0;
2973 args[arg] = line;
2974
2975 while (*line && arg < MAX_LINE_ARGS) {
2976 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2977 * C equivalent value. Other combinations left unchanged (eg: \1).
2978 */
2979 if (*line == '\\') {
2980 int skip = 0;
2981 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2982 *line = line[1];
2983 skip = 1;
2984 }
2985 else if (line[1] == 'r') {
2986 *line = '\r';
2987 skip = 1;
2988 }
2989 else if (line[1] == 'n') {
2990 *line = '\n';
2991 skip = 1;
2992 }
2993 else if (line[1] == 't') {
2994 *line = '\t';
2995 skip = 1;
2996 }
2997 else if (line[1] == 'x') {
2998 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2999 unsigned char hex1, hex2;
3000 hex1 = toupper(line[2]) - '0';
3001 hex2 = toupper(line[3]) - '0';
3002 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3003 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3004 *line = (hex1<<4) + hex2;
3005 skip = 3;
3006 }
3007 else {
3008 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003009 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 }
3011 }
3012 if (skip) {
3013 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3014 end -= skip;
3015 }
3016 line++;
3017 }
3018 else if (*line == '#' || *line == '\n' || *line == '\r') {
3019 /* end of string, end of loop */
3020 *line = 0;
3021 break;
3022 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003023 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003024 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003025 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003026 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003027 line++;
3028 args[++arg] = line;
3029 }
3030 else {
3031 line++;
3032 }
3033 }
3034
3035 /* empty line */
3036 if (!**args)
3037 continue;
3038
Willy Tarreau540abe42007-05-02 20:50:16 +02003039 /* zero out remaining args and ensure that at least one entry
3040 * is zeroed out.
3041 */
3042 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043 args[arg] = line;
3044 }
3045
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003046 if (!strcmp(args[0], "no")) {
3047 inv = 1;
3048 for (arg=0; *args[arg+1]; arg++)
3049 args[arg] = args[arg+1]; // shift args after inversion
3050 }
3051
3052 if (inv && strcmp(args[0], "option")) {
3053 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003054 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003055 }
3056
Willy Tarreau977b8e42006-12-29 14:19:17 +01003057 if (!strcmp(args[0], "listen") ||
3058 !strcmp(args[0], "frontend") ||
3059 !strcmp(args[0], "backend") ||
3060 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003061 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003062 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003063 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003064 cursection = strdup(args[0]);
3065 }
3066 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003068 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003069 cursection = strdup(args[0]);
3070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 /* else it's a section keyword */
3072
3073 switch (confsect) {
3074 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003075 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003076 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077 break;
3078 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003079 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003080 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 break;
3082 default:
3083 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003084 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003087 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003088 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089 fclose(f);
3090
3091 /*
3092 * Now, check for the integrity of all that we have collected.
3093 */
3094
3095 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003096 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003097
3098 if ((curproxy = proxy) == NULL) {
3099 Alert("parsing %s : no <listen> line. Nothing to do !\n",
3100 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003101 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 }
3103
3104 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003105 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003106 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003107
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003109 /* ensure we don't keep listeners uselessly bound */
3110 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003111 curproxy = curproxy->next;
3112 continue;
3113 }
3114
Willy Tarreau977b8e42006-12-29 14:19:17 +01003115 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
3116 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 +01003117 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 cfgerr++;
3119 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003120 else if (curproxy->cap & PR_CAP_BE &&
3121 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01003122 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01003123 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01003124 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
3125 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 +01003126 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127 cfgerr++;
3128 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003129
Willy Tarreau31682232007-11-29 15:38:04 +01003130 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003132 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003133 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 cfgerr++;
3135 }
3136#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
3137 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003138 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003139 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003140 cfgerr++;
3141 }
3142#endif
3143 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003144 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003145 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003146 }
3147 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003148
3149 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003151 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003152 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003153 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003155 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003156 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 }
3158 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003159 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003160 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003161 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003162 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003163 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003164 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003165 }
Willy Tarreaudf366142007-11-30 16:23:20 +01003166 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01003167 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3168 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003169
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01003170 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003171 file, proxy_type_str(curproxy), curproxy->id);
3172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003174
3175 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
3176 if ((newsrv = curproxy->srv) != NULL) {
3177 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
3178 file, proxy_type_str(curproxy), curproxy->id);
3179 }
3180 }
3181
3182 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
3184 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
3185 file, curproxy->id);
3186 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003187 }
3188 }
3189
Willy Tarreau82936582007-11-30 15:20:09 +01003190 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3191 curproxy->options &= ~PR_O_DISABLE404;
3192 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3193 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
3194 }
3195
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003196 /* if a default backend was specified, let's find it */
3197 if (curproxy->defbe.name) {
3198 struct proxy *target;
3199
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003200 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3201 if (!target) {
3202 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3203 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003204 cfgerr++;
3205 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003206 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3207 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003208 } else {
3209 free(curproxy->defbe.name);
3210 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003211 /* we force the backend to be present on at least all of
3212 * the frontend's processes.
3213 */
3214 target->bind_proc = curproxy->bind_proc ?
3215 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 }
3217 }
3218
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003219 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003220 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3221 /* map jump target for ACT_SETBE in req_rep chain */
3222 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003223 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003224 struct proxy *target;
3225
Willy Tarreaua496b602006-12-17 23:15:24 +01003226 if (exp->action != ACT_SETBE)
3227 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003228
3229 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3230 if (!target) {
3231 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3232 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003233 cfgerr++;
3234 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003235 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3236 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003237 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003238 } else {
3239 free((void *)exp->replace);
3240 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003241 /* we force the backend to be present on at least all of
3242 * the frontend's processes.
3243 */
3244 target->bind_proc = curproxy->bind_proc ?
3245 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01003246 }
3247 }
3248 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003249
3250 /* find the target proxy for 'use_backend' rules */
3251 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003252 struct proxy *target;
3253
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003254 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003255
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003256 if (!target) {
3257 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3258 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003259 cfgerr++;
3260 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003261 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3262 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003263 cfgerr++;
3264 } else {
3265 free((void *)rule->be.name);
3266 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003267 /* we force the backend to be present on at least all of
3268 * the frontend's processes.
3269 */
3270 target->bind_proc = curproxy->bind_proc ?
3271 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003272 }
3273 }
3274
Willy Tarreau2738a142006-07-08 17:28:09 +02003275 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003276 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003277 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003278 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003279 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003280 " | While not properly invalid, you will certainly encounter various problems\n"
3281 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003282 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003283 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003284 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003285
Willy Tarreau1fa31262007-12-03 00:36:16 +01003286 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3287 * We must still support older configurations, so let's find out whether those
3288 * parameters have been set or must be copied from contimeouts.
3289 */
3290 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003291 if (!curproxy->timeout.tarpit ||
3292 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003293 /* tarpit timeout not set. We search in the following order:
3294 * default.tarpit, curr.connect, default.connect.
3295 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003296 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003297 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003298 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003299 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003300 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003301 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003302 }
3303 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003304 (!curproxy->timeout.queue ||
3305 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003306 /* queue timeout not set. We search in the following order:
3307 * default.queue, curr.connect, default.connect.
3308 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003309 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003310 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003311 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003312 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003313 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003314 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003315 }
3316 }
3317
Willy Tarreauf3c69202006-07-09 16:42:34 +02003318 if (curproxy->options & PR_O_SSL3_CHK) {
3319 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3320 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3321 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3322 }
3323
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003324 /* The small pools required for the capture lists */
3325 if (curproxy->nb_req_cap)
3326 curproxy->req_cap_pool = create_pool("ptrcap",
3327 curproxy->nb_req_cap * sizeof(char *),
3328 MEM_F_SHARED);
3329 if (curproxy->nb_rsp_cap)
3330 curproxy->rsp_cap_pool = create_pool("ptrcap",
3331 curproxy->nb_rsp_cap * sizeof(char *),
3332 MEM_F_SHARED);
3333
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003334 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3335 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3336 MEM_F_SHARED);
3337
Willy Tarreau86034312006-12-29 00:10:33 +01003338 /* for backwards compatibility with "listen" instances, if
3339 * fullconn is not set but maxconn is set, then maxconn
3340 * is used.
3341 */
3342 if (!curproxy->fullconn)
3343 curproxy->fullconn = curproxy->maxconn;
3344
Willy Tarreaubaaee002006-06-26 02:48:02 +02003345 /* first, we will invert the servers list order */
3346 newsrv = NULL;
3347 while (curproxy->srv) {
3348 struct server *next;
3349
3350 next = curproxy->srv->next;
3351 curproxy->srv->next = newsrv;
3352 newsrv = curproxy->srv;
3353 if (!next)
3354 break;
3355 curproxy->srv = next;
3356 }
3357
Willy Tarreau20697042007-11-15 23:26:18 +01003358 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003359 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360
Willy Tarreaub625a082007-11-26 01:15:43 +01003361 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003362 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003363 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003364 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3365 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003366 else
3367 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003368
3369 if (curproxy->options & PR_O_LOGASAP)
3370 curproxy->to_log &= ~LW_BYTES;
3371
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003373 * ensure that we're not cross-dressing a TCP server into HTTP.
3374 */
3375 newsrv = curproxy->srv;
3376 while (newsrv != NULL) {
3377 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3378 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3379 file, proxy_type_str(curproxy), curproxy->id, linenum);
3380 goto err;
3381 }
3382 newsrv = newsrv->next;
3383 }
3384
3385 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 * If this server supports a maxconn parameter, it needs a dedicated
3387 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003388 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 */
3390 newsrv = curproxy->srv;
3391 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003392 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 /* Only 'minconn' was specified, or it was higher than or equal
3394 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3395 * this will avoid further useless expensive computations.
3396 */
3397 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003398 } else if (newsrv->maxconn && !newsrv->minconn) {
3399 /* minconn was not specified, so we set it to maxconn */
3400 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003401 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3402 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003403 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003404 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 }
3406
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003407 if (newsrv->trackit) {
3408 struct proxy *px;
3409 struct server *srv;
3410 char *pname, *sname;
3411
3412 pname = newsrv->trackit;
3413 sname = strrchr(pname, '/');
3414
3415 if (sname)
3416 *sname++ = '\0';
3417 else {
3418 sname = pname;
3419 pname = NULL;
3420 }
3421
3422 if (pname) {
3423 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3424 if (!px) {
3425 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3426 file, proxy_type_str(curproxy), curproxy->id,
3427 newsrv->id, pname);
3428 return -1;
3429 }
3430 } else
3431 px = curproxy;
3432
3433 srv = findserver(px, sname);
3434 if (!srv) {
3435 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3436 file, proxy_type_str(curproxy), curproxy->id,
3437 newsrv->id, sname);
3438 return -1;
3439 }
3440
3441 if (!(srv->state & SRV_CHECKED)) {
3442 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3443 "tracing as it does not have checks enabled.\n",
3444 file, proxy_type_str(curproxy), curproxy->id,
3445 newsrv->id, px->id, srv->id);
3446 return -1;
3447 }
3448
3449 if (curproxy != px &&
3450 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3451 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3452 "tracing: disable-on-404 option inconsistency.\n",
3453 file, proxy_type_str(curproxy), curproxy->id,
3454 newsrv->id, px->id, srv->id);
3455 return -1;
3456 }
3457
3458 newsrv->tracked = srv;
3459 newsrv->tracknext = srv->tracknext;
3460 srv->tracknext = newsrv;
3461
3462 free(newsrv->trackit);
3463 }
3464
Willy Tarreaubaaee002006-06-26 02:48:02 +02003465 newsrv = newsrv->next;
3466 }
3467
Willy Tarreaue6b98942007-10-29 01:09:36 +01003468 /* adjust this proxy's listeners */
3469 listener = curproxy->listen;
3470 while (listener) {
3471 if (curproxy->options & PR_O_TCP_NOLING)
3472 listener->options |= LI_O_NOLINGER;
3473 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003474 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003475 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003476 listener->accept = event_accept;
3477 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003478 listener->handler = process_session;
3479
3480 if (curproxy->mode == PR_MODE_HTTP)
3481 listener->analysers |= AN_REQ_HTTP_HDR;
3482
3483 if (curproxy->tcp_req.inspect_delay)
3484 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003485
3486 listener = listener->next;
3487 }
3488
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489 curproxy = curproxy->next;
3490 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003491
Willy Tarreaubaaee002006-06-26 02:48:02 +02003492 if (cfgerr > 0) {
3493 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003494 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003495 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003496
3497 /*
3498 * Recount currently required checks.
3499 */
3500
3501 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3502 int optnum;
3503
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003504 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3505 if (curproxy->options & cfg_opts[optnum].val)
3506 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003507
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003508 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3509 if (curproxy->options2 & cfg_opts2[optnum].val)
3510 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003511 }
3512
Willy Tarreaua534fea2008-08-03 12:19:50 +02003513 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003514 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003515 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003516
3517 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003518 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003519 cursection = NULL;
3520 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521}
3522
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003523/*
3524 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3525 * parsing sessions.
3526 */
3527void cfg_register_keywords(struct cfg_kw_list *kwl)
3528{
3529 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3530}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003532/*
3533 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3534 */
3535void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3536{
3537 LIST_DEL(&kwl->list);
3538 LIST_INIT(&kwl->list);
3539}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540
3541/*
3542 * Local variables:
3543 * c-indent-level: 8
3544 * c-basic-offset: 8
3545 * End:
3546 */