blob: e427a6ffdfb965f312132a4b6caf2b12683ea65b [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 }
2202
2203 curproxy->source_addr = *str2sa(args[1]);
2204 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002205
2206 cur_arg = 2;
2207 while (*(args[cur_arg])) {
2208 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002209#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2210#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002211 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2212 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2213 file, linenum, "usesrc");
2214 return -1;
2215 }
2216#endif
2217 if (!*args[cur_arg + 1]) {
2218 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2219 file, linenum, "usesrc");
2220 return -1;
2221 }
2222
2223 if (!strcmp(args[cur_arg + 1], "client")) {
2224 curproxy->options |= PR_O_TPXY_CLI;
2225 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2226 curproxy->options |= PR_O_TPXY_CIP;
2227 } else {
2228 curproxy->options |= PR_O_TPXY_ADDR;
2229 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2230 }
2231 global.last_checks |= LSTCHK_NETADM;
2232#if !defined(CONFIG_HAP_LINUX_TPROXY)
2233 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002234#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002235#else /* no TPROXY support */
2236 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002237 file, linenum, "usesrc");
2238 return -1;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002239#endif
2240 cur_arg += 2;
2241 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002242 }
2243
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002244 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2245#ifdef SO_BINDTODEVICE
2246 if (!*args[cur_arg + 1]) {
2247 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2248 file, linenum, args[0]);
2249 return -1;
2250 }
2251 if (curproxy->iface_name)
2252 free(curproxy->iface_name);
2253
2254 curproxy->iface_name = strdup(args[cur_arg + 1]);
2255 curproxy->iface_len = strlen(curproxy->iface_name);
2256 global.last_checks |= LSTCHK_NETADM;
2257#else
2258 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2259 file, linenum, args[0], args[cur_arg]);
2260 return -1;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002261#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002262 cur_arg += 2;
2263 continue;
2264 }
2265 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2266 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002267 return -1;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002269 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002270 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2271 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2272 file, linenum, "usesrc", "source");
2273 return -1;
2274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2276 regex_t *preg;
2277 if (curproxy == &defproxy) {
2278 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2279 return -1;
2280 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002281 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2282 return 0;
2283
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284 if (*(args[1]) == 0 || *(args[2]) == 0) {
2285 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2286 file, linenum, args[0]);
2287 return -1;
2288 }
2289
2290 preg = calloc(1, sizeof(regex_t));
2291 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2292 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2293 return -1;
2294 }
2295
2296 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2297 if (err) {
2298 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2299 file, linenum, *err);
2300 return -1;
2301 }
2302 }
2303 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2304 regex_t *preg;
2305 if (curproxy == &defproxy) {
2306 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2307 return -1;
2308 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002309 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2310 return 0;
2311
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 if (*(args[1]) == 0) {
2313 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2314 return -1;
2315 }
2316
2317 preg = calloc(1, sizeof(regex_t));
2318 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2319 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2320 return -1;
2321 }
2322
2323 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2324 }
2325 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2326 regex_t *preg;
2327 if (curproxy == &defproxy) {
2328 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2329 return -1;
2330 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002331 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2332 return 0;
2333
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 if (*(args[1]) == 0) {
2335 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2336 return -1;
2337 }
2338
2339 preg = calloc(1, sizeof(regex_t));
2340 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2341 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2342 return -1;
2343 }
2344
2345 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2346 }
2347 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2348 regex_t *preg;
2349 if (curproxy == &defproxy) {
2350 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2351 return -1;
2352 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002353 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2354 return 0;
2355
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 if (*(args[1]) == 0) {
2357 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2358 return -1;
2359 }
2360
2361 preg = calloc(1, sizeof(regex_t));
2362 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2363 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2364 return -1;
2365 }
2366
2367 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2368 }
2369 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2370 regex_t *preg;
2371 if (curproxy == &defproxy) {
2372 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2373 return -1;
2374 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002375 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2376 return 0;
2377
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 if (*(args[1]) == 0) {
2379 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2380 return -1;
2381 }
2382
2383 preg = calloc(1, sizeof(regex_t));
2384 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2385 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2386 return -1;
2387 }
2388
2389 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2390 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002391 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2392 regex_t *preg;
2393 if (curproxy == &defproxy) {
2394 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2395 return -1;
2396 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002397 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2398 return 0;
2399
Willy Tarreaub8750a82006-09-03 09:56:00 +02002400 if (*(args[1]) == 0) {
2401 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2402 return -1;
2403 }
2404
2405 preg = calloc(1, sizeof(regex_t));
2406 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2407 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2408 return -1;
2409 }
2410
2411 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2412 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002413 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2414 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002415 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002416 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2417 return -1;
2418 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002419 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2420 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002421
Willy Tarreau977b8e42006-12-29 14:19:17 +01002422 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002423 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2424 file, linenum, args[0]);
2425 return -1;
2426 }
2427
2428 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002429 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002430 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2431 }
2432
2433 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2434 }
2435 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2436 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002437 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002438 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2439 return -1;
2440 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002441 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2442 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002443
Willy Tarreau977b8e42006-12-29 14:19:17 +01002444 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002445 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2446 file, linenum, args[0]);
2447 return -1;
2448 }
2449
2450 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002451 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002452 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2453 }
2454
2455 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2456 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2458 regex_t *preg;
2459 if (curproxy == &defproxy) {
2460 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2461 return -1;
2462 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002463 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2464 return 0;
2465
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 if (*(args[1]) == 0 || *(args[2]) == 0) {
2467 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2468 file, linenum, args[0]);
2469 return -1;
2470 }
2471
2472 preg = calloc(1, sizeof(regex_t));
2473 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2474 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2475 return -1;
2476 }
2477
2478 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2479 if (err) {
2480 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2481 file, linenum, *err);
2482 return -1;
2483 }
2484 }
2485 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2486 regex_t *preg;
2487 if (curproxy == &defproxy) {
2488 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2489 return -1;
2490 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002491 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2492 return 0;
2493
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494 if (*(args[1]) == 0) {
2495 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2496 return -1;
2497 }
2498
2499 preg = calloc(1, sizeof(regex_t));
2500 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2501 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2502 return -1;
2503 }
2504
2505 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2506 }
2507 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2508 regex_t *preg;
2509 if (curproxy == &defproxy) {
2510 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2511 return -1;
2512 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002513 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2514 return 0;
2515
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 if (*(args[1]) == 0) {
2517 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2518 return -1;
2519 }
2520
2521 preg = calloc(1, sizeof(regex_t));
2522 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2523 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2524 return -1;
2525 }
2526
2527 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2528 }
2529 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2530 regex_t *preg;
2531 if (curproxy == &defproxy) {
2532 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2533 return -1;
2534 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002535 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2536 return 0;
2537
Willy Tarreaubaaee002006-06-26 02:48:02 +02002538 if (*(args[1]) == 0) {
2539 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2540 return -1;
2541 }
2542
2543 preg = calloc(1, sizeof(regex_t));
2544 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2545 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2546 return -1;
2547 }
2548
2549 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2550 }
2551 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2552 regex_t *preg;
2553 if (curproxy == &defproxy) {
2554 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2555 return -1;
2556 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002557 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2558 return 0;
2559
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 if (*(args[1]) == 0) {
2561 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2562 return -1;
2563 }
2564
2565 preg = calloc(1, sizeof(regex_t));
2566 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2567 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2568 return -1;
2569 }
2570
2571 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2572 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002573 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2574 regex_t *preg;
2575 if (curproxy == &defproxy) {
2576 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2577 return -1;
2578 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002579 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2580 return 0;
2581
Willy Tarreaub8750a82006-09-03 09:56:00 +02002582 if (*(args[1]) == 0) {
2583 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2584 return -1;
2585 }
2586
2587 preg = calloc(1, sizeof(regex_t));
2588 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2589 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2590 return -1;
2591 }
2592
2593 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2594 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2596 if (curproxy == &defproxy) {
2597 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2598 return -1;
2599 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002600 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2601 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602
2603 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2604 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2605 return 0;
2606 }
2607
2608 if (*(args[1]) == 0) {
2609 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2610 return -1;
2611 }
2612
2613 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2614 }
2615 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2616 regex_t *preg;
2617
2618 if (*(args[1]) == 0 || *(args[2]) == 0) {
2619 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2620 file, linenum, args[0]);
2621 return -1;
2622 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002623 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2624 return 0;
2625
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626 preg = calloc(1, sizeof(regex_t));
2627 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2628 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2629 return -1;
2630 }
2631
2632 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2633 if (err) {
2634 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2635 file, linenum, *err);
2636 return -1;
2637 }
2638 }
2639 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2640 regex_t *preg;
2641 if (curproxy == &defproxy) {
2642 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2643 return -1;
2644 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002645 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2646 return 0;
2647
Willy Tarreaubaaee002006-06-26 02:48:02 +02002648 if (*(args[1]) == 0) {
2649 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2650 return -1;
2651 }
2652
2653 preg = calloc(1, sizeof(regex_t));
2654 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2655 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2656 return -1;
2657 }
2658
2659 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2660 if (err) {
2661 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2662 file, linenum, *err);
2663 return -1;
2664 }
2665 }
2666 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2667 regex_t *preg;
2668 if (curproxy == &defproxy) {
2669 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2670 return -1;
2671 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002672 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2673 return 0;
2674
Willy Tarreaubaaee002006-06-26 02:48:02 +02002675 if (*(args[1]) == 0) {
2676 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2677 return -1;
2678 }
2679
2680 preg = calloc(1, sizeof(regex_t));
2681 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2682 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2683 return -1;
2684 }
2685
2686 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2687 if (err) {
2688 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2689 file, linenum, *err);
2690 return -1;
2691 }
2692 }
2693 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2694 regex_t *preg;
2695 if (curproxy == &defproxy) {
2696 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2697 return -1;
2698 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002699 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2700 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002701
2702 if (*(args[1]) == 0 || *(args[2]) == 0) {
2703 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2704 file, linenum, args[0]);
2705 return -1;
2706 }
2707
2708 preg = calloc(1, sizeof(regex_t));
2709 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2710 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2711 return -1;
2712 }
2713
2714 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2715 if (err) {
2716 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2717 file, linenum, *err);
2718 return -1;
2719 }
2720 }
2721 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2722 regex_t *preg;
2723 if (curproxy == &defproxy) {
2724 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2725 return -1;
2726 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002727 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2728 return 0;
2729
Willy Tarreaubaaee002006-06-26 02:48:02 +02002730 if (*(args[1]) == 0) {
2731 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2732 return -1;
2733 }
2734
2735 preg = calloc(1, sizeof(regex_t));
2736 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2737 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2738 return -1;
2739 }
2740
2741 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2742 if (err) {
2743 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2744 file, linenum, *err);
2745 return -1;
2746 }
2747 }
2748 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2749 regex_t *preg;
2750 if (curproxy == &defproxy) {
2751 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2752 return -1;
2753 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002754 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2755 return 0;
2756
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 if (*(args[1]) == 0) {
2758 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2759 return -1;
2760 }
2761
2762 preg = calloc(1, sizeof(regex_t));
2763 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2764 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2765 return -1;
2766 }
2767
2768 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2769 if (err) {
2770 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2771 file, linenum, *err);
2772 return -1;
2773 }
2774 }
2775 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2776 if (curproxy == &defproxy) {
2777 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2778 return -1;
2779 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002780 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2781 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782
2783 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2784 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2785 return 0;
2786 }
2787
2788 if (*(args[1]) == 0) {
2789 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2790 return -1;
2791 }
2792
2793 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2794 }
2795 else if (!strcmp(args[0], "errorloc") ||
2796 !strcmp(args[0], "errorloc302") ||
2797 !strcmp(args[0], "errorloc303")) { /* error location */
2798 int errnum, errlen;
2799 char *err;
2800
Willy Tarreau977b8e42006-12-29 14:19:17 +01002801 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2802 return 0;
2803
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002805 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002806 return -1;
2807 }
2808
2809 errnum = atol(args[1]);
2810 if (!strcmp(args[0], "errorloc303")) {
2811 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2812 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2813 } else {
2814 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2815 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2816 }
2817
Willy Tarreau0f772532006-12-23 20:51:41 +01002818 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2819 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002820 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002821 curproxy->errmsg[rc].str = err;
2822 curproxy->errmsg[rc].len = errlen;
2823 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002824 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002825 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002826
2827 if (rc >= HTTP_ERR_SIZE) {
2828 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2829 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002830 free(err);
2831 }
2832 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002833 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2834 int errnum, errlen, fd;
2835 char *err;
2836 struct stat stat;
2837
2838 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2839 return 0;
2840
2841 if (*(args[2]) == 0) {
2842 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2843 return -1;
2844 }
2845
2846 fd = open(args[2], O_RDONLY);
2847 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2848 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2849 file, linenum, args[2], args[1]);
2850 if (fd >= 0)
2851 close(fd);
2852 return -1;
2853 }
2854
2855 if (stat.st_size <= BUFSIZE) {
2856 errlen = stat.st_size;
2857 } else {
2858 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2859 file, linenum, args[2], BUFSIZE);
2860 errlen = BUFSIZE;
2861 }
2862
2863 err = malloc(errlen); /* malloc() must succeed during parsing */
2864 errnum = read(fd, err, errlen);
2865 if (errnum != errlen) {
2866 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2867 file, linenum, args[2], args[1]);
2868 close(fd);
2869 free(err);
2870 return -1;
2871 }
2872 close(fd);
2873
2874 errnum = atol(args[1]);
2875 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2876 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002877 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002878 curproxy->errmsg[rc].str = err;
2879 curproxy->errmsg[rc].len = errlen;
2880 break;
2881 }
2882 }
2883
2884 if (rc >= HTTP_ERR_SIZE) {
2885 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2886 file, linenum, errnum);
2887 free(err);
2888 }
2889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002891 struct cfg_kw_list *kwl;
2892 int index;
2893
2894 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2895 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2896 if (kwl->kw[index].section != CFG_LISTEN)
2897 continue;
2898 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2899 /* prepare error message just in case */
2900 snprintf(trash, sizeof(trash),
2901 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002902 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2903 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002904 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2905 return -1;
2906 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002907 else if (rc > 0) {
2908 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2909 return 0;
2910 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002911 return 0;
2912 }
2913 }
2914 }
2915
Willy Tarreau6daf3432008-01-22 16:44:08 +01002916 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002917 return -1;
2918 }
2919 return 0;
2920}
2921
2922
2923/*
2924 * This function reads and parses the configuration file given in the argument.
2925 * returns 0 if OK, -1 if error.
2926 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002927int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002929 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002930 FILE *f;
2931 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002932 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002933 int confsect = CFG_NONE;
2934
2935 struct proxy *curproxy = NULL;
2936 struct server *newsrv = NULL;
2937
2938 if ((f=fopen(file,"r")) == NULL)
2939 return -1;
2940
2941 init_default_instance();
2942
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002943 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002944 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002945 char *end;
2946 char *args[MAX_LINE_ARGS + 1];
2947 char *line = thisline;
2948
Willy Tarreaubaaee002006-06-26 02:48:02 +02002949 linenum++;
2950
2951 end = line + strlen(line);
2952
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002953 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2954 /* Check if we reached the limit and the last char is not \n.
2955 * Watch out for the last line without the terminating '\n'!
2956 */
2957 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2958 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002959 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002960 }
2961
Willy Tarreaubaaee002006-06-26 02:48:02 +02002962 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002963 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002964 line++;
2965
2966 arg = 0;
2967 args[arg] = line;
2968
2969 while (*line && arg < MAX_LINE_ARGS) {
2970 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2971 * C equivalent value. Other combinations left unchanged (eg: \1).
2972 */
2973 if (*line == '\\') {
2974 int skip = 0;
2975 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2976 *line = line[1];
2977 skip = 1;
2978 }
2979 else if (line[1] == 'r') {
2980 *line = '\r';
2981 skip = 1;
2982 }
2983 else if (line[1] == 'n') {
2984 *line = '\n';
2985 skip = 1;
2986 }
2987 else if (line[1] == 't') {
2988 *line = '\t';
2989 skip = 1;
2990 }
2991 else if (line[1] == 'x') {
2992 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2993 unsigned char hex1, hex2;
2994 hex1 = toupper(line[2]) - '0';
2995 hex2 = toupper(line[3]) - '0';
2996 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2997 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2998 *line = (hex1<<4) + hex2;
2999 skip = 3;
3000 }
3001 else {
3002 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003003 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 }
3005 }
3006 if (skip) {
3007 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3008 end -= skip;
3009 }
3010 line++;
3011 }
3012 else if (*line == '#' || *line == '\n' || *line == '\r') {
3013 /* end of string, end of loop */
3014 *line = 0;
3015 break;
3016 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003017 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003019 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003020 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 line++;
3022 args[++arg] = line;
3023 }
3024 else {
3025 line++;
3026 }
3027 }
3028
3029 /* empty line */
3030 if (!**args)
3031 continue;
3032
Willy Tarreau540abe42007-05-02 20:50:16 +02003033 /* zero out remaining args and ensure that at least one entry
3034 * is zeroed out.
3035 */
3036 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037 args[arg] = line;
3038 }
3039
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003040 if (!strcmp(args[0], "no")) {
3041 inv = 1;
3042 for (arg=0; *args[arg+1]; arg++)
3043 args[arg] = args[arg+1]; // shift args after inversion
3044 }
3045
3046 if (inv && strcmp(args[0], "option")) {
3047 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003048 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003049 }
3050
Willy Tarreau977b8e42006-12-29 14:19:17 +01003051 if (!strcmp(args[0], "listen") ||
3052 !strcmp(args[0], "frontend") ||
3053 !strcmp(args[0], "backend") ||
3054 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003055 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003057 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003058 cursection = strdup(args[0]);
3059 }
3060 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003062 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003063 cursection = strdup(args[0]);
3064 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003065 /* else it's a section keyword */
3066
3067 switch (confsect) {
3068 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003069 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003070 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 break;
3072 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003073 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003074 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075 break;
3076 default:
3077 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003078 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003081 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003082 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 fclose(f);
3084
3085 /*
3086 * Now, check for the integrity of all that we have collected.
3087 */
3088
3089 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003090 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003091
3092 if ((curproxy = proxy) == NULL) {
3093 Alert("parsing %s : no <listen> line. Nothing to do !\n",
3094 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003095 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096 }
3097
3098 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003099 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003100 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003101
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003103 /* ensure we don't keep listeners uselessly bound */
3104 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105 curproxy = curproxy->next;
3106 continue;
3107 }
3108
Willy Tarreau977b8e42006-12-29 14:19:17 +01003109 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
3110 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 +01003111 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 cfgerr++;
3113 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003114 else if (curproxy->cap & PR_CAP_BE &&
3115 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01003116 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01003117 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01003118 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
3119 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 +01003120 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 cfgerr++;
3122 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003123
Willy Tarreau31682232007-11-29 15:38:04 +01003124 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003126 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003127 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003128 cfgerr++;
3129 }
3130#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
3131 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003132 Alert("parsing %s : %s '%s' needs at least 1 server in 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#endif
3137 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003138 Warning("parsing %s : dispatch address of %s '%s' will be ignored 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 }
3141 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003142
3143 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003145 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003146 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003149 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003150 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151 }
3152 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003153 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003154 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003156 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003157 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003158 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003159 }
Willy Tarreaudf366142007-11-30 16:23:20 +01003160 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01003161 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3162 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003163
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01003164 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003165 file, proxy_type_str(curproxy), curproxy->id);
3166 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003168
3169 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
3170 if ((newsrv = curproxy->srv) != NULL) {
3171 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
3172 file, proxy_type_str(curproxy), curproxy->id);
3173 }
3174 }
3175
3176 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003177 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
3178 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
3179 file, curproxy->id);
3180 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003181 }
3182 }
3183
Willy Tarreau82936582007-11-30 15:20:09 +01003184 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3185 curproxy->options &= ~PR_O_DISABLE404;
3186 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3187 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
3188 }
3189
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003190 /* if a default backend was specified, let's find it */
3191 if (curproxy->defbe.name) {
3192 struct proxy *target;
3193
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003194 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3195 if (!target) {
3196 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3197 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003198 cfgerr++;
3199 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003200 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3201 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003202 } else {
3203 free(curproxy->defbe.name);
3204 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003205 /* we force the backend to be present on at least all of
3206 * the frontend's processes.
3207 */
3208 target->bind_proc = curproxy->bind_proc ?
3209 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 }
3211 }
3212
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003213 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003214 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3215 /* map jump target for ACT_SETBE in req_rep chain */
3216 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003217 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003218 struct proxy *target;
3219
Willy Tarreaua496b602006-12-17 23:15:24 +01003220 if (exp->action != ACT_SETBE)
3221 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003222
3223 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3224 if (!target) {
3225 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3226 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003227 cfgerr++;
3228 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003229 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3230 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003231 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003232 } else {
3233 free((void *)exp->replace);
3234 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003235 /* we force the backend to be present on at least all of
3236 * the frontend's processes.
3237 */
3238 target->bind_proc = curproxy->bind_proc ?
3239 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01003240 }
3241 }
3242 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003243
3244 /* find the target proxy for 'use_backend' rules */
3245 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003246 struct proxy *target;
3247
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003248 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003249
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003250 if (!target) {
3251 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3252 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003253 cfgerr++;
3254 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003255 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3256 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003257 cfgerr++;
3258 } else {
3259 free((void *)rule->be.name);
3260 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003261 /* we force the backend to be present on at least all of
3262 * the frontend's processes.
3263 */
3264 target->bind_proc = curproxy->bind_proc ?
3265 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003266 }
3267 }
3268
Willy Tarreau2738a142006-07-08 17:28:09 +02003269 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003270 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003271 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003272 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003273 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003274 " | While not properly invalid, you will certainly encounter various problems\n"
3275 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003276 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003277 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003278 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003279
Willy Tarreau1fa31262007-12-03 00:36:16 +01003280 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3281 * We must still support older configurations, so let's find out whether those
3282 * parameters have been set or must be copied from contimeouts.
3283 */
3284 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003285 if (!curproxy->timeout.tarpit ||
3286 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003287 /* tarpit timeout not set. We search in the following order:
3288 * default.tarpit, curr.connect, default.connect.
3289 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003290 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003291 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003292 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003293 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003294 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003295 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003296 }
3297 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003298 (!curproxy->timeout.queue ||
3299 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003300 /* queue timeout not set. We search in the following order:
3301 * default.queue, curr.connect, default.connect.
3302 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003303 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003304 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003305 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003306 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003307 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003308 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003309 }
3310 }
3311
Willy Tarreauf3c69202006-07-09 16:42:34 +02003312 if (curproxy->options & PR_O_SSL3_CHK) {
3313 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3314 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3315 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3316 }
3317
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003318 /* The small pools required for the capture lists */
3319 if (curproxy->nb_req_cap)
3320 curproxy->req_cap_pool = create_pool("ptrcap",
3321 curproxy->nb_req_cap * sizeof(char *),
3322 MEM_F_SHARED);
3323 if (curproxy->nb_rsp_cap)
3324 curproxy->rsp_cap_pool = create_pool("ptrcap",
3325 curproxy->nb_rsp_cap * sizeof(char *),
3326 MEM_F_SHARED);
3327
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003328 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3329 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3330 MEM_F_SHARED);
3331
Willy Tarreau86034312006-12-29 00:10:33 +01003332 /* for backwards compatibility with "listen" instances, if
3333 * fullconn is not set but maxconn is set, then maxconn
3334 * is used.
3335 */
3336 if (!curproxy->fullconn)
3337 curproxy->fullconn = curproxy->maxconn;
3338
Willy Tarreaubaaee002006-06-26 02:48:02 +02003339 /* first, we will invert the servers list order */
3340 newsrv = NULL;
3341 while (curproxy->srv) {
3342 struct server *next;
3343
3344 next = curproxy->srv->next;
3345 curproxy->srv->next = newsrv;
3346 newsrv = curproxy->srv;
3347 if (!next)
3348 break;
3349 curproxy->srv = next;
3350 }
3351
Willy Tarreau20697042007-11-15 23:26:18 +01003352 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003353 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003354
Willy Tarreaub625a082007-11-26 01:15:43 +01003355 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003356 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003357 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003358 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3359 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003360 else
3361 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362
3363 if (curproxy->options & PR_O_LOGASAP)
3364 curproxy->to_log &= ~LW_BYTES;
3365
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003367 * ensure that we're not cross-dressing a TCP server into HTTP.
3368 */
3369 newsrv = curproxy->srv;
3370 while (newsrv != NULL) {
3371 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3372 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3373 file, proxy_type_str(curproxy), curproxy->id, linenum);
3374 goto err;
3375 }
3376 newsrv = newsrv->next;
3377 }
3378
3379 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003380 * If this server supports a maxconn parameter, it needs a dedicated
3381 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003382 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003383 */
3384 newsrv = curproxy->srv;
3385 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003386 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 /* Only 'minconn' was specified, or it was higher than or equal
3388 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3389 * this will avoid further useless expensive computations.
3390 */
3391 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003392 } else if (newsrv->maxconn && !newsrv->minconn) {
3393 /* minconn was not specified, so we set it to maxconn */
3394 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003395 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3396 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003397 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003398 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 }
3400
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003401 if (newsrv->trackit) {
3402 struct proxy *px;
3403 struct server *srv;
3404 char *pname, *sname;
3405
3406 pname = newsrv->trackit;
3407 sname = strrchr(pname, '/');
3408
3409 if (sname)
3410 *sname++ = '\0';
3411 else {
3412 sname = pname;
3413 pname = NULL;
3414 }
3415
3416 if (pname) {
3417 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3418 if (!px) {
3419 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3420 file, proxy_type_str(curproxy), curproxy->id,
3421 newsrv->id, pname);
3422 return -1;
3423 }
3424 } else
3425 px = curproxy;
3426
3427 srv = findserver(px, sname);
3428 if (!srv) {
3429 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3430 file, proxy_type_str(curproxy), curproxy->id,
3431 newsrv->id, sname);
3432 return -1;
3433 }
3434
3435 if (!(srv->state & SRV_CHECKED)) {
3436 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3437 "tracing as it does not have checks enabled.\n",
3438 file, proxy_type_str(curproxy), curproxy->id,
3439 newsrv->id, px->id, srv->id);
3440 return -1;
3441 }
3442
3443 if (curproxy != px &&
3444 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3445 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3446 "tracing: disable-on-404 option inconsistency.\n",
3447 file, proxy_type_str(curproxy), curproxy->id,
3448 newsrv->id, px->id, srv->id);
3449 return -1;
3450 }
3451
3452 newsrv->tracked = srv;
3453 newsrv->tracknext = srv->tracknext;
3454 srv->tracknext = newsrv;
3455
3456 free(newsrv->trackit);
3457 }
3458
Willy Tarreaubaaee002006-06-26 02:48:02 +02003459 newsrv = newsrv->next;
3460 }
3461
Willy Tarreaue6b98942007-10-29 01:09:36 +01003462 /* adjust this proxy's listeners */
3463 listener = curproxy->listen;
3464 while (listener) {
3465 if (curproxy->options & PR_O_TCP_NOLING)
3466 listener->options |= LI_O_NOLINGER;
3467 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003468 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003469 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003470 listener->accept = event_accept;
3471 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003472 listener->handler = process_session;
3473
3474 if (curproxy->mode == PR_MODE_HTTP)
3475 listener->analysers |= AN_REQ_HTTP_HDR;
3476
3477 if (curproxy->tcp_req.inspect_delay)
3478 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003479
3480 listener = listener->next;
3481 }
3482
Willy Tarreaubaaee002006-06-26 02:48:02 +02003483 curproxy = curproxy->next;
3484 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003485
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 if (cfgerr > 0) {
3487 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003488 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003490
3491 /*
3492 * Recount currently required checks.
3493 */
3494
3495 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3496 int optnum;
3497
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003498 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3499 if (curproxy->options & cfg_opts[optnum].val)
3500 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003501
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003502 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3503 if (curproxy->options2 & cfg_opts2[optnum].val)
3504 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003505 }
3506
Willy Tarreaua534fea2008-08-03 12:19:50 +02003507 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003508 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003509 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003510
3511 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003512 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003513 cursection = NULL;
3514 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003515}
3516
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003517/*
3518 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3519 * parsing sessions.
3520 */
3521void cfg_register_keywords(struct cfg_kw_list *kwl)
3522{
3523 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3524}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003525
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003526/*
3527 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3528 */
3529void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3530{
3531 LIST_DEL(&kwl->list);
3532 LIST_INIT(&kwl->list);
3533}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003534
3535/*
3536 * Local variables:
3537 * c-indent-level: 8
3538 * c-basic-offset: 8
3539 * End:
3540 */