blob: e5d684002d8e21e0f14fe29ed5760cd1622f4e47 [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) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100132int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
133unsigned int acl_seen = 0; /* CFG_ACL_* */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200134
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200135/* List head of all known configuration keywords */
136static struct cfg_kw_list cfg_keywords = {
137 .list = LIST_HEAD_INIT(cfg_keywords.list)
138};
139
Willy Tarreaubaaee002006-06-26 02:48:02 +0200140/*
141 * converts <str> to a list of listeners which are dynamically allocated.
142 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
143 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
144 * - <port> is a numerical port from 1 to 65535 ;
145 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
146 * This can be repeated as many times as necessary, separated by a coma.
147 * The <tail> argument is a pointer to a current list which should be appended
148 * to the tail of the new list. The pointer to the new list is returned.
149 */
150static struct listener *str2listener(char *str, struct listener *tail)
151{
152 struct listener *l;
153 char *c, *next, *range, *dupstr;
154 int port, end;
155
156 next = dupstr = strdup(str);
157
158 while (next && *next) {
159 struct sockaddr_storage ss;
160
161 str = next;
162 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100163 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200164 *next++ = 0;
165 }
166
167 /* 2) look for the addr/port delimiter, it's the last colon. */
168 if ((range = strrchr(str, ':')) == NULL) {
169 Alert("Missing port number: '%s'\n", str);
170 goto fail;
171 }
172
173 *range++ = 0;
174
175 if (strrchr(str, ':') != NULL) {
176 /* IPv6 address contains ':' */
177 memset(&ss, 0, sizeof(ss));
178 ss.ss_family = AF_INET6;
179
180 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
181 Alert("Invalid server address: '%s'\n", str);
182 goto fail;
183 }
184 }
185 else {
186 memset(&ss, 0, sizeof(ss));
187 ss.ss_family = AF_INET;
188
189 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
190 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
191 }
192 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
193 struct hostent *he;
194
195 if ((he = gethostbyname(str)) == NULL) {
196 Alert("Invalid server name: '%s'\n", str);
197 goto fail;
198 }
199 else
200 ((struct sockaddr_in *)&ss)->sin_addr =
201 *(struct in_addr *) *(he->h_addr_list);
202 }
203 }
204
205 /* 3) look for the port-end delimiter */
206 if ((c = strchr(range, '-')) != NULL) {
207 *c++ = 0;
208 end = atol(c);
209 }
210 else {
211 end = atol(range);
212 }
213
214 port = atol(range);
215
216 if (port < 1 || port > 65535) {
217 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
218 goto fail;
219 }
220
221 if (end < 1 || end > 65535) {
222 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
223 goto fail;
224 }
225
226 for (; port <= end; port++) {
227 l = (struct listener *)calloc(1, sizeof(struct listener));
228 l->next = tail;
229 tail = l;
230
231 l->fd = -1;
232 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100233 l->state = LI_INIT;
234
235 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100237 tcpv6_add_listener(l);
238 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100240 tcpv4_add_listener(l);
241 }
242 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 } /* end for(port) */
244 } /* end while(next) */
245 free(dupstr);
246 return tail;
247 fail:
248 free(dupstr);
249 return NULL;
250}
251
Willy Tarreau977b8e42006-12-29 14:19:17 +0100252/*
253 * Sends a warning if proxy <proxy> does not have at least one of the
254 * capabilities in <cap>. An optionnal <hint> may be added at the end
255 * of the warning to help the user. Returns 1 if a warning was emitted
256 * or 0 if the condition is valid.
257 */
258int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
259{
260 char *msg;
261
262 switch (cap) {
263 case PR_CAP_BE: msg = "no backend"; break;
264 case PR_CAP_FE: msg = "no frontend"; break;
265 case PR_CAP_RS: msg = "no ruleset"; break;
266 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
267 default: msg = "not enough"; break;
268 }
269
270 if (!(proxy->cap & cap)) {
271 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100272 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100273 return 1;
274 }
275 return 0;
276}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200277
278/*
279 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
280 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100281int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200282{
283
284 if (!strcmp(args[0], "global")) { /* new section */
285 /* no option, nothing special to do */
286 return 0;
287 }
288 else if (!strcmp(args[0], "daemon")) {
289 global.mode |= MODE_DAEMON;
290 }
291 else if (!strcmp(args[0], "debug")) {
292 global.mode |= MODE_DEBUG;
293 }
294 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100295 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200297 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100298 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200299 }
300 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100301 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200302 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200303 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100304 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200305 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100306 else if (!strcmp(args[0], "nosplice")) {
307 global.tune.options &= ~GTUNE_USE_SPLICE;
308 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200309 else if (!strcmp(args[0], "quiet")) {
310 global.mode |= MODE_QUIET;
311 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200312 else if (!strcmp(args[0], "tune.maxpollevents")) {
313 if (global.tune.maxpollevents != 0) {
314 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
315 return 0;
316 }
317 if (*(args[1]) == 0) {
318 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
319 return -1;
320 }
321 global.tune.maxpollevents = atol(args[1]);
322 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100323 else if (!strcmp(args[0], "tune.maxaccept")) {
324 if (global.tune.maxaccept != 0) {
325 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
326 return 0;
327 }
328 if (*(args[1]) == 0) {
329 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
330 return -1;
331 }
332 global.tune.maxaccept = atol(args[1]);
333 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200334 else if (!strcmp(args[0], "uid")) {
335 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200336 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200337 return 0;
338 }
339 if (*(args[1]) == 0) {
340 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
341 return -1;
342 }
343 global.uid = atol(args[1]);
344 }
345 else if (!strcmp(args[0], "gid")) {
346 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200347 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200348 return 0;
349 }
350 if (*(args[1]) == 0) {
351 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
352 return -1;
353 }
354 global.gid = atol(args[1]);
355 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200356 /* user/group name handling */
357 else if (!strcmp(args[0], "user")) {
358 struct passwd *ha_user;
359 if (global.uid != 0) {
360 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
361 return 0;
362 }
363 errno = 0;
364 ha_user = getpwnam(args[1]);
365 if (ha_user != NULL) {
366 global.uid = (int)ha_user->pw_uid;
367 }
368 else {
369 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
370 exit(1);
371 }
372 }
373 else if (!strcmp(args[0], "group")) {
374 struct group *ha_group;
375 if (global.gid != 0) {
376 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
377 return 0;
378 }
379 errno = 0;
380 ha_group = getgrnam(args[1]);
381 if (ha_group != NULL) {
382 global.gid = (int)ha_group->gr_gid;
383 }
384 else {
385 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
386 exit(1);
387 }
388 }
389 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200390 else if (!strcmp(args[0], "nbproc")) {
391 if (global.nbproc != 0) {
392 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
393 return 0;
394 }
395 if (*(args[1]) == 0) {
396 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
397 return -1;
398 }
399 global.nbproc = atol(args[1]);
400 }
401 else if (!strcmp(args[0], "maxconn")) {
402 if (global.maxconn != 0) {
403 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
404 return 0;
405 }
406 if (*(args[1]) == 0) {
407 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
408 return -1;
409 }
410 global.maxconn = atol(args[1]);
411#ifdef SYSTEM_MAXCONN
412 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
413 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);
414 global.maxconn = DEFAULT_MAXCONN;
415 }
416#endif /* SYSTEM_MAXCONN */
417 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100418 else if (!strcmp(args[0], "maxpipes")) {
419 if (global.maxpipes != 0) {
420 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
421 return 0;
422 }
423 if (*(args[1]) == 0) {
424 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
425 return -1;
426 }
427 global.maxpipes = atol(args[1]);
428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200429 else if (!strcmp(args[0], "ulimit-n")) {
430 if (global.rlimit_nofile != 0) {
431 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
432 return 0;
433 }
434 if (*(args[1]) == 0) {
435 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
436 return -1;
437 }
438 global.rlimit_nofile = atol(args[1]);
439 }
440 else if (!strcmp(args[0], "chroot")) {
441 if (global.chroot != NULL) {
442 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
443 return 0;
444 }
445 if (*(args[1]) == 0) {
446 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
447 return -1;
448 }
449 global.chroot = strdup(args[1]);
450 }
451 else if (!strcmp(args[0], "pidfile")) {
452 if (global.pidfile != NULL) {
453 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
454 return 0;
455 }
456 if (*(args[1]) == 0) {
457 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
458 return -1;
459 }
460 global.pidfile = strdup(args[1]);
461 }
462 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100463 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200464 int facility, level;
465
466 if (*(args[1]) == 0 || *(args[2]) == 0) {
467 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
468 return -1;
469 }
470
471 facility = get_log_facility(args[2]);
472 if (facility < 0) {
473 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
474 exit(1);
475 }
476
477 level = 7; /* max syslog level = debug */
478 if (*(args[3])) {
479 level = get_log_level(args[3]);
480 if (level < 0) {
481 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
482 exit(1);
483 }
484 }
485
Robert Tsai81ae1952007-12-05 10:47:29 +0100486 if (args[1][0] == '/') {
487 logsrv.u.addr.sa_family = AF_UNIX;
488 logsrv.u.un = *str2sun(args[1]);
489 } else {
490 logsrv.u.addr.sa_family = AF_INET;
491 logsrv.u.in = *str2sa(args[1]);
492 if (!logsrv.u.in.sin_port)
493 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200495
496 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100497 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200498 global.logfac1 = facility;
499 global.loglev1 = level;
500 }
501 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100502 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200503 global.logfac2 = facility;
504 global.loglev2 = level;
505 }
506 else {
507 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
508 return -1;
509 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200510 }
511 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
512 if (global.spread_checks != 0) {
513 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
514 return 0;
515 }
516 if (*(args[1]) == 0) {
517 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
518 return -1;
519 }
520 global.spread_checks = atol(args[1]);
521 if (global.spread_checks < 0 || global.spread_checks > 50) {
522 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
523 return -1;
524 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200525 }
526 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200527 struct cfg_kw_list *kwl;
528 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200529 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200530
531 list_for_each_entry(kwl, &cfg_keywords.list, list) {
532 for (index = 0; kwl->kw[index].kw != NULL; index++) {
533 if (kwl->kw[index].section != CFG_GLOBAL)
534 continue;
535 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
536 /* prepare error message just in case */
537 snprintf(trash, sizeof(trash),
538 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200539 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
540 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200541 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
542 return -1;
543 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200544 else if (rc > 0) {
545 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
546 return 0;
547 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200548 return 0;
549 }
550 }
551 }
552
Willy Tarreaubaaee002006-06-26 02:48:02 +0200553 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
554 return -1;
555 }
556 return 0;
557}
558
559
560static void init_default_instance()
561{
562 memset(&defproxy, 0, sizeof(defproxy));
563 defproxy.mode = PR_MODE_TCP;
564 defproxy.state = PR_STNEW;
565 defproxy.maxconn = cfg_maxpconn;
566 defproxy.conn_retries = CONN_RETRIES;
567 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200568
569 LIST_INIT(&defproxy.pendconns);
570 LIST_INIT(&defproxy.acl);
571 LIST_INIT(&defproxy.block_cond);
572 LIST_INIT(&defproxy.mon_fail_cond);
573 LIST_INIT(&defproxy.switching_rules);
574
Willy Tarreau3a70f942008-02-15 11:15:34 +0100575 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200576}
577
578/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100579 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
580 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100582int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200583{
584 static struct proxy *curproxy = NULL;
585 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200586 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100587 int rc;
588 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589
Willy Tarreau977b8e42006-12-29 14:19:17 +0100590 if (!strcmp(args[0], "listen"))
591 rc = PR_CAP_LISTEN;
592 else if (!strcmp(args[0], "frontend"))
593 rc = PR_CAP_FE | PR_CAP_RS;
594 else if (!strcmp(args[0], "backend"))
595 rc = PR_CAP_BE | PR_CAP_RS;
596 else if (!strcmp(args[0], "ruleset"))
597 rc = PR_CAP_RS;
598 else
599 rc = PR_CAP_NONE;
600
601 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 if (!*args[1]) {
603 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
604 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
605 file, linenum, args[0]);
606 return -1;
607 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200608
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100609 err = invalid_char(args[1]);
610 if (err) {
611 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
612 file, linenum, *err, args[0], args[1]);
613 return -1;
614 }
615
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200616 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
617 /*
618 * If there are two proxies with the same name only following
619 * combinations are allowed:
620 *
621 * listen backend frontend ruleset
622 * listen - - - -
623 * backend - - OK -
624 * frontend - OK - -
625 * ruleset - - - -
626 */
627
628 if (!strcmp(curproxy->id, args[1]) &&
629 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
630 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100631 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
632 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200633 }
634 }
635
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
637 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
638 return -1;
639 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100640
641 acl_seen = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 curproxy->next = proxy;
643 proxy = curproxy;
644 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200645 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200646 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200647 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100648 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200649 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200650 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200651
Willy Tarreauee991362007-05-14 14:37:50 +0200652 /* Timeouts are defined as -1, so we cannot use the zeroed area
653 * as a default value.
654 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100655 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200656
657 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100659 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200660
661 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100662 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200663 curproxy->listen = str2listener(args[2], curproxy->listen);
664 if (!curproxy->listen)
665 return -1;
666 global.maxsock++;
667 }
668
669 /* set default values */
670 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100672 curproxy->options2 = defproxy.options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100673 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100674 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200675 curproxy->except_net = defproxy.except_net;
676 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200678 if (defproxy.fwdfor_hdr_len) {
679 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
680 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
681 }
682
Willy Tarreau977b8e42006-12-29 14:19:17 +0100683 if (curproxy->cap & PR_CAP_FE) {
684 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100685 curproxy->backlog = defproxy.backlog;
Willy Tarreau39af0f62009-03-07 11:53:44 +0100686 curproxy->fe_maxsps = defproxy.fe_maxsps;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100687
688 /* initialize error relocations */
689 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
690 if (defproxy.errmsg[rc].str)
691 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
692 }
693
694 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
695 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696
Willy Tarreau977b8e42006-12-29 14:19:17 +0100697 if (curproxy->cap & PR_CAP_BE) {
698 curproxy->fullconn = defproxy.fullconn;
699 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700
Willy Tarreau977b8e42006-12-29 14:19:17 +0100701 if (defproxy.check_req)
702 curproxy->check_req = strdup(defproxy.check_req);
703 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200704
Willy Tarreau977b8e42006-12-29 14:19:17 +0100705 if (defproxy.cookie_name)
706 curproxy->cookie_name = strdup(defproxy.cookie_name);
707 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100708
709 if (defproxy.url_param_name)
710 curproxy->url_param_name = strdup(defproxy.url_param_name);
711 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100712
713 if (defproxy.iface_name)
714 curproxy->iface_name = strdup(defproxy.iface_name);
715 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100716 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200717
Willy Tarreau977b8e42006-12-29 14:19:17 +0100718 if (curproxy->cap & PR_CAP_RS) {
719 if (defproxy.capture_name)
720 curproxy->capture_name = strdup(defproxy.capture_name);
721 curproxy->capture_namelen = defproxy.capture_namelen;
722 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200724
Willy Tarreau977b8e42006-12-29 14:19:17 +0100725 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100726 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100727 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100728 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100729 curproxy->uri_auth = defproxy.uri_auth;
730 curproxy->mon_net = defproxy.mon_net;
731 curproxy->mon_mask = defproxy.mon_mask;
732 if (defproxy.monitor_uri)
733 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
734 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100735 if (defproxy.defbe.name)
736 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100737 }
738
739 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100740 curproxy->timeout.connect = defproxy.timeout.connect;
741 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100742 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100743 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100744 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100745 curproxy->source_addr = defproxy.source_addr;
746 }
747
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748 curproxy->mode = defproxy.mode;
749 curproxy->logfac1 = defproxy.logfac1;
750 curproxy->logsrv1 = defproxy.logsrv1;
751 curproxy->loglev1 = defproxy.loglev1;
752 curproxy->logfac2 = defproxy.logfac2;
753 curproxy->logsrv2 = defproxy.logsrv2;
754 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200755 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100756 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
757 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200758
Willy Tarreaubaaee002006-06-26 02:48:02 +0200759 return 0;
760 }
761 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
762 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100763 /* FIXME-20070101: we should do this too at the end of the
764 * config parsing to free all default values.
765 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200766 free(defproxy.check_req);
767 free(defproxy.cookie_name);
768 free(defproxy.url_param_name);
769 free(defproxy.capture_name);
770 free(defproxy.monitor_uri);
771 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100772 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200773 free(defproxy.fwdfor_hdr_name);
774 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100775
Willy Tarreaua534fea2008-08-03 12:19:50 +0200776 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
777 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100778
Willy Tarreaubaaee002006-06-26 02:48:02 +0200779 /* we cannot free uri_auth because it might already be used */
780 init_default_instance();
781 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100782 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200783 return 0;
784 }
785 else if (curproxy == NULL) {
786 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
787 return -1;
788 }
789
Willy Tarreau977b8e42006-12-29 14:19:17 +0100790
791 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200792 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100793 struct listener *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100794 int cur_arg;
795
Willy Tarreaubaaee002006-06-26 02:48:02 +0200796 if (curproxy == &defproxy) {
797 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
798 return -1;
799 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100800 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
801 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200802
803 if (strchr(args[1], ':') == NULL) {
804 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
805 file, linenum, args[0]);
806 return -1;
807 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100808
809 last_listen = curproxy->listen;
810 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200811 if (!curproxy->listen)
812 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100813
814 cur_arg = 2;
815 while (*(args[cur_arg])) {
816 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
817#ifdef SO_BINDTODEVICE
818 struct listener *l;
819
820 if (!*args[cur_arg + 1]) {
821 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
822 file, linenum, args[0]);
823 return -1;
824 }
825
826 for (l = curproxy->listen; l != last_listen; l = l->next)
827 l->interface = strdup(args[cur_arg + 1]);
828
829 global.last_checks |= LSTCHK_NETADM;
830
831 cur_arg += 2;
832 continue;
833#else
834 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
835 file, linenum, args[0], args[cur_arg]);
836 return -1;
837#endif
838 }
839 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100840#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100841 struct listener *l;
842
843 for (l = curproxy->listen; l != last_listen; l = l->next)
844 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100845
846 cur_arg ++;
847 continue;
848#else
849 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
850 file, linenum, args[0], args[cur_arg]);
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100851 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100852#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100853 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100854 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100855 file, linenum, args[0]);
856 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100857 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200858 global.maxsock++;
859 return 0;
860 }
861 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
862 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
863 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
864 file, linenum, args[0]);
865 return -1;
866 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100867 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
868 return 0;
869
Willy Tarreaubaaee002006-06-26 02:48:02 +0200870 /* flush useless bits */
871 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
872 return 0;
873 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200874 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100875 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
876 return 0;
877
Willy Tarreau1c47f852006-07-09 08:22:27 +0200878 if (!*args[1]) {
879 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
880 file, linenum, args[0]);
881 return -1;
882 }
883
Willy Tarreaua534fea2008-08-03 12:19:50 +0200884 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100885 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200886 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100887 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200888 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
889
890 return 0;
891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
893 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
894 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
895 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
896 else {
897 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
898 return -1;
899 }
900 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100901 else if (!strcmp(args[0], "id")) {
902 struct proxy *target;
903
904 if (curproxy == &defproxy) {
905 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
906 file, linenum, args[0]);
907 return -1;
908 }
909
910 if (!*args[1]) {
911 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
912 file, linenum, args[0]);
913 return -1;
914 }
915
916 curproxy->uuid = atol(args[1]);
917
918 if (curproxy->uuid < 1001) {
919 Alert("parsing [%s:%d]: custom id has to be > 1000",
920 file, linenum);
921 return -1;
922 }
923
924 for (target = proxy; target; target = target->next)
925 if (curproxy != target && curproxy->uuid == target->uuid) {
926 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
927 file, linenum, curproxy->id, target->id);
928 return -1;
929 }
930 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
932 curproxy->state = PR_STSTOPPED;
933 }
934 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
935 curproxy->state = PR_STNEW;
936 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100937 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
938 int cur_arg = 1;
939 unsigned int set = 0;
940
941 while (*args[cur_arg]) {
942 int u;
943 if (strcmp(args[cur_arg], "all") == 0) {
944 set = 0;
945 break;
946 }
947 else if (strcmp(args[cur_arg], "odd") == 0) {
948 set |= 0x55555555;
949 }
950 else if (strcmp(args[cur_arg], "even") == 0) {
951 set |= 0xAAAAAAAA;
952 }
953 else {
954 u = str2uic(args[cur_arg]);
955 if (u < 1 || u > 32) {
956 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
957 file, linenum, args[0]);
958 return -1;
959 }
960 if (u > global.nbproc) {
961 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
962 file, linenum, args[0]);
963 }
964 set |= 1 << (u - 1);
965 }
966 cur_arg++;
967 }
968 curproxy->bind_proc = set;
969 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200970 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200971 if (curproxy == &defproxy) {
972 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
973 return -1;
974 }
975
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100976 err = invalid_char(args[1]);
977 if (err) {
978 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
979 file, linenum, *err, args[1]);
980 return -1;
981 }
982
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200983 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
984 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
985 file, linenum, args[1]);
986 return -1;
987 }
988 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200989 else if (!strcmp(args[0], "cookie")) { /* cookie name */
990 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200991
Willy Tarreau977b8e42006-12-29 14:19:17 +0100992 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
993 return 0;
994
Willy Tarreaubaaee002006-06-26 02:48:02 +0200995 if (*(args[1]) == 0) {
996 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
997 file, linenum, args[0]);
998 return -1;
999 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001000
1001 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 curproxy->cookie_name = strdup(args[1]);
1003 curproxy->cookie_len = strlen(curproxy->cookie_name);
1004
1005 cur_arg = 2;
1006 while (*(args[cur_arg])) {
1007 if (!strcmp(args[cur_arg], "rewrite")) {
1008 curproxy->options |= PR_O_COOK_RW;
1009 }
1010 else if (!strcmp(args[cur_arg], "indirect")) {
1011 curproxy->options |= PR_O_COOK_IND;
1012 }
1013 else if (!strcmp(args[cur_arg], "insert")) {
1014 curproxy->options |= PR_O_COOK_INS;
1015 }
1016 else if (!strcmp(args[cur_arg], "nocache")) {
1017 curproxy->options |= PR_O_COOK_NOC;
1018 }
1019 else if (!strcmp(args[cur_arg], "postonly")) {
1020 curproxy->options |= PR_O_COOK_POST;
1021 }
1022 else if (!strcmp(args[cur_arg], "prefix")) {
1023 curproxy->options |= PR_O_COOK_PFX;
1024 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001025 else if (!strcmp(args[cur_arg], "domain")) {
1026 if (!*args[cur_arg + 1]) {
1027 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1028 file, linenum, args[cur_arg]);
1029 return -1;
1030 }
1031
1032 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1033 /* rfc2109, 4.3.2 Rejecting Cookies */
1034 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1035 " dots or does not start with a dot.\n",
1036 file, linenum, args[cur_arg + 1]);
1037 return -1;
1038 }
1039
1040 err = invalid_domainchar(args[cur_arg + 1]);
1041 if (err) {
1042 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1043 file, linenum, *err, args[cur_arg + 1]);
1044 return -1;
1045 }
1046
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001047 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001048 cur_arg++;
1049 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001051 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 file, linenum, args[0]);
1053 return -1;
1054 }
1055 cur_arg++;
1056 }
1057 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1058 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1059 file, linenum);
1060 return -1;
1061 }
1062
1063 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1064 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1065 file, linenum);
1066 return -1;
1067 }
1068 }/* end else if (!strcmp(args[0], "cookie")) */
1069 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001070
Willy Tarreau977b8e42006-12-29 14:19:17 +01001071 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1072 return 0;
1073
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074 if (*(args[5]) == 0) {
1075 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1076 file, linenum, args[0]);
1077 return -1;
1078 }
1079 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001080 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081 curproxy->appsession_name = strdup(args[1]);
1082 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1083 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001084 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1085 if (err) {
1086 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1087 file, linenum, *err, args[0]);
1088 return -1;
1089 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001090 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001091
Willy Tarreau51041c72007-09-09 21:56:53 +02001092 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1093 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 return -1;
1095 }
1096 } /* Url App Session */
1097 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001098 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1099 return 0;
1100
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 if (*(args[4]) == 0) {
1103 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1104 file, linenum, args[0]);
1105 return -1;
1106 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001107 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001108 curproxy->capture_name = strdup(args[2]);
1109 curproxy->capture_namelen = strlen(curproxy->capture_name);
1110 curproxy->capture_len = atol(args[4]);
1111 if (curproxy->capture_len >= CAPTURE_LEN) {
1112 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1113 file, linenum, CAPTURE_LEN - 1);
1114 curproxy->capture_len = CAPTURE_LEN - 1;
1115 }
1116 curproxy->to_log |= LW_COOKIE;
1117 }
1118 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1119 struct cap_hdr *hdr;
1120
1121 if (curproxy == &defproxy) {
1122 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1123 return -1;
1124 }
1125
1126 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1127 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1128 file, linenum, args[0], args[1]);
1129 return -1;
1130 }
1131
1132 hdr = calloc(sizeof(struct cap_hdr), 1);
1133 hdr->next = curproxy->req_cap;
1134 hdr->name = strdup(args[3]);
1135 hdr->namelen = strlen(args[3]);
1136 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001137 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001138 hdr->index = curproxy->nb_req_cap++;
1139 curproxy->req_cap = hdr;
1140 curproxy->to_log |= LW_REQHDR;
1141 }
1142 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1143 struct cap_hdr *hdr;
1144
1145 if (curproxy == &defproxy) {
1146 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1147 return -1;
1148 }
1149
1150 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1151 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1152 file, linenum, args[0], args[1]);
1153 return -1;
1154 }
1155 hdr = calloc(sizeof(struct cap_hdr), 1);
1156 hdr->next = curproxy->rsp_cap;
1157 hdr->name = strdup(args[3]);
1158 hdr->namelen = strlen(args[3]);
1159 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001160 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001161 hdr->index = curproxy->nb_rsp_cap++;
1162 curproxy->rsp_cap = hdr;
1163 curproxy->to_log |= LW_RSPHDR;
1164 }
1165 else {
1166 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1167 file, linenum, args[0]);
1168 return -1;
1169 }
1170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001171 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001172 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1173 return 0;
1174
Willy Tarreaubaaee002006-06-26 02:48:02 +02001175 if (*(args[1]) == 0) {
1176 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1177 file, linenum, args[0]);
1178 return -1;
1179 }
1180 curproxy->conn_retries = atol(args[1]);
1181 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001182 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1183 int pol = ACL_COND_NONE;
1184 struct acl_cond *cond;
1185
Willy Tarreaub099aca2008-10-12 17:26:37 +02001186 if (curproxy == &defproxy) {
1187 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1188 return -1;
1189 }
1190
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001191 if (!strcmp(args[1], "if"))
1192 pol = ACL_COND_IF;
1193 else if (!strcmp(args[1], "unless"))
1194 pol = ACL_COND_UNLESS;
1195
1196 if (pol == ACL_COND_NONE) {
1197 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1198 file, linenum, args[0]);
1199 return -1;
1200 }
1201
1202 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1203 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1204 file, linenum);
1205 return -1;
1206 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001207 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001208 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001209
1210 if (!(acl_seen & CFG_ACL_BLOCK)) {
1211 if (acl_seen & CFG_ACL_REDIR)
1212 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
1213 file, linenum, args[0]);
1214 if (acl_seen & CFG_ACL_BACKEND)
1215 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
1216 file, linenum, args[0]);
1217 acl_seen |= CFG_ACL_BLOCK;
1218 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001219 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001220 else if (!strcmp(args[0], "redirect")) {
1221 int pol = ACL_COND_NONE;
1222 struct acl_cond *cond;
1223 struct redirect_rule *rule;
1224 int cur_arg;
1225 int type = REDIRECT_TYPE_NONE;
1226 int code = 302;
1227 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001228 char *cookie = NULL;
1229 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001230 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001231
1232 cur_arg = 1;
1233 while (*(args[cur_arg])) {
1234 if (!strcmp(args[cur_arg], "location")) {
1235 if (!*args[cur_arg + 1]) {
1236 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1237 file, linenum, args[0], args[cur_arg]);
1238 return -1;
1239 }
1240
1241 type = REDIRECT_TYPE_LOCATION;
1242 cur_arg++;
1243 destination = args[cur_arg];
1244 }
1245 else if (!strcmp(args[cur_arg], "prefix")) {
1246 if (!*args[cur_arg + 1]) {
1247 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1248 file, linenum, args[0], args[cur_arg]);
1249 return -1;
1250 }
1251
1252 type = REDIRECT_TYPE_PREFIX;
1253 cur_arg++;
1254 destination = args[cur_arg];
1255 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001256 else if (!strcmp(args[cur_arg], "set-cookie")) {
1257 if (!*args[cur_arg + 1]) {
1258 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1259 file, linenum, args[0], args[cur_arg]);
1260 return -1;
1261 }
1262
1263 cur_arg++;
1264 cookie = args[cur_arg];
1265 cookie_set = 1;
1266 }
1267 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1268 if (!*args[cur_arg + 1]) {
1269 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1270 file, linenum, args[0], args[cur_arg]);
1271 return -1;
1272 }
1273
1274 cur_arg++;
1275 cookie = args[cur_arg];
1276 cookie_set = 0;
1277 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001278 else if (!strcmp(args[cur_arg],"code")) {
1279 if (!*args[cur_arg + 1]) {
1280 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1281 file, linenum, args[0]);
1282 return -1;
1283 }
1284 cur_arg++;
1285 code = atol(args[cur_arg]);
1286 if (code < 301 || code > 303) {
1287 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1288 file, linenum, args[0], code);
1289 return -1;
1290 }
1291 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001292 else if (!strcmp(args[cur_arg],"drop-query")) {
1293 flags |= REDIRECT_FLAG_DROP_QS;
1294 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001295 else if (!strcmp(args[cur_arg], "if")) {
1296 pol = ACL_COND_IF;
1297 cur_arg++;
1298 break;
1299 }
1300 else if (!strcmp(args[cur_arg], "unless")) {
1301 pol = ACL_COND_UNLESS;
1302 cur_arg++;
1303 break;
1304 }
1305 else {
1306 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1307 file, linenum, args[0], args[cur_arg]);
1308 return -1;
1309 }
1310 cur_arg++;
1311 }
1312
1313 if (type == REDIRECT_TYPE_NONE) {
1314 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1315 file, linenum, args[0]);
1316 return -1;
1317 }
1318
1319 if (pol == ACL_COND_NONE) {
1320 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1321 file, linenum, args[0]);
1322 return -1;
1323 }
1324
1325 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1326 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1327 file, linenum, args[0]);
1328 return -1;
1329 }
1330
Willy Tarreaua9802632008-07-25 19:13:19 +02001331 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001332 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1333 rule->cond = cond;
1334 rule->rdr_str = strdup(destination);
1335 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001336 if (cookie) {
1337 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1338 * a clear consists in appending "; Max-Age=0" at the end.
1339 */
1340 rule->cookie_len = strlen(cookie);
1341 if (cookie_set)
1342 rule->cookie_str = strdup(cookie);
1343 else {
1344 rule->cookie_str = malloc(rule->cookie_len + 12);
1345 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1346 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1347 rule->cookie_len += 11;
1348 }
1349 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001350 rule->type = type;
1351 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001352 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001353 LIST_INIT(&rule->list);
1354 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001355
1356 if (!(acl_seen & CFG_ACL_REDIR)) {
1357 if (acl_seen & CFG_ACL_BACKEND)
1358 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
1359 file, linenum, args[0]);
1360 acl_seen |= CFG_ACL_REDIR;
1361 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001362 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001363 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001364 int pol = ACL_COND_NONE;
1365 struct acl_cond *cond;
1366 struct switching_rule *rule;
1367
Willy Tarreaub099aca2008-10-12 17:26:37 +02001368 if (curproxy == &defproxy) {
1369 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1370 return -1;
1371 }
1372
Willy Tarreau55ea7572007-06-17 19:56:27 +02001373 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1374 return 0;
1375
1376 if (*(args[1]) == 0) {
1377 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1378 return -1;
1379 }
1380
1381 if (!strcmp(args[2], "if"))
1382 pol = ACL_COND_IF;
1383 else if (!strcmp(args[2], "unless"))
1384 pol = ACL_COND_UNLESS;
1385
1386 if (pol == ACL_COND_NONE) {
1387 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1388 file, linenum, args[0]);
1389 return -1;
1390 }
1391
1392 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001393 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001394 file, linenum);
1395 return -1;
1396 }
1397
Willy Tarreaua9802632008-07-25 19:13:19 +02001398 cond->line = linenum;
1399 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001400 struct acl *acl;
1401 const char *name;
1402
1403 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1404 name = acl ? acl->name : "(unknown)";
1405 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1406 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001407 }
1408
Willy Tarreau55ea7572007-06-17 19:56:27 +02001409 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1410 rule->cond = cond;
1411 rule->be.name = strdup(args[1]);
1412 LIST_INIT(&rule->list);
1413 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001414 acl_seen |= CFG_ACL_BACKEND;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001415 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001416 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001417 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1418 return 0;
1419
Willy Tarreaubaaee002006-06-26 02:48:02 +02001420 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1421 curproxy->uri_auth = NULL; /* we must detach from the default config */
1422
1423 if (*(args[1]) == 0) {
1424 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1425 return -1;
1426 } else if (!strcmp(args[1], "uri")) {
1427 if (*(args[2]) == 0) {
1428 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1429 return -1;
1430 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1431 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1432 return -1;
1433 }
1434 } else if (!strcmp(args[1], "realm")) {
1435 if (*(args[2]) == 0) {
1436 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1437 return -1;
1438 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1439 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1440 return -1;
1441 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001442 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001443 unsigned interval;
1444
1445 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1446 if (err) {
1447 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1448 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001449 return -1;
1450 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1451 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1452 return -1;
1453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 } else if (!strcmp(args[1], "auth")) {
1455 if (*(args[2]) == 0) {
1456 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1457 return -1;
1458 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1459 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1460 return -1;
1461 }
1462 } else if (!strcmp(args[1], "scope")) {
1463 if (*(args[2]) == 0) {
1464 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1465 return -1;
1466 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1467 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1468 return -1;
1469 }
1470 } else if (!strcmp(args[1], "enable")) {
1471 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1472 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1473 return -1;
1474 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001475 } else if (!strcmp(args[1], "hide-version")) {
1476 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1477 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1478 return -1;
1479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001480 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001481 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001482 file, linenum, args[0]);
1483 return -1;
1484 }
1485 }
1486 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001487 int optnum;
1488
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001489 if (*(args[1]) == '\0') {
1490 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1491 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492 return -1;
1493 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001494
1495 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1496 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1497 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1498 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001499
1500 if (!inv)
1501 curproxy->options |= cfg_opts[optnum].val;
1502 else
1503 curproxy->options &= ~cfg_opts[optnum].val;
1504
Willy Tarreau13943ab2006-12-31 00:24:10 +01001505 return 0;
1506 }
1507 }
1508
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001509 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1510 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
1511 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
1512 return 0;
1513
1514 if (!inv)
1515 curproxy->options2 |= cfg_opts2[optnum].val;
1516 else
1517 curproxy->options2 &= ~cfg_opts2[optnum].val;
1518
1519 return 0;
1520 }
1521 }
1522
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001523 if (inv) {
1524 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1525 file, linenum, args[1]);
1526 return -1;
1527 }
1528
Willy Tarreau13943ab2006-12-31 00:24:10 +01001529 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530 /* generate a complete HTTP log */
1531 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1532 else if (!strcmp(args[1], "tcplog"))
1533 /* generate a detailed TCP log */
1534 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535 else if (!strcmp(args[1], "tcpka")) {
1536 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001537 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1538 return 0;
1539
1540 if (curproxy->cap & PR_CAP_FE)
1541 curproxy->options |= PR_O_TCP_CLI_KA;
1542 if (curproxy->cap & PR_CAP_BE)
1543 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001544 }
1545 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001546 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1547 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001548 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001549 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001550 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001551 curproxy->options &= ~PR_O_SMTP_CHK;
1552 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001553 if (!*args[2]) { /* no argument */
1554 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1555 curproxy->check_len = strlen(DEF_CHECK_REQ);
1556 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001557 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558 curproxy->check_req = (char *)malloc(reqlen);
1559 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1560 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1561 } else { /* more arguments : METHOD URI [HTTP_VER] */
1562 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1563 if (*args[4])
1564 reqlen += strlen(args[4]);
1565 else
1566 reqlen += strlen("HTTP/1.0");
1567
1568 curproxy->check_req = (char *)malloc(reqlen);
1569 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1570 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1571 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001572 }
1573 else if (!strcmp(args[1], "ssl-hello-chk")) {
1574 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001575 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1576 return 0;
1577
Willy Tarreaua534fea2008-08-03 12:19:50 +02001578 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001579 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001580 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001581 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001582 }
Willy Tarreau23677902007-05-08 23:50:35 +02001583 else if (!strcmp(args[1], "smtpchk")) {
1584 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001585 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001586 curproxy->options &= ~PR_O_HTTP_CHK;
1587 curproxy->options &= ~PR_O_SSL3_CHK;
1588 curproxy->options |= PR_O_SMTP_CHK;
1589
1590 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1591 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1592 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1593 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1594 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1595 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1596 curproxy->check_req = (char *)malloc(reqlen);
1597 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1598 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1599 } else {
1600 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1601 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1602 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1603 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1604 }
1605 }
1606 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001607 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001608 int cur_arg;
1609
1610 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1611 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001612 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001613
1614 curproxy->options |= PR_O_FWDFOR;
1615
1616 free(curproxy->fwdfor_hdr_name);
1617 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1618 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1619
1620 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1621 cur_arg = 2;
1622 while (*(args[cur_arg])) {
1623 if (!strcmp(args[cur_arg], "except")) {
1624 /* suboption except - needs additional argument for it */
1625 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1626 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1627 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001628 return -1;
1629 }
1630 /* flush useless bits */
1631 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001632 cur_arg += 2;
1633 } else if (!strcmp(args[cur_arg], "header")) {
1634 /* suboption header - needs additional argument for it */
1635 if (*(args[cur_arg+1]) == 0) {
1636 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1637 file, linenum, args[0], args[1], args[cur_arg]);
1638 return -1;
1639 }
1640 free(curproxy->fwdfor_hdr_name);
1641 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1642 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1643 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001644 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001645 /* unknown suboption - catchall */
1646 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1647 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001648 return -1;
1649 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001650 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001652 else {
1653 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1654 return -1;
1655 }
1656 return 0;
1657 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001658 else if (!strcmp(args[0], "default_backend")) {
1659 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1660 return 0;
1661
1662 if (*(args[1]) == 0) {
1663 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1664 return -1;
1665 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001666 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001667 curproxy->defbe.name = strdup(args[1]);
1668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001669 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001670 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1671 return 0;
1672
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001673 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1674 file, linenum, args[0]);
1675
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 /* enable reconnections to dispatch */
1677 curproxy->options |= PR_O_REDISP;
1678 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001679 else if (!strcmp(args[0], "http-check")) {
1680 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1681 return 0;
1682
1683 if (strcmp(args[1], "disable-on-404") == 0) {
1684 /* enable a graceful server shutdown on an HTTP 404 response */
1685 curproxy->options |= PR_O_DISABLE404;
1686 }
1687 else {
1688 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1689 return -1;
1690 }
1691 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001692 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001693 if (curproxy == &defproxy) {
1694 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1695 return -1;
1696 }
1697
Willy Tarreaub80c2302007-11-30 20:51:32 +01001698 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1699 return 0;
1700
1701 if (strcmp(args[1], "fail") == 0) {
1702 /* add a condition to fail monitor requests */
1703 int pol = ACL_COND_NONE;
1704 struct acl_cond *cond;
1705
1706 if (!strcmp(args[2], "if"))
1707 pol = ACL_COND_IF;
1708 else if (!strcmp(args[2], "unless"))
1709 pol = ACL_COND_UNLESS;
1710
1711 if (pol == ACL_COND_NONE) {
1712 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1713 file, linenum, args[0], args[1]);
1714 return -1;
1715 }
1716
1717 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1718 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1719 file, linenum, args[0], args[1]);
1720 return -1;
1721 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001722 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001723 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1724 }
1725 else {
1726 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1727 return -1;
1728 }
1729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001730#ifdef TPROXY
1731 else if (!strcmp(args[0], "transparent")) {
1732 /* enable transparent proxy connections */
1733 curproxy->options |= PR_O_TRANSP;
1734 }
1735#endif
1736 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001737 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1738 return 0;
1739
Willy Tarreaubaaee002006-06-26 02:48:02 +02001740 if (*(args[1]) == 0) {
1741 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1742 return -1;
1743 }
1744 curproxy->maxconn = atol(args[1]);
1745 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001746 else if (!strcmp(args[0], "backlog")) { /* backlog */
1747 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1748 return 0;
1749
1750 if (*(args[1]) == 0) {
1751 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1752 return -1;
1753 }
1754 curproxy->backlog = atol(args[1]);
1755 }
Willy Tarreau86034312006-12-29 00:10:33 +01001756 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001757 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1758 return 0;
1759
Willy Tarreau86034312006-12-29 00:10:33 +01001760 if (*(args[1]) == 0) {
1761 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1762 return -1;
1763 }
1764 curproxy->fullconn = atol(args[1]);
1765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1767 if (*(args[1]) == 0) {
1768 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1769 return -1;
1770 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001771 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1772 if (err) {
1773 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1774 file, linenum, *err);
1775 return -1;
1776 }
1777 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 }
1779 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1780 if (curproxy == &defproxy) {
1781 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1782 return -1;
1783 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001784 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1785 return 0;
1786
Willy Tarreaubaaee002006-06-26 02:48:02 +02001787 if (strchr(args[1], ':') == NULL) {
1788 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1789 return -1;
1790 }
1791 curproxy->dispatch_addr = *str2sa(args[1]);
1792 }
1793 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001794 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1795 return 0;
1796
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02001797 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001798 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1799 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1800 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001801 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802 }
1803 else if (!strcmp(args[0], "server")) { /* server address */
1804 int cur_arg;
1805 char *rport;
1806 char *raddr;
1807 short realport;
1808 int do_check;
1809
1810 if (curproxy == &defproxy) {
1811 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1812 return -1;
1813 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001814 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1815 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001816
1817 if (!*args[2]) {
1818 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1819 file, linenum, args[0]);
1820 return -1;
1821 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001822
1823 err = invalid_char(args[1]);
1824 if (err) {
1825 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1826 file, linenum, *err, args[1]);
1827 return -1;
1828 }
1829
Willy Tarreaubaaee002006-06-26 02:48:02 +02001830 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1831 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1832 return -1;
1833 }
1834
1835 /* the servers are linked backwards first */
1836 newsrv->next = curproxy->srv;
1837 curproxy->srv = newsrv;
1838 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001839 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001840
1841 LIST_INIT(&newsrv->pendconns);
1842 do_check = 0;
1843 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001844 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001845 newsrv->id = strdup(args[1]);
1846
1847 /* several ways to check the port component :
1848 * - IP => port=+0, relative
1849 * - IP: => port=+0, relative
1850 * - IP:N => port=N, absolute
1851 * - IP:+N => port=+N, relative
1852 * - IP:-N => port=-N, relative
1853 */
1854 raddr = strdup(args[2]);
1855 rport = strchr(raddr, ':');
1856 if (rport) {
1857 *rport++ = 0;
1858 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001859 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001860 newsrv->state |= SRV_MAPPORTS;
1861 } else {
1862 realport = 0;
1863 newsrv->state |= SRV_MAPPORTS;
1864 }
1865
1866 newsrv->addr = *str2sa(raddr);
1867 newsrv->addr.sin_port = htons(realport);
1868 free(raddr);
1869
1870 newsrv->curfd = -1; /* no health-check in progress */
1871 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001872 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1873 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001874 newsrv->rise = DEF_RISETIME;
1875 newsrv->fall = DEF_FALLTIME;
1876 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001877 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001878 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001879 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001880
Willy Tarreaubaaee002006-06-26 02:48:02 +02001881 cur_arg = 3;
1882 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001883 if (!strcmp(args[cur_arg], "id")) {
1884 struct server *target;
1885
1886 if (!*args[cur_arg + 1]) {
1887 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1888 file, linenum, args[cur_arg]);
1889 return -1;
1890 }
1891
1892 newsrv->puid = atol(args[cur_arg + 1]);
1893
1894 if (newsrv->puid< 1001) {
1895 Alert("parsing [%s:%d]: custom id has to be > 1000",
1896 file, linenum);
1897 return -1;
1898 }
1899
1900 for (target = proxy->srv; target; target = target->next)
1901 if (newsrv != target && newsrv->puid == target->puid) {
1902 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1903 file, linenum, newsrv->id, target->id);
1904 return -1;
1905 }
1906 cur_arg += 2;
1907 }
1908 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909 newsrv->cookie = strdup(args[cur_arg + 1]);
1910 newsrv->cklen = strlen(args[cur_arg + 1]);
1911 cur_arg += 2;
1912 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001913 else if (!strcmp(args[cur_arg], "redir")) {
1914 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1915 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1916 cur_arg += 2;
1917 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 else if (!strcmp(args[cur_arg], "rise")) {
1919 newsrv->rise = atol(args[cur_arg + 1]);
1920 newsrv->health = newsrv->rise;
1921 cur_arg += 2;
1922 }
1923 else if (!strcmp(args[cur_arg], "fall")) {
1924 newsrv->fall = atol(args[cur_arg + 1]);
1925 cur_arg += 2;
1926 }
1927 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001928 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1929 if (err) {
1930 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1931 file, linenum, *err, newsrv->id);
1932 return -1;
1933 }
1934 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001935 cur_arg += 2;
1936 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001937 else if (!strcmp(args[cur_arg], "fastinter")) {
1938 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1939 if (err) {
1940 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1941 file, linenum, *err, newsrv->id);
1942 return -1;
1943 }
1944 newsrv->fastinter = val;
1945 cur_arg += 2;
1946 }
1947 else if (!strcmp(args[cur_arg], "downinter")) {
1948 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1949 if (err) {
1950 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1951 file, linenum, *err, newsrv->id);
1952 return -1;
1953 }
1954 newsrv->downinter = val;
1955 cur_arg += 2;
1956 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001957 else if (!strcmp(args[cur_arg], "addr")) {
1958 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001959 cur_arg += 2;
1960 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001961 else if (!strcmp(args[cur_arg], "port")) {
1962 newsrv->check_port = atol(args[cur_arg + 1]);
1963 cur_arg += 2;
1964 }
1965 else if (!strcmp(args[cur_arg], "backup")) {
1966 newsrv->state |= SRV_BACKUP;
1967 cur_arg ++;
1968 }
1969 else if (!strcmp(args[cur_arg], "weight")) {
1970 int w;
1971 w = atol(args[cur_arg + 1]);
1972 if (w < 1 || w > 256) {
1973 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1974 file, linenum, newsrv->id, w);
1975 return -1;
1976 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001977 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001978 cur_arg += 2;
1979 }
1980 else if (!strcmp(args[cur_arg], "minconn")) {
1981 newsrv->minconn = atol(args[cur_arg + 1]);
1982 cur_arg += 2;
1983 }
1984 else if (!strcmp(args[cur_arg], "maxconn")) {
1985 newsrv->maxconn = atol(args[cur_arg + 1]);
1986 cur_arg += 2;
1987 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001988 else if (!strcmp(args[cur_arg], "maxqueue")) {
1989 newsrv->maxqueue = atol(args[cur_arg + 1]);
1990 cur_arg += 2;
1991 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001992 else if (!strcmp(args[cur_arg], "slowstart")) {
1993 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001994 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001995 if (err) {
1996 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1997 file, linenum, *err, newsrv->id);
1998 return -1;
1999 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002000 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002001 cur_arg += 2;
2002 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002003 else if (!strcmp(args[cur_arg], "track")) {
2004
2005 if (!*args[cur_arg + 1]) {
2006 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2007 file, linenum);
2008 return -1;
2009 }
2010
2011 newsrv->trackit = strdup(args[cur_arg + 1]);
2012
2013 cur_arg += 2;
2014 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002015 else if (!strcmp(args[cur_arg], "check")) {
2016 global.maxsock++;
2017 do_check = 1;
2018 cur_arg += 1;
2019 }
2020 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
2021 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002022#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002023 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2024 file, linenum, "source", "usesrc");
2025#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002026 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2027 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002028#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002029 return -1;
2030 }
2031 newsrv->state |= SRV_BIND_SRC;
2032 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
2033 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002034 while (*(args[cur_arg])) {
2035 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002036#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2037#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002038 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2039 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2040 file, linenum, "usesrc", "source");
2041 return -1;
2042 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002043#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002044 if (!*args[cur_arg + 1]) {
2045 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2046 file, linenum, "usesrc");
2047 return -1;
2048 }
2049 if (!strcmp(args[cur_arg + 1], "client")) {
2050 newsrv->state |= SRV_TPROXY_CLI;
2051 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2052 newsrv->state |= SRV_TPROXY_CIP;
2053 } else {
2054 newsrv->state |= SRV_TPROXY_ADDR;
2055 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2056 }
2057 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002058#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002059 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002060#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002061 cur_arg += 2;
2062 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002063#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002064 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002065 file, linenum, "usesrc");
2066 return -1;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002067#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2068 } /* "usesrc" */
2069
2070 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2071#ifdef SO_BINDTODEVICE
2072 if (!*args[cur_arg + 1]) {
2073 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2074 file, linenum, args[0]);
2075 return -1;
2076 }
2077 if (newsrv->iface_name)
2078 free(newsrv->iface_name);
2079
2080 newsrv->iface_name = strdup(args[cur_arg + 1]);
2081 newsrv->iface_len = strlen(newsrv->iface_name);
2082 global.last_checks |= LSTCHK_NETADM;
2083#else
2084 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2085 file, linenum, args[0], args[cur_arg]);
2086 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002087#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002088 cur_arg += 2;
2089 continue;
2090 }
2091 /* this keyword in not an option of "source" */
2092 break;
2093 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002094 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002095 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2096 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2097 file, linenum, "usesrc", "source");
2098 return -1;
2099 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002100 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002101 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 +02002102 file, linenum, newsrv->id);
2103 return -1;
2104 }
2105 }
2106
2107 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002108 if (newsrv->trackit) {
2109 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2110 file, linenum);
2111 return -1;
2112 }
2113
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002114 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2115 newsrv->check_port = newsrv->check_addr.sin_port;
2116
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2118 newsrv->check_port = realport; /* by default */
2119 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002120 /* not yet valid, because no port was set on
2121 * the server either. We'll check if we have
2122 * a known port on the first listener.
2123 */
2124 struct listener *l;
2125 l = curproxy->listen;
2126 if (l) {
2127 int port;
2128 port = (l->addr.ss_family == AF_INET6)
2129 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2130 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2131 newsrv->check_port = port;
2132 }
2133 }
2134 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002135 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2136 file, linenum, newsrv->id);
2137 return -1;
2138 }
2139 newsrv->state |= SRV_CHECKED;
2140 }
2141
2142 if (newsrv->state & SRV_BACKUP)
2143 curproxy->srv_bck++;
2144 else
2145 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002146
2147 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002148 }
2149 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002150 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002151 int facility;
2152
2153 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2154 curproxy->logfac1 = global.logfac1;
2155 curproxy->logsrv1 = global.logsrv1;
2156 curproxy->loglev1 = global.loglev1;
2157 curproxy->logfac2 = global.logfac2;
2158 curproxy->logsrv2 = global.logsrv2;
2159 curproxy->loglev2 = global.loglev2;
2160 }
2161 else if (*(args[1]) && *(args[2])) {
2162 int level;
2163
2164 facility = get_log_facility(args[2]);
2165 if (facility < 0) {
2166 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2167 exit(1);
2168 }
2169
2170 level = 7; /* max syslog level = debug */
2171 if (*(args[3])) {
2172 level = get_log_level(args[3]);
2173 if (level < 0) {
2174 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2175 exit(1);
2176 }
2177 }
2178
Robert Tsai81ae1952007-12-05 10:47:29 +01002179 if (args[1][0] == '/') {
2180 logsrv.u.addr.sa_family = AF_UNIX;
2181 logsrv.u.un = *str2sun(args[1]);
2182 } else {
2183 logsrv.u.addr.sa_family = AF_INET;
2184 logsrv.u.in = *str2sa(args[1]);
2185 if (!logsrv.u.in.sin_port) {
2186 logsrv.u.in.sin_port =
2187 htons(SYSLOG_PORT);
2188 }
2189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002190
2191 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002192 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193 curproxy->logfac1 = facility;
2194 curproxy->loglev1 = level;
2195 }
2196 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002197 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002198 curproxy->logfac2 = facility;
2199 curproxy->loglev2 = level;
2200 }
2201 else {
2202 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2203 return -1;
2204 }
2205 }
2206 else {
2207 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2208 file, linenum);
2209 return -1;
2210 }
2211 }
2212 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002213 int cur_arg;
2214
Willy Tarreau977b8e42006-12-29 14:19:17 +01002215 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2216 return 0;
2217
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002219 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2220 file, linenum, "source", "usesrc", "interface");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002221 return -1;
2222 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002223
2224 /* we must first clear any optional default setting */
2225 curproxy->options &= ~PR_O_TPXY_MASK;
2226 free(curproxy->iface_name);
2227 curproxy->iface_name = NULL;
2228 curproxy->iface_len = 0;
2229
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230 curproxy->source_addr = *str2sa(args[1]);
2231 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002232
2233 cur_arg = 2;
2234 while (*(args[cur_arg])) {
2235 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002236#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2237#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002238 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2239 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2240 file, linenum, "usesrc");
2241 return -1;
2242 }
2243#endif
2244 if (!*args[cur_arg + 1]) {
2245 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2246 file, linenum, "usesrc");
2247 return -1;
2248 }
2249
2250 if (!strcmp(args[cur_arg + 1], "client")) {
2251 curproxy->options |= PR_O_TPXY_CLI;
2252 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2253 curproxy->options |= PR_O_TPXY_CIP;
2254 } else {
2255 curproxy->options |= PR_O_TPXY_ADDR;
2256 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2257 }
2258 global.last_checks |= LSTCHK_NETADM;
2259#if !defined(CONFIG_HAP_LINUX_TPROXY)
2260 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002261#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002262#else /* no TPROXY support */
2263 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002264 file, linenum, "usesrc");
2265 return -1;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002266#endif
2267 cur_arg += 2;
2268 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002269 }
2270
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002271 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2272#ifdef SO_BINDTODEVICE
2273 if (!*args[cur_arg + 1]) {
2274 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2275 file, linenum, args[0]);
2276 return -1;
2277 }
2278 if (curproxy->iface_name)
2279 free(curproxy->iface_name);
2280
2281 curproxy->iface_name = strdup(args[cur_arg + 1]);
2282 curproxy->iface_len = strlen(curproxy->iface_name);
2283 global.last_checks |= LSTCHK_NETADM;
2284#else
2285 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2286 file, linenum, args[0], args[cur_arg]);
2287 return -1;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002288#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002289 cur_arg += 2;
2290 continue;
2291 }
2292 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2293 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002294 return -1;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002295 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002297 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2298 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2299 file, linenum, "usesrc", "source");
2300 return -1;
2301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002302 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2303 regex_t *preg;
2304 if (curproxy == &defproxy) {
2305 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2306 return -1;
2307 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002308 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2309 return 0;
2310
Willy Tarreaubaaee002006-06-26 02:48:02 +02002311 if (*(args[1]) == 0 || *(args[2]) == 0) {
2312 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2313 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 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2324 if (err) {
2325 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2326 file, linenum, *err);
2327 return -1;
2328 }
2329 }
2330 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2331 regex_t *preg;
2332 if (curproxy == &defproxy) {
2333 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2334 return -1;
2335 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002336 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2337 return 0;
2338
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 if (*(args[1]) == 0) {
2340 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2341 return -1;
2342 }
2343
2344 preg = calloc(1, sizeof(regex_t));
2345 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2346 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2347 return -1;
2348 }
2349
2350 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2351 }
2352 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2353 regex_t *preg;
2354 if (curproxy == &defproxy) {
2355 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2356 return -1;
2357 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002358 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2359 return 0;
2360
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 if (*(args[1]) == 0) {
2362 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2363 return -1;
2364 }
2365
2366 preg = calloc(1, sizeof(regex_t));
2367 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2368 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2369 return -1;
2370 }
2371
2372 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2373 }
2374 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2375 regex_t *preg;
2376 if (curproxy == &defproxy) {
2377 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2378 return -1;
2379 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002380 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2381 return 0;
2382
Willy Tarreaubaaee002006-06-26 02:48:02 +02002383 if (*(args[1]) == 0) {
2384 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2385 return -1;
2386 }
2387
2388 preg = calloc(1, sizeof(regex_t));
2389 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2390 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2391 return -1;
2392 }
2393
2394 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2395 }
2396 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2397 regex_t *preg;
2398 if (curproxy == &defproxy) {
2399 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2400 return -1;
2401 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002402 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2403 return 0;
2404
Willy Tarreaubaaee002006-06-26 02:48:02 +02002405 if (*(args[1]) == 0) {
2406 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2407 return -1;
2408 }
2409
2410 preg = calloc(1, sizeof(regex_t));
2411 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2412 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2413 return -1;
2414 }
2415
2416 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2417 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002418 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2419 regex_t *preg;
2420 if (curproxy == &defproxy) {
2421 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2422 return -1;
2423 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002424 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2425 return 0;
2426
Willy Tarreaub8750a82006-09-03 09:56:00 +02002427 if (*(args[1]) == 0) {
2428 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2429 return -1;
2430 }
2431
2432 preg = calloc(1, sizeof(regex_t));
2433 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2434 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2435 return -1;
2436 }
2437
2438 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2439 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002440 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2441 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002442 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002443 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2444 return -1;
2445 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002446 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2447 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002448
Willy Tarreau977b8e42006-12-29 14:19:17 +01002449 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002450 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2451 file, linenum, args[0]);
2452 return -1;
2453 }
2454
2455 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002456 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002457 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2458 }
2459
2460 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2461 }
2462 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2463 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002464 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002465 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2466 return -1;
2467 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002468 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2469 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002470
Willy Tarreau977b8e42006-12-29 14:19:17 +01002471 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002472 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2473 file, linenum, args[0]);
2474 return -1;
2475 }
2476
2477 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002478 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002479 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2480 }
2481
2482 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002484 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2485 regex_t *preg;
2486 if (curproxy == &defproxy) {
2487 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2488 return -1;
2489 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002490 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2491 return 0;
2492
Willy Tarreaubaaee002006-06-26 02:48:02 +02002493 if (*(args[1]) == 0 || *(args[2]) == 0) {
2494 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2495 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 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2506 if (err) {
2507 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2508 file, linenum, *err);
2509 return -1;
2510 }
2511 }
2512 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2513 regex_t *preg;
2514 if (curproxy == &defproxy) {
2515 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2516 return -1;
2517 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002518 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2519 return 0;
2520
Willy Tarreaubaaee002006-06-26 02:48:02 +02002521 if (*(args[1]) == 0) {
2522 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2523 return -1;
2524 }
2525
2526 preg = calloc(1, sizeof(regex_t));
2527 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2528 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2529 return -1;
2530 }
2531
2532 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2533 }
2534 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2535 regex_t *preg;
2536 if (curproxy == &defproxy) {
2537 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2538 return -1;
2539 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002540 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2541 return 0;
2542
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 if (*(args[1]) == 0) {
2544 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2545 return -1;
2546 }
2547
2548 preg = calloc(1, sizeof(regex_t));
2549 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2550 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2551 return -1;
2552 }
2553
2554 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2555 }
2556 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2557 regex_t *preg;
2558 if (curproxy == &defproxy) {
2559 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2560 return -1;
2561 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002562 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2563 return 0;
2564
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 if (*(args[1]) == 0) {
2566 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2567 return -1;
2568 }
2569
2570 preg = calloc(1, sizeof(regex_t));
2571 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2572 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2573 return -1;
2574 }
2575
2576 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2577 }
2578 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2579 regex_t *preg;
2580 if (curproxy == &defproxy) {
2581 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2582 return -1;
2583 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002584 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2585 return 0;
2586
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 if (*(args[1]) == 0) {
2588 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2589 return -1;
2590 }
2591
2592 preg = calloc(1, sizeof(regex_t));
2593 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2594 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2595 return -1;
2596 }
2597
2598 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2599 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002600 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2601 regex_t *preg;
2602 if (curproxy == &defproxy) {
2603 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2604 return -1;
2605 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002606 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2607 return 0;
2608
Willy Tarreaub8750a82006-09-03 09:56:00 +02002609 if (*(args[1]) == 0) {
2610 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2611 return -1;
2612 }
2613
2614 preg = calloc(1, sizeof(regex_t));
2615 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2616 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2617 return -1;
2618 }
2619
2620 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2621 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2623 if (curproxy == &defproxy) {
2624 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2625 return -1;
2626 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002627 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2628 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629
2630 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2631 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2632 return 0;
2633 }
2634
2635 if (*(args[1]) == 0) {
2636 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2637 return -1;
2638 }
2639
2640 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2641 }
2642 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2643 regex_t *preg;
2644
2645 if (*(args[1]) == 0 || *(args[2]) == 0) {
2646 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2647 file, linenum, args[0]);
2648 return -1;
2649 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002650 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2651 return 0;
2652
Willy Tarreaubaaee002006-06-26 02:48:02 +02002653 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_REPLACE, 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], "rspdel")) { /* delete 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_REMOVE, 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], "rspdeny")) { /* block response header from a regex */
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;
2701
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702 if (*(args[1]) == 0) {
2703 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2704 return -1;
2705 }
2706
2707 preg = calloc(1, sizeof(regex_t));
2708 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2709 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2710 return -1;
2711 }
2712
2713 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2714 if (err) {
2715 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2716 file, linenum, *err);
2717 return -1;
2718 }
2719 }
2720 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2721 regex_t *preg;
2722 if (curproxy == &defproxy) {
2723 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2724 return -1;
2725 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002726 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2727 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728
2729 if (*(args[1]) == 0 || *(args[2]) == 0) {
2730 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2731 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_REPLACE, 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], "rspidel")) { /* delete 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_REMOVE, 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], "rspideny")) { /* block response header from a regex ignoring case */
2776 regex_t *preg;
2777 if (curproxy == &defproxy) {
2778 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2779 return -1;
2780 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002781 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2782 return 0;
2783
Willy Tarreaubaaee002006-06-26 02:48:02 +02002784 if (*(args[1]) == 0) {
2785 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2786 return -1;
2787 }
2788
2789 preg = calloc(1, sizeof(regex_t));
2790 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2791 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2792 return -1;
2793 }
2794
2795 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2796 if (err) {
2797 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2798 file, linenum, *err);
2799 return -1;
2800 }
2801 }
2802 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2803 if (curproxy == &defproxy) {
2804 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2805 return -1;
2806 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002807 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2808 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002809
2810 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2811 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2812 return 0;
2813 }
2814
2815 if (*(args[1]) == 0) {
2816 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2817 return -1;
2818 }
2819
2820 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2821 }
2822 else if (!strcmp(args[0], "errorloc") ||
2823 !strcmp(args[0], "errorloc302") ||
2824 !strcmp(args[0], "errorloc303")) { /* error location */
2825 int errnum, errlen;
2826 char *err;
2827
Willy Tarreau977b8e42006-12-29 14:19:17 +01002828 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2829 return 0;
2830
Willy Tarreaubaaee002006-06-26 02:48:02 +02002831 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002832 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002833 return -1;
2834 }
2835
2836 errnum = atol(args[1]);
2837 if (!strcmp(args[0], "errorloc303")) {
2838 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2839 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2840 } else {
2841 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2842 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2843 }
2844
Willy Tarreau0f772532006-12-23 20:51:41 +01002845 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2846 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002847 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002848 curproxy->errmsg[rc].str = err;
2849 curproxy->errmsg[rc].len = errlen;
2850 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002852 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002853
2854 if (rc >= HTTP_ERR_SIZE) {
2855 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2856 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002857 free(err);
2858 }
2859 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002860 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2861 int errnum, errlen, fd;
2862 char *err;
2863 struct stat stat;
2864
2865 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2866 return 0;
2867
2868 if (*(args[2]) == 0) {
2869 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2870 return -1;
2871 }
2872
2873 fd = open(args[2], O_RDONLY);
2874 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2875 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2876 file, linenum, args[2], args[1]);
2877 if (fd >= 0)
2878 close(fd);
2879 return -1;
2880 }
2881
2882 if (stat.st_size <= BUFSIZE) {
2883 errlen = stat.st_size;
2884 } else {
2885 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2886 file, linenum, args[2], BUFSIZE);
2887 errlen = BUFSIZE;
2888 }
2889
2890 err = malloc(errlen); /* malloc() must succeed during parsing */
2891 errnum = read(fd, err, errlen);
2892 if (errnum != errlen) {
2893 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2894 file, linenum, args[2], args[1]);
2895 close(fd);
2896 free(err);
2897 return -1;
2898 }
2899 close(fd);
2900
2901 errnum = atol(args[1]);
2902 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2903 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002904 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002905 curproxy->errmsg[rc].str = err;
2906 curproxy->errmsg[rc].len = errlen;
2907 break;
2908 }
2909 }
2910
2911 if (rc >= HTTP_ERR_SIZE) {
2912 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2913 file, linenum, errnum);
2914 free(err);
2915 }
2916 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002917 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002918 struct cfg_kw_list *kwl;
2919 int index;
2920
2921 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2922 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2923 if (kwl->kw[index].section != CFG_LISTEN)
2924 continue;
2925 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2926 /* prepare error message just in case */
2927 snprintf(trash, sizeof(trash),
2928 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002929 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2930 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002931 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2932 return -1;
2933 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002934 else if (rc > 0) {
2935 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2936 return 0;
2937 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002938 return 0;
2939 }
2940 }
2941 }
2942
Willy Tarreau6daf3432008-01-22 16:44:08 +01002943 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002944 return -1;
2945 }
2946 return 0;
2947}
2948
2949
2950/*
2951 * This function reads and parses the configuration file given in the argument.
2952 * returns 0 if OK, -1 if error.
2953 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002954int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002955{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002956 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002957 FILE *f;
2958 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002959 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002960 int confsect = CFG_NONE;
2961
2962 struct proxy *curproxy = NULL;
2963 struct server *newsrv = NULL;
2964
2965 if ((f=fopen(file,"r")) == NULL)
2966 return -1;
2967
2968 init_default_instance();
2969
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002970 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002971 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002972 char *end;
2973 char *args[MAX_LINE_ARGS + 1];
2974 char *line = thisline;
2975
Willy Tarreaubaaee002006-06-26 02:48:02 +02002976 linenum++;
2977
2978 end = line + strlen(line);
2979
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002980 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2981 /* Check if we reached the limit and the last char is not \n.
2982 * Watch out for the last line without the terminating '\n'!
2983 */
2984 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2985 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002986 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002987 }
2988
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002990 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002991 line++;
2992
2993 arg = 0;
2994 args[arg] = line;
2995
2996 while (*line && arg < MAX_LINE_ARGS) {
2997 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2998 * C equivalent value. Other combinations left unchanged (eg: \1).
2999 */
3000 if (*line == '\\') {
3001 int skip = 0;
3002 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3003 *line = line[1];
3004 skip = 1;
3005 }
3006 else if (line[1] == 'r') {
3007 *line = '\r';
3008 skip = 1;
3009 }
3010 else if (line[1] == 'n') {
3011 *line = '\n';
3012 skip = 1;
3013 }
3014 else if (line[1] == 't') {
3015 *line = '\t';
3016 skip = 1;
3017 }
3018 else if (line[1] == 'x') {
3019 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3020 unsigned char hex1, hex2;
3021 hex1 = toupper(line[2]) - '0';
3022 hex2 = toupper(line[3]) - '0';
3023 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3024 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3025 *line = (hex1<<4) + hex2;
3026 skip = 3;
3027 }
3028 else {
3029 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003030 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003031 }
3032 }
3033 if (skip) {
3034 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3035 end -= skip;
3036 }
3037 line++;
3038 }
3039 else if (*line == '#' || *line == '\n' || *line == '\r') {
3040 /* end of string, end of loop */
3041 *line = 0;
3042 break;
3043 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003044 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003045 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003046 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003047 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048 line++;
3049 args[++arg] = line;
3050 }
3051 else {
3052 line++;
3053 }
3054 }
3055
3056 /* empty line */
3057 if (!**args)
3058 continue;
3059
Willy Tarreau540abe42007-05-02 20:50:16 +02003060 /* zero out remaining args and ensure that at least one entry
3061 * is zeroed out.
3062 */
3063 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003064 args[arg] = line;
3065 }
3066
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003067 if (!strcmp(args[0], "no")) {
3068 inv = 1;
3069 for (arg=0; *args[arg+1]; arg++)
3070 args[arg] = args[arg+1]; // shift args after inversion
3071 }
3072
3073 if (inv && strcmp(args[0], "option")) {
3074 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003075 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003076 }
3077
Willy Tarreau977b8e42006-12-29 14:19:17 +01003078 if (!strcmp(args[0], "listen") ||
3079 !strcmp(args[0], "frontend") ||
3080 !strcmp(args[0], "backend") ||
3081 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003082 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003084 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003085 cursection = strdup(args[0]);
3086 }
3087 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003089 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003090 cursection = strdup(args[0]);
3091 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003092 /* else it's a section keyword */
3093
3094 switch (confsect) {
3095 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003096 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003097 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098 break;
3099 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003100 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003101 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 break;
3103 default:
3104 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003105 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003108 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003109 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 fclose(f);
3111
3112 /*
3113 * Now, check for the integrity of all that we have collected.
3114 */
3115
3116 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003117 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118
Willy Tarreau55bc0f82009-03-15 14:51:53 +01003119 /* first, we will invert the proxy list order */
3120 curproxy = NULL;
3121 while (proxy) {
3122 struct proxy *next;
3123
3124 next = proxy->next;
3125 proxy->next = curproxy;
3126 curproxy = proxy;
3127 if (!next)
3128 break;
3129 proxy = next;
3130 }
3131
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 if ((curproxy = proxy) == NULL) {
3133 Alert("parsing %s : no <listen> line. Nothing to do !\n",
3134 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003135 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 }
3137
3138 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003139 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003140 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003141
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003143 /* ensure we don't keep listeners uselessly bound */
3144 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 curproxy = curproxy->next;
3146 continue;
3147 }
3148
Willy Tarreauff01a212009-03-15 13:46:16 +01003149 switch (curproxy->mode) {
3150 case PR_MODE_HEALTH:
3151 cfgerr += proxy_cfg_ensure_no_http(curproxy, file);
3152 if (!(curproxy->cap & PR_CAP_FE)) {
3153 Alert("parsing %s : %s '%s' cannot be in health mode as it has no frontend capability.\n",
3154 file, proxy_type_str(curproxy), curproxy->id);
3155 cfgerr++;
3156 }
3157
3158 if (curproxy->srv != NULL)
3159 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
3160 file, proxy_type_str(curproxy), curproxy->id);
3161 break;
3162
3163 case PR_MODE_TCP:
3164 cfgerr += proxy_cfg_ensure_no_http(curproxy, file);
3165 break;
3166
3167 case PR_MODE_HTTP:
3168 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
3169 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
3170 file, curproxy->id);
3171 cfgerr++;
3172 }
3173 break;
3174 }
3175
3176 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003177 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 +01003178 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003179 cfgerr++;
3180 }
Willy Tarreauff01a212009-03-15 13:46:16 +01003181
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003182 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
3183 if (curproxy->lbprm.algo & BE_LB_ALGO) {
3184 if (curproxy->options & PR_O_TRANSP) {
3185 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
3186 file, proxy_type_str(curproxy), curproxy->id);
3187 cfgerr++;
3188 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003190 else if (curproxy->srv == NULL) {
3191 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
3192 file, proxy_type_str(curproxy), curproxy->id);
3193 cfgerr++;
3194 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003196 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
3197 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
3198 file, proxy_type_str(curproxy), curproxy->id);
3199 }
3200 }
3201 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
3202 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
3203 /* If no LB algo is set in a backend, and we're not in
3204 * transparent mode, dispatch mode nor proxy mode, we
3205 * want to use balance roundrobin by default.
3206 */
3207 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3208 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 }
3210 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003211
Willy Tarreau82936582007-11-30 15:20:09 +01003212 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3213 curproxy->options &= ~PR_O_DISABLE404;
3214 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3215 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
3216 }
3217
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003218 /* if a default backend was specified, let's find it */
3219 if (curproxy->defbe.name) {
3220 struct proxy *target;
3221
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003222 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3223 if (!target) {
3224 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3225 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003226 cfgerr++;
3227 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003228 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3229 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003230 } else {
3231 free(curproxy->defbe.name);
3232 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003233 /* we force the backend to be present on at least all of
3234 * the frontend's processes.
3235 */
3236 target->bind_proc = curproxy->bind_proc ?
3237 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 }
3239 }
3240
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003241 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003242 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3243 /* map jump target for ACT_SETBE in req_rep chain */
3244 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003245 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003246 struct proxy *target;
3247
Willy Tarreaua496b602006-12-17 23:15:24 +01003248 if (exp->action != ACT_SETBE)
3249 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003250
3251 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3252 if (!target) {
3253 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3254 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003255 cfgerr++;
3256 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003257 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3258 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003259 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003260 } else {
3261 free((void *)exp->replace);
3262 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003263 /* we force the backend to be present on at least all of
3264 * the frontend's processes.
3265 */
3266 target->bind_proc = curproxy->bind_proc ?
3267 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01003268 }
3269 }
3270 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003271
3272 /* find the target proxy for 'use_backend' rules */
3273 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003274 struct proxy *target;
3275
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003276 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003277
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003278 if (!target) {
3279 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3280 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003281 cfgerr++;
3282 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003283 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3284 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003285 cfgerr++;
3286 } else {
3287 free((void *)rule->be.name);
3288 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003289 /* we force the backend to be present on at least all of
3290 * the frontend's processes.
3291 */
3292 target->bind_proc = curproxy->bind_proc ?
3293 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003294 }
3295 }
3296
Willy Tarreau2738a142006-07-08 17:28:09 +02003297 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003298 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003299 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003300 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003301 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003302 " | While not properly invalid, you will certainly encounter various problems\n"
3303 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003304 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003305 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003306 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003307
Willy Tarreau1fa31262007-12-03 00:36:16 +01003308 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3309 * We must still support older configurations, so let's find out whether those
3310 * parameters have been set or must be copied from contimeouts.
3311 */
3312 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003313 if (!curproxy->timeout.tarpit ||
3314 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003315 /* tarpit timeout not set. We search in the following order:
3316 * default.tarpit, curr.connect, default.connect.
3317 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003318 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003319 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003320 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003321 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003322 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003323 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003324 }
3325 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003326 (!curproxy->timeout.queue ||
3327 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003328 /* queue timeout not set. We search in the following order:
3329 * default.queue, curr.connect, default.connect.
3330 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003331 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003332 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003333 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003334 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003335 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003336 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003337 }
3338 }
3339
Willy Tarreauf3c69202006-07-09 16:42:34 +02003340 if (curproxy->options & PR_O_SSL3_CHK) {
3341 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3342 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3343 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3344 }
3345
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003346 /* The small pools required for the capture lists */
3347 if (curproxy->nb_req_cap)
3348 curproxy->req_cap_pool = create_pool("ptrcap",
3349 curproxy->nb_req_cap * sizeof(char *),
3350 MEM_F_SHARED);
3351 if (curproxy->nb_rsp_cap)
3352 curproxy->rsp_cap_pool = create_pool("ptrcap",
3353 curproxy->nb_rsp_cap * sizeof(char *),
3354 MEM_F_SHARED);
3355
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003356 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3357 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3358 MEM_F_SHARED);
3359
Willy Tarreau86034312006-12-29 00:10:33 +01003360 /* for backwards compatibility with "listen" instances, if
3361 * fullconn is not set but maxconn is set, then maxconn
3362 * is used.
3363 */
3364 if (!curproxy->fullconn)
3365 curproxy->fullconn = curproxy->maxconn;
3366
Willy Tarreaubaaee002006-06-26 02:48:02 +02003367 /* first, we will invert the servers list order */
3368 newsrv = NULL;
3369 while (curproxy->srv) {
3370 struct server *next;
3371
3372 next = curproxy->srv->next;
3373 curproxy->srv->next = newsrv;
3374 newsrv = curproxy->srv;
3375 if (!next)
3376 break;
3377 curproxy->srv = next;
3378 }
3379
Willy Tarreau20697042007-11-15 23:26:18 +01003380 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003381 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003382
Willy Tarreaub625a082007-11-26 01:15:43 +01003383 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003384 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003385 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003386 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3387 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003388 else
3389 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390
3391 if (curproxy->options & PR_O_LOGASAP)
3392 curproxy->to_log &= ~LW_BYTES;
3393
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003395 * ensure that we're not cross-dressing a TCP server into HTTP.
3396 */
3397 newsrv = curproxy->srv;
3398 while (newsrv != NULL) {
3399 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3400 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3401 file, proxy_type_str(curproxy), curproxy->id, linenum);
3402 goto err;
3403 }
3404 newsrv = newsrv->next;
3405 }
3406
3407 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 * If this server supports a maxconn parameter, it needs a dedicated
3409 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003410 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 */
3412 newsrv = curproxy->srv;
3413 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003414 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003415 /* Only 'minconn' was specified, or it was higher than or equal
3416 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3417 * this will avoid further useless expensive computations.
3418 */
3419 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003420 } else if (newsrv->maxconn && !newsrv->minconn) {
3421 /* minconn was not specified, so we set it to maxconn */
3422 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003423 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3424 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003425 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003426 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427 }
3428
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003429 if (newsrv->trackit) {
3430 struct proxy *px;
3431 struct server *srv;
3432 char *pname, *sname;
3433
3434 pname = newsrv->trackit;
3435 sname = strrchr(pname, '/');
3436
3437 if (sname)
3438 *sname++ = '\0';
3439 else {
3440 sname = pname;
3441 pname = NULL;
3442 }
3443
3444 if (pname) {
3445 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3446 if (!px) {
3447 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3448 file, proxy_type_str(curproxy), curproxy->id,
3449 newsrv->id, pname);
3450 return -1;
3451 }
3452 } else
3453 px = curproxy;
3454
3455 srv = findserver(px, sname);
3456 if (!srv) {
3457 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3458 file, proxy_type_str(curproxy), curproxy->id,
3459 newsrv->id, sname);
3460 return -1;
3461 }
3462
3463 if (!(srv->state & SRV_CHECKED)) {
3464 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3465 "tracing as it does not have checks enabled.\n",
3466 file, proxy_type_str(curproxy), curproxy->id,
3467 newsrv->id, px->id, srv->id);
3468 return -1;
3469 }
3470
3471 if (curproxy != px &&
3472 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3473 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3474 "tracing: disable-on-404 option inconsistency.\n",
3475 file, proxy_type_str(curproxy), curproxy->id,
3476 newsrv->id, px->id, srv->id);
3477 return -1;
3478 }
3479
3480 newsrv->tracked = srv;
3481 newsrv->tracknext = srv->tracknext;
3482 srv->tracknext = newsrv;
3483
3484 free(newsrv->trackit);
3485 }
3486
Willy Tarreaubaaee002006-06-26 02:48:02 +02003487 newsrv = newsrv->next;
3488 }
3489
Willy Tarreaue6b98942007-10-29 01:09:36 +01003490 /* adjust this proxy's listeners */
3491 listener = curproxy->listen;
3492 while (listener) {
3493 if (curproxy->options & PR_O_TCP_NOLING)
3494 listener->options |= LI_O_NOLINGER;
3495 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003496 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003497 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003498 listener->accept = event_accept;
3499 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003500 listener->handler = process_session;
3501
3502 if (curproxy->mode == PR_MODE_HTTP)
3503 listener->analysers |= AN_REQ_HTTP_HDR;
3504
Willy Tarreaud869b242009-03-15 14:43:58 +01003505 if (curproxy->tcp_req.inspect_delay ||
3506 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreau3bc13772008-12-07 11:50:35 +01003507 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003508
3509 listener = listener->next;
3510 }
3511
Willy Tarreaubaaee002006-06-26 02:48:02 +02003512 curproxy = curproxy->next;
3513 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003514
Willy Tarreaubaaee002006-06-26 02:48:02 +02003515 if (cfgerr > 0) {
3516 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003517 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003519
3520 /*
3521 * Recount currently required checks.
3522 */
3523
3524 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3525 int optnum;
3526
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003527 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3528 if (curproxy->options & cfg_opts[optnum].val)
3529 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003530
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003531 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3532 if (curproxy->options2 & cfg_opts2[optnum].val)
3533 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003534 }
3535
Willy Tarreaua534fea2008-08-03 12:19:50 +02003536 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003537 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003538 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003539
3540 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003541 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003542 cursection = NULL;
3543 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544}
3545
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003546/*
3547 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3548 * parsing sessions.
3549 */
3550void cfg_register_keywords(struct cfg_kw_list *kwl)
3551{
3552 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3553}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003555/*
3556 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3557 */
3558void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3559{
3560 LIST_DEL(&kwl->list);
3561 LIST_INIT(&kwl->list);
3562}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003563
3564/*
3565 * Local variables:
3566 * c-indent-level: 8
3567 * c-basic-offset: 8
3568 * End:
3569 */