blob: 6defe9e9277d9fd1f14d27639b018ac4baec31ed [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau7c669d72008-06-20 15:04:11 +02004 * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
27#include <common/config.h>
28#include <common/memory.h>
29#include <common/standard.h>
30#include <common/time.h>
31#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020032
33#include <types/capture.h>
34#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreaueb0c6142007-05-07 00:53:22 +020036#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010038#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020040#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010041#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010043#include <proto/protocols.h>
44#include <proto/proto_tcp.h>
45#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010046#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010048#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <proto/task.h>
50
51
Willy Tarreauf3c69202006-07-09 16:42:34 +020052/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
53 * ssl-hello-chk option to ensure that the remote server speaks SSL.
54 *
55 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
56 */
57const char sslv3_client_hello_pkt[] = {
58 "\x16" /* ContentType : 0x16 = Hanshake */
59 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
60 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
61 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
62 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
63 "\x03\x00" /* Hello Version : 0x0300 = v3 */
64 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
65 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
66 "\x00" /* Session ID length : empty (no session ID) */
67 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
68 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
69 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
70 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
71 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
72 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
73 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
74 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
75 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
76 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
77 "\x00\x38" "\x00\x39" "\x00\x3A"
78 "\x01" /* Compression Length : 0x01 = 1 byte for types */
79 "\x00" /* Compression Type : 0x00 = NULL compression */
80};
81
Willy Tarreau13943ab2006-12-31 00:24:10 +010082/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010083struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010084 const char *name;
85 unsigned int val;
86 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010087 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +010088};
89
90/* proxy->options */
91static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +010092{
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010094 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010095 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010096 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010097 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
98 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
99 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
100 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
101 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
102 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
103 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
104 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100106 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
107 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100108#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100109 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
110#endif
111#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100112 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100113#endif
114
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116};
117
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100118/* proxy->options2 */
119static const struct cfg_opt cfg_opts2[] =
120{
121#ifdef CONFIG_HAP_LINUX_SPLICE
122 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
123 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
124 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
125#endif
126 { NULL, 0, 0, 0 }
127};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200128
Willy Tarreau6daf3432008-01-22 16:44:08 +0100129static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200130static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
131int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
132int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
133
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200134/* List head of all known configuration keywords */
135static struct cfg_kw_list cfg_keywords = {
136 .list = LIST_HEAD_INIT(cfg_keywords.list)
137};
138
Willy Tarreaubaaee002006-06-26 02:48:02 +0200139/*
140 * converts <str> to a list of listeners which are dynamically allocated.
141 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
142 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
143 * - <port> is a numerical port from 1 to 65535 ;
144 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
145 * This can be repeated as many times as necessary, separated by a coma.
146 * The <tail> argument is a pointer to a current list which should be appended
147 * to the tail of the new list. The pointer to the new list is returned.
148 */
149static struct listener *str2listener(char *str, struct listener *tail)
150{
151 struct listener *l;
152 char *c, *next, *range, *dupstr;
153 int port, end;
154
155 next = dupstr = strdup(str);
156
157 while (next && *next) {
158 struct sockaddr_storage ss;
159
160 str = next;
161 /* 1) look for the end of the first address */
162 if ((next = strrchr(str, ',')) != NULL) {
163 *next++ = 0;
164 }
165
166 /* 2) look for the addr/port delimiter, it's the last colon. */
167 if ((range = strrchr(str, ':')) == NULL) {
168 Alert("Missing port number: '%s'\n", str);
169 goto fail;
170 }
171
172 *range++ = 0;
173
174 if (strrchr(str, ':') != NULL) {
175 /* IPv6 address contains ':' */
176 memset(&ss, 0, sizeof(ss));
177 ss.ss_family = AF_INET6;
178
179 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
180 Alert("Invalid server address: '%s'\n", str);
181 goto fail;
182 }
183 }
184 else {
185 memset(&ss, 0, sizeof(ss));
186 ss.ss_family = AF_INET;
187
188 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
189 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
190 }
191 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
192 struct hostent *he;
193
194 if ((he = gethostbyname(str)) == NULL) {
195 Alert("Invalid server name: '%s'\n", str);
196 goto fail;
197 }
198 else
199 ((struct sockaddr_in *)&ss)->sin_addr =
200 *(struct in_addr *) *(he->h_addr_list);
201 }
202 }
203
204 /* 3) look for the port-end delimiter */
205 if ((c = strchr(range, '-')) != NULL) {
206 *c++ = 0;
207 end = atol(c);
208 }
209 else {
210 end = atol(range);
211 }
212
213 port = atol(range);
214
215 if (port < 1 || port > 65535) {
216 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
217 goto fail;
218 }
219
220 if (end < 1 || end > 65535) {
221 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
222 goto fail;
223 }
224
225 for (; port <= end; port++) {
226 l = (struct listener *)calloc(1, sizeof(struct listener));
227 l->next = tail;
228 tail = l;
229
230 l->fd = -1;
231 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100232 l->state = LI_INIT;
233
234 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100236 tcpv6_add_listener(l);
237 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100239 tcpv4_add_listener(l);
240 }
241 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242 } /* end for(port) */
243 } /* end while(next) */
244 free(dupstr);
245 return tail;
246 fail:
247 free(dupstr);
248 return NULL;
249}
250
Willy Tarreau977b8e42006-12-29 14:19:17 +0100251/*
252 * Sends a warning if proxy <proxy> does not have at least one of the
253 * capabilities in <cap>. An optionnal <hint> may be added at the end
254 * of the warning to help the user. Returns 1 if a warning was emitted
255 * or 0 if the condition is valid.
256 */
257int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
258{
259 char *msg;
260
261 switch (cap) {
262 case PR_CAP_BE: msg = "no backend"; break;
263 case PR_CAP_FE: msg = "no frontend"; break;
264 case PR_CAP_RS: msg = "no ruleset"; break;
265 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
266 default: msg = "not enough"; break;
267 }
268
269 if (!(proxy->cap & cap)) {
270 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100271 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100272 return 1;
273 }
274 return 0;
275}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200276
277/*
278 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
279 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100280int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281{
282
283 if (!strcmp(args[0], "global")) { /* new section */
284 /* no option, nothing special to do */
285 return 0;
286 }
287 else if (!strcmp(args[0], "daemon")) {
288 global.mode |= MODE_DAEMON;
289 }
290 else if (!strcmp(args[0], "debug")) {
291 global.mode |= MODE_DEBUG;
292 }
293 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100294 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200296 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100297 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200298 }
299 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100300 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100303 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304 }
305 else if (!strcmp(args[0], "quiet")) {
306 global.mode |= MODE_QUIET;
307 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200308 else if (!strcmp(args[0], "tune.maxpollevents")) {
309 if (global.tune.maxpollevents != 0) {
310 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
311 return 0;
312 }
313 if (*(args[1]) == 0) {
314 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
315 return -1;
316 }
317 global.tune.maxpollevents = atol(args[1]);
318 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100319 else if (!strcmp(args[0], "tune.maxaccept")) {
320 if (global.tune.maxaccept != 0) {
321 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
322 return 0;
323 }
324 if (*(args[1]) == 0) {
325 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
326 return -1;
327 }
328 global.tune.maxaccept = atol(args[1]);
329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200330 else if (!strcmp(args[0], "uid")) {
331 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200332 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200333 return 0;
334 }
335 if (*(args[1]) == 0) {
336 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
337 return -1;
338 }
339 global.uid = atol(args[1]);
340 }
341 else if (!strcmp(args[0], "gid")) {
342 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200343 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200344 return 0;
345 }
346 if (*(args[1]) == 0) {
347 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
348 return -1;
349 }
350 global.gid = atol(args[1]);
351 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200352 /* user/group name handling */
353 else if (!strcmp(args[0], "user")) {
354 struct passwd *ha_user;
355 if (global.uid != 0) {
356 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
357 return 0;
358 }
359 errno = 0;
360 ha_user = getpwnam(args[1]);
361 if (ha_user != NULL) {
362 global.uid = (int)ha_user->pw_uid;
363 }
364 else {
365 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
366 exit(1);
367 }
368 }
369 else if (!strcmp(args[0], "group")) {
370 struct group *ha_group;
371 if (global.gid != 0) {
372 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
373 return 0;
374 }
375 errno = 0;
376 ha_group = getgrnam(args[1]);
377 if (ha_group != NULL) {
378 global.gid = (int)ha_group->gr_gid;
379 }
380 else {
381 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
382 exit(1);
383 }
384 }
385 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200386 else if (!strcmp(args[0], "nbproc")) {
387 if (global.nbproc != 0) {
388 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
389 return 0;
390 }
391 if (*(args[1]) == 0) {
392 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
393 return -1;
394 }
395 global.nbproc = atol(args[1]);
396 }
397 else if (!strcmp(args[0], "maxconn")) {
398 if (global.maxconn != 0) {
399 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
400 return 0;
401 }
402 if (*(args[1]) == 0) {
403 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
404 return -1;
405 }
406 global.maxconn = atol(args[1]);
407#ifdef SYSTEM_MAXCONN
408 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
409 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);
410 global.maxconn = DEFAULT_MAXCONN;
411 }
412#endif /* SYSTEM_MAXCONN */
413 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100414 else if (!strcmp(args[0], "maxpipes")) {
415 if (global.maxpipes != 0) {
416 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
417 return 0;
418 }
419 if (*(args[1]) == 0) {
420 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
421 return -1;
422 }
423 global.maxpipes = atol(args[1]);
424 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200425 else if (!strcmp(args[0], "ulimit-n")) {
426 if (global.rlimit_nofile != 0) {
427 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
428 return 0;
429 }
430 if (*(args[1]) == 0) {
431 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
432 return -1;
433 }
434 global.rlimit_nofile = atol(args[1]);
435 }
436 else if (!strcmp(args[0], "chroot")) {
437 if (global.chroot != NULL) {
438 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
439 return 0;
440 }
441 if (*(args[1]) == 0) {
442 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
443 return -1;
444 }
445 global.chroot = strdup(args[1]);
446 }
447 else if (!strcmp(args[0], "pidfile")) {
448 if (global.pidfile != NULL) {
449 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
450 return 0;
451 }
452 if (*(args[1]) == 0) {
453 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
454 return -1;
455 }
456 global.pidfile = strdup(args[1]);
457 }
458 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100459 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460 int facility, level;
461
462 if (*(args[1]) == 0 || *(args[2]) == 0) {
463 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
464 return -1;
465 }
466
467 facility = get_log_facility(args[2]);
468 if (facility < 0) {
469 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
470 exit(1);
471 }
472
473 level = 7; /* max syslog level = debug */
474 if (*(args[3])) {
475 level = get_log_level(args[3]);
476 if (level < 0) {
477 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
478 exit(1);
479 }
480 }
481
Robert Tsai81ae1952007-12-05 10:47:29 +0100482 if (args[1][0] == '/') {
483 logsrv.u.addr.sa_family = AF_UNIX;
484 logsrv.u.un = *str2sun(args[1]);
485 } else {
486 logsrv.u.addr.sa_family = AF_INET;
487 logsrv.u.in = *str2sa(args[1]);
488 if (!logsrv.u.in.sin_port)
489 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200491
492 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100493 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200494 global.logfac1 = facility;
495 global.loglev1 = level;
496 }
497 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100498 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200499 global.logfac2 = facility;
500 global.loglev2 = level;
501 }
502 else {
503 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
504 return -1;
505 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200506 }
507 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
508 if (global.spread_checks != 0) {
509 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
510 return 0;
511 }
512 if (*(args[1]) == 0) {
513 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
514 return -1;
515 }
516 global.spread_checks = atol(args[1]);
517 if (global.spread_checks < 0 || global.spread_checks > 50) {
518 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
519 return -1;
520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200521 }
522 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200523 struct cfg_kw_list *kwl;
524 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200525 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200526
527 list_for_each_entry(kwl, &cfg_keywords.list, list) {
528 for (index = 0; kwl->kw[index].kw != NULL; index++) {
529 if (kwl->kw[index].section != CFG_GLOBAL)
530 continue;
531 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
532 /* prepare error message just in case */
533 snprintf(trash, sizeof(trash),
534 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200535 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
536 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200537 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
538 return -1;
539 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200540 else if (rc > 0) {
541 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
542 return 0;
543 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200544 return 0;
545 }
546 }
547 }
548
Willy Tarreaubaaee002006-06-26 02:48:02 +0200549 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
550 return -1;
551 }
552 return 0;
553}
554
555
556static void init_default_instance()
557{
558 memset(&defproxy, 0, sizeof(defproxy));
559 defproxy.mode = PR_MODE_TCP;
560 defproxy.state = PR_STNEW;
561 defproxy.maxconn = cfg_maxpconn;
562 defproxy.conn_retries = CONN_RETRIES;
563 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200564
565 LIST_INIT(&defproxy.pendconns);
566 LIST_INIT(&defproxy.acl);
567 LIST_INIT(&defproxy.block_cond);
568 LIST_INIT(&defproxy.mon_fail_cond);
569 LIST_INIT(&defproxy.switching_rules);
570
Willy Tarreau3a70f942008-02-15 11:15:34 +0100571 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200572}
573
574/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100575 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
576 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100578int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579{
580 static struct proxy *curproxy = NULL;
581 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200582 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100583 int rc;
584 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585
Willy Tarreau977b8e42006-12-29 14:19:17 +0100586 if (!strcmp(args[0], "listen"))
587 rc = PR_CAP_LISTEN;
588 else if (!strcmp(args[0], "frontend"))
589 rc = PR_CAP_FE | PR_CAP_RS;
590 else if (!strcmp(args[0], "backend"))
591 rc = PR_CAP_BE | PR_CAP_RS;
592 else if (!strcmp(args[0], "ruleset"))
593 rc = PR_CAP_RS;
594 else
595 rc = PR_CAP_NONE;
596
597 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598 if (!*args[1]) {
599 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
600 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
601 file, linenum, args[0]);
602 return -1;
603 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200604
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100605 err = invalid_char(args[1]);
606 if (err) {
607 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
608 file, linenum, *err, args[0], args[1]);
609 return -1;
610 }
611
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200612 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
613 /*
614 * If there are two proxies with the same name only following
615 * combinations are allowed:
616 *
617 * listen backend frontend ruleset
618 * listen - - - -
619 * backend - - OK -
620 * frontend - OK - -
621 * ruleset - - - -
622 */
623
624 if (!strcmp(curproxy->id, args[1]) &&
625 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
626 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100627 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
628 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200629 }
630 }
631
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
633 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
634 return -1;
635 }
636
637 curproxy->next = proxy;
638 proxy = curproxy;
639 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200640 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200641 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200642 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100643 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200644 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200645 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646
Willy Tarreauee991362007-05-14 14:37:50 +0200647 /* Timeouts are defined as -1, so we cannot use the zeroed area
648 * as a default value.
649 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100650 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200651
652 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200653 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100654 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200655
656 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100657 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658 curproxy->listen = str2listener(args[2], curproxy->listen);
659 if (!curproxy->listen)
660 return -1;
661 global.maxsock++;
662 }
663
664 /* set default values */
665 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100667 curproxy->options2 = defproxy.options2;
Willy Tarreau31682232007-11-29 15:38:04 +0100668 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200669 curproxy->except_net = defproxy.except_net;
670 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200672 if (defproxy.fwdfor_hdr_len) {
673 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
674 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
675 }
676
Willy Tarreau977b8e42006-12-29 14:19:17 +0100677 if (curproxy->cap & PR_CAP_FE) {
678 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100679 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100680
681 /* initialize error relocations */
682 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
683 if (defproxy.errmsg[rc].str)
684 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
685 }
686
687 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
688 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200689
Willy Tarreau977b8e42006-12-29 14:19:17 +0100690 if (curproxy->cap & PR_CAP_BE) {
691 curproxy->fullconn = defproxy.fullconn;
692 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693
Willy Tarreau977b8e42006-12-29 14:19:17 +0100694 if (defproxy.check_req)
695 curproxy->check_req = strdup(defproxy.check_req);
696 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200697
Willy Tarreau977b8e42006-12-29 14:19:17 +0100698 if (defproxy.cookie_name)
699 curproxy->cookie_name = strdup(defproxy.cookie_name);
700 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100701
702 if (defproxy.url_param_name)
703 curproxy->url_param_name = strdup(defproxy.url_param_name);
704 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100705 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200706
Willy Tarreau977b8e42006-12-29 14:19:17 +0100707 if (curproxy->cap & PR_CAP_RS) {
708 if (defproxy.capture_name)
709 curproxy->capture_name = strdup(defproxy.capture_name);
710 curproxy->capture_namelen = defproxy.capture_namelen;
711 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200713
Willy Tarreau977b8e42006-12-29 14:19:17 +0100714 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100715 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100716 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100717 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100718 curproxy->uri_auth = defproxy.uri_auth;
719 curproxy->mon_net = defproxy.mon_net;
720 curproxy->mon_mask = defproxy.mon_mask;
721 if (defproxy.monitor_uri)
722 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
723 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100724 if (defproxy.defbe.name)
725 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100726 }
727
728 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100729 curproxy->timeout.connect = defproxy.timeout.connect;
730 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100731 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100732 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100733 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100734 curproxy->source_addr = defproxy.source_addr;
735 }
736
Willy Tarreaubaaee002006-06-26 02:48:02 +0200737 curproxy->mode = defproxy.mode;
738 curproxy->logfac1 = defproxy.logfac1;
739 curproxy->logsrv1 = defproxy.logsrv1;
740 curproxy->loglev1 = defproxy.loglev1;
741 curproxy->logfac2 = defproxy.logfac2;
742 curproxy->logsrv2 = defproxy.logsrv2;
743 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200744 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100745 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
746 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200747
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748 return 0;
749 }
750 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
751 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100752 /* FIXME-20070101: we should do this too at the end of the
753 * config parsing to free all default values.
754 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200755 free(defproxy.check_req);
756 free(defproxy.cookie_name);
757 free(defproxy.url_param_name);
758 free(defproxy.capture_name);
759 free(defproxy.monitor_uri);
760 free(defproxy.defbe.name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200761 free(defproxy.fwdfor_hdr_name);
762 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100763
Willy Tarreaua534fea2008-08-03 12:19:50 +0200764 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
765 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100766
Willy Tarreaubaaee002006-06-26 02:48:02 +0200767 /* we cannot free uri_auth because it might already be used */
768 init_default_instance();
769 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100770 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 return 0;
772 }
773 else if (curproxy == NULL) {
774 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
775 return -1;
776 }
777
Willy Tarreau977b8e42006-12-29 14:19:17 +0100778
779 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100781 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 if (curproxy == &defproxy) {
783 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
784 return -1;
785 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100786 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
787 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200788
789 if (strchr(args[1], ':') == NULL) {
790 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
791 file, linenum, args[0]);
792 return -1;
793 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100794
795 last_listen = curproxy->listen;
796 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200797 if (!curproxy->listen)
798 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100799 if (*args[2]) {
800#ifdef CONFIG_HAP_LINUX_TPROXY
801 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
802 struct listener *l;
803
804 for (l = curproxy->listen; l != last_listen; l = l->next)
805 l->options |= LI_O_FOREIGN;
806 }
807 else {
808 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
809 file, linenum, args[0]);
810 return -1;
811 }
812#else
813 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
814 file, linenum, args[0]);
815 return -1;
816#endif
817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200818 global.maxsock++;
819 return 0;
820 }
821 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
822 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
823 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
824 file, linenum, args[0]);
825 return -1;
826 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100827 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
828 return 0;
829
Willy Tarreaubaaee002006-06-26 02:48:02 +0200830 /* flush useless bits */
831 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
832 return 0;
833 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200834 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100835 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
836 return 0;
837
Willy Tarreau1c47f852006-07-09 08:22:27 +0200838 if (!*args[1]) {
839 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
840 file, linenum, args[0]);
841 return -1;
842 }
843
Willy Tarreaua534fea2008-08-03 12:19:50 +0200844 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100845 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200846 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100847 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200848 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
849
850 return 0;
851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200852 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
853 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
854 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
855 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
856 else {
857 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
858 return -1;
859 }
860 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100861 else if (!strcmp(args[0], "id")) {
862 struct proxy *target;
863
864 if (curproxy == &defproxy) {
865 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
866 file, linenum, args[0]);
867 return -1;
868 }
869
870 if (!*args[1]) {
871 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
872 file, linenum, args[0]);
873 return -1;
874 }
875
876 curproxy->uuid = atol(args[1]);
877
878 if (curproxy->uuid < 1001) {
879 Alert("parsing [%s:%d]: custom id has to be > 1000",
880 file, linenum);
881 return -1;
882 }
883
884 for (target = proxy; target; target = target->next)
885 if (curproxy != target && curproxy->uuid == target->uuid) {
886 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
887 file, linenum, curproxy->id, target->id);
888 return -1;
889 }
890 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
892 curproxy->state = PR_STSTOPPED;
893 }
894 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
895 curproxy->state = PR_STNEW;
896 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200897 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200898 if (curproxy == &defproxy) {
899 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
900 return -1;
901 }
902
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100903 err = invalid_char(args[1]);
904 if (err) {
905 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
906 file, linenum, *err, args[1]);
907 return -1;
908 }
909
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200910 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
911 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
912 file, linenum, args[1]);
913 return -1;
914 }
915 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916 else if (!strcmp(args[0], "cookie")) { /* cookie name */
917 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918
Willy Tarreau977b8e42006-12-29 14:19:17 +0100919 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
920 return 0;
921
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 if (*(args[1]) == 0) {
923 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
924 file, linenum, args[0]);
925 return -1;
926 }
Willy Tarreaua534fea2008-08-03 12:19:50 +0200927
928 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 curproxy->cookie_name = strdup(args[1]);
930 curproxy->cookie_len = strlen(curproxy->cookie_name);
931
932 cur_arg = 2;
933 while (*(args[cur_arg])) {
934 if (!strcmp(args[cur_arg], "rewrite")) {
935 curproxy->options |= PR_O_COOK_RW;
936 }
937 else if (!strcmp(args[cur_arg], "indirect")) {
938 curproxy->options |= PR_O_COOK_IND;
939 }
940 else if (!strcmp(args[cur_arg], "insert")) {
941 curproxy->options |= PR_O_COOK_INS;
942 }
943 else if (!strcmp(args[cur_arg], "nocache")) {
944 curproxy->options |= PR_O_COOK_NOC;
945 }
946 else if (!strcmp(args[cur_arg], "postonly")) {
947 curproxy->options |= PR_O_COOK_POST;
948 }
949 else if (!strcmp(args[cur_arg], "prefix")) {
950 curproxy->options |= PR_O_COOK_PFX;
951 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200952 else if (!strcmp(args[cur_arg], "domain")) {
953 if (!*args[cur_arg + 1]) {
954 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
955 file, linenum, args[cur_arg]);
956 return -1;
957 }
958
959 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
960 /* rfc2109, 4.3.2 Rejecting Cookies */
961 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
962 " dots or does not start with a dot.\n",
963 file, linenum, args[cur_arg + 1]);
964 return -1;
965 }
966
967 err = invalid_domainchar(args[cur_arg + 1]);
968 if (err) {
969 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
970 file, linenum, *err, args[cur_arg + 1]);
971 return -1;
972 }
973
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +0200974 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200975 cur_arg++;
976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200978 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +0200979 file, linenum, args[0]);
980 return -1;
981 }
982 cur_arg++;
983 }
984 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
985 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
986 file, linenum);
987 return -1;
988 }
989
990 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
991 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
992 file, linenum);
993 return -1;
994 }
995 }/* end else if (!strcmp(args[0], "cookie")) */
996 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997
Willy Tarreau977b8e42006-12-29 14:19:17 +0100998 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
999 return 0;
1000
Willy Tarreaubaaee002006-06-26 02:48:02 +02001001 if (*(args[5]) == 0) {
1002 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1003 file, linenum, args[0]);
1004 return -1;
1005 }
1006 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001007 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001008 curproxy->appsession_name = strdup(args[1]);
1009 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1010 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001011 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1012 if (err) {
1013 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1014 file, linenum, *err, args[0]);
1015 return -1;
1016 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001017 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001018
Willy Tarreau51041c72007-09-09 21:56:53 +02001019 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1020 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021 return -1;
1022 }
1023 } /* Url App Session */
1024 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001025 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1026 return 0;
1027
Willy Tarreaubaaee002006-06-26 02:48:02 +02001028 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001029 if (*(args[4]) == 0) {
1030 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1031 file, linenum, args[0]);
1032 return -1;
1033 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001034 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001035 curproxy->capture_name = strdup(args[2]);
1036 curproxy->capture_namelen = strlen(curproxy->capture_name);
1037 curproxy->capture_len = atol(args[4]);
1038 if (curproxy->capture_len >= CAPTURE_LEN) {
1039 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1040 file, linenum, CAPTURE_LEN - 1);
1041 curproxy->capture_len = CAPTURE_LEN - 1;
1042 }
1043 curproxy->to_log |= LW_COOKIE;
1044 }
1045 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1046 struct cap_hdr *hdr;
1047
1048 if (curproxy == &defproxy) {
1049 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1050 return -1;
1051 }
1052
1053 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1054 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1055 file, linenum, args[0], args[1]);
1056 return -1;
1057 }
1058
1059 hdr = calloc(sizeof(struct cap_hdr), 1);
1060 hdr->next = curproxy->req_cap;
1061 hdr->name = strdup(args[3]);
1062 hdr->namelen = strlen(args[3]);
1063 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001064 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 hdr->index = curproxy->nb_req_cap++;
1066 curproxy->req_cap = hdr;
1067 curproxy->to_log |= LW_REQHDR;
1068 }
1069 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1070 struct cap_hdr *hdr;
1071
1072 if (curproxy == &defproxy) {
1073 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1074 return -1;
1075 }
1076
1077 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1078 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1079 file, linenum, args[0], args[1]);
1080 return -1;
1081 }
1082 hdr = calloc(sizeof(struct cap_hdr), 1);
1083 hdr->next = curproxy->rsp_cap;
1084 hdr->name = strdup(args[3]);
1085 hdr->namelen = strlen(args[3]);
1086 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001087 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 hdr->index = curproxy->nb_rsp_cap++;
1089 curproxy->rsp_cap = hdr;
1090 curproxy->to_log |= LW_RSPHDR;
1091 }
1092 else {
1093 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1094 file, linenum, args[0]);
1095 return -1;
1096 }
1097 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001099 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1100 return 0;
1101
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 if (*(args[1]) == 0) {
1103 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1104 file, linenum, args[0]);
1105 return -1;
1106 }
1107 curproxy->conn_retries = atol(args[1]);
1108 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001109 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1110 int pol = ACL_COND_NONE;
1111 struct acl_cond *cond;
1112
Willy Tarreaub099aca2008-10-12 17:26:37 +02001113 if (curproxy == &defproxy) {
1114 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1115 return -1;
1116 }
1117
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001118 if (!strcmp(args[1], "if"))
1119 pol = ACL_COND_IF;
1120 else if (!strcmp(args[1], "unless"))
1121 pol = ACL_COND_UNLESS;
1122
1123 if (pol == ACL_COND_NONE) {
1124 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1125 file, linenum, args[0]);
1126 return -1;
1127 }
1128
1129 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1130 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1131 file, linenum);
1132 return -1;
1133 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001134 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001135 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1136 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001137 else if (!strcmp(args[0], "redirect")) {
1138 int pol = ACL_COND_NONE;
1139 struct acl_cond *cond;
1140 struct redirect_rule *rule;
1141 int cur_arg;
1142 int type = REDIRECT_TYPE_NONE;
1143 int code = 302;
1144 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001145 char *cookie = NULL;
1146 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001147 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001148
1149 cur_arg = 1;
1150 while (*(args[cur_arg])) {
1151 if (!strcmp(args[cur_arg], "location")) {
1152 if (!*args[cur_arg + 1]) {
1153 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1154 file, linenum, args[0], args[cur_arg]);
1155 return -1;
1156 }
1157
1158 type = REDIRECT_TYPE_LOCATION;
1159 cur_arg++;
1160 destination = args[cur_arg];
1161 }
1162 else if (!strcmp(args[cur_arg], "prefix")) {
1163 if (!*args[cur_arg + 1]) {
1164 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1165 file, linenum, args[0], args[cur_arg]);
1166 return -1;
1167 }
1168
1169 type = REDIRECT_TYPE_PREFIX;
1170 cur_arg++;
1171 destination = args[cur_arg];
1172 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001173 else if (!strcmp(args[cur_arg], "set-cookie")) {
1174 if (!*args[cur_arg + 1]) {
1175 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1176 file, linenum, args[0], args[cur_arg]);
1177 return -1;
1178 }
1179
1180 cur_arg++;
1181 cookie = args[cur_arg];
1182 cookie_set = 1;
1183 }
1184 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1185 if (!*args[cur_arg + 1]) {
1186 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1187 file, linenum, args[0], args[cur_arg]);
1188 return -1;
1189 }
1190
1191 cur_arg++;
1192 cookie = args[cur_arg];
1193 cookie_set = 0;
1194 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001195 else if (!strcmp(args[cur_arg],"code")) {
1196 if (!*args[cur_arg + 1]) {
1197 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1198 file, linenum, args[0]);
1199 return -1;
1200 }
1201 cur_arg++;
1202 code = atol(args[cur_arg]);
1203 if (code < 301 || code > 303) {
1204 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1205 file, linenum, args[0], code);
1206 return -1;
1207 }
1208 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001209 else if (!strcmp(args[cur_arg],"drop-query")) {
1210 flags |= REDIRECT_FLAG_DROP_QS;
1211 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001212 else if (!strcmp(args[cur_arg], "if")) {
1213 pol = ACL_COND_IF;
1214 cur_arg++;
1215 break;
1216 }
1217 else if (!strcmp(args[cur_arg], "unless")) {
1218 pol = ACL_COND_UNLESS;
1219 cur_arg++;
1220 break;
1221 }
1222 else {
1223 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1224 file, linenum, args[0], args[cur_arg]);
1225 return -1;
1226 }
1227 cur_arg++;
1228 }
1229
1230 if (type == REDIRECT_TYPE_NONE) {
1231 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1232 file, linenum, args[0]);
1233 return -1;
1234 }
1235
1236 if (pol == ACL_COND_NONE) {
1237 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1238 file, linenum, args[0]);
1239 return -1;
1240 }
1241
1242 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1243 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1244 file, linenum, args[0]);
1245 return -1;
1246 }
1247
Willy Tarreaua9802632008-07-25 19:13:19 +02001248 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001249 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1250 rule->cond = cond;
1251 rule->rdr_str = strdup(destination);
1252 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001253 if (cookie) {
1254 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1255 * a clear consists in appending "; Max-Age=0" at the end.
1256 */
1257 rule->cookie_len = strlen(cookie);
1258 if (cookie_set)
1259 rule->cookie_str = strdup(cookie);
1260 else {
1261 rule->cookie_str = malloc(rule->cookie_len + 12);
1262 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1263 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1264 rule->cookie_len += 11;
1265 }
1266 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001267 rule->type = type;
1268 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001269 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001270 LIST_INIT(&rule->list);
1271 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1272 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001273 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1274 int pol = ACL_COND_NONE;
1275 struct acl_cond *cond;
1276 struct switching_rule *rule;
1277
Willy Tarreaub099aca2008-10-12 17:26:37 +02001278 if (curproxy == &defproxy) {
1279 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1280 return -1;
1281 }
1282
Willy Tarreau55ea7572007-06-17 19:56:27 +02001283 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1284 return 0;
1285
1286 if (*(args[1]) == 0) {
1287 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1288 return -1;
1289 }
1290
1291 if (!strcmp(args[2], "if"))
1292 pol = ACL_COND_IF;
1293 else if (!strcmp(args[2], "unless"))
1294 pol = ACL_COND_UNLESS;
1295
1296 if (pol == ACL_COND_NONE) {
1297 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1298 file, linenum, args[0]);
1299 return -1;
1300 }
1301
1302 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001303 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001304 file, linenum);
1305 return -1;
1306 }
1307
Willy Tarreaua9802632008-07-25 19:13:19 +02001308 cond->line = linenum;
1309 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001310 struct acl *acl;
1311 const char *name;
1312
1313 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1314 name = acl ? acl->name : "(unknown)";
1315 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1316 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001317 }
1318
Willy Tarreau55ea7572007-06-17 19:56:27 +02001319 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1320 rule->cond = cond;
1321 rule->be.name = strdup(args[1]);
1322 LIST_INIT(&rule->list);
1323 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1324 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001325 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001326 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1327 return 0;
1328
Willy Tarreaubaaee002006-06-26 02:48:02 +02001329 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1330 curproxy->uri_auth = NULL; /* we must detach from the default config */
1331
1332 if (*(args[1]) == 0) {
1333 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1334 return -1;
1335 } else if (!strcmp(args[1], "uri")) {
1336 if (*(args[2]) == 0) {
1337 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1338 return -1;
1339 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1340 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1341 return -1;
1342 }
1343 } else if (!strcmp(args[1], "realm")) {
1344 if (*(args[2]) == 0) {
1345 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1346 return -1;
1347 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1348 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1349 return -1;
1350 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001351 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001352 unsigned interval;
1353
1354 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1355 if (err) {
1356 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1357 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001358 return -1;
1359 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1360 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1361 return -1;
1362 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363 } else if (!strcmp(args[1], "auth")) {
1364 if (*(args[2]) == 0) {
1365 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1366 return -1;
1367 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1368 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1369 return -1;
1370 }
1371 } else if (!strcmp(args[1], "scope")) {
1372 if (*(args[2]) == 0) {
1373 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1374 return -1;
1375 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1376 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1377 return -1;
1378 }
1379 } else if (!strcmp(args[1], "enable")) {
1380 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1381 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1382 return -1;
1383 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001384 } else if (!strcmp(args[1], "hide-version")) {
1385 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1386 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1387 return -1;
1388 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001390 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391 file, linenum, args[0]);
1392 return -1;
1393 }
1394 }
1395 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001396 int optnum;
1397
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001398 if (*(args[1]) == '\0') {
1399 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1400 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 return -1;
1402 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001403
1404 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1405 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1406 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1407 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001408
1409 if (!inv)
1410 curproxy->options |= cfg_opts[optnum].val;
1411 else
1412 curproxy->options &= ~cfg_opts[optnum].val;
1413
Willy Tarreau13943ab2006-12-31 00:24:10 +01001414 return 0;
1415 }
1416 }
1417
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001418 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1419 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
1420 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
1421 return 0;
1422
1423 if (!inv)
1424 curproxy->options2 |= cfg_opts2[optnum].val;
1425 else
1426 curproxy->options2 &= ~cfg_opts2[optnum].val;
1427
1428 return 0;
1429 }
1430 }
1431
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001432 if (inv) {
1433 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1434 file, linenum, args[1]);
1435 return -1;
1436 }
1437
Willy Tarreau13943ab2006-12-31 00:24:10 +01001438 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439 /* generate a complete HTTP log */
1440 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1441 else if (!strcmp(args[1], "tcplog"))
1442 /* generate a detailed TCP log */
1443 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444 else if (!strcmp(args[1], "tcpka")) {
1445 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001446 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1447 return 0;
1448
1449 if (curproxy->cap & PR_CAP_FE)
1450 curproxy->options |= PR_O_TCP_CLI_KA;
1451 if (curproxy->cap & PR_CAP_BE)
1452 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453 }
1454 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001455 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1456 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001458 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001459 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001460 curproxy->options &= ~PR_O_SMTP_CHK;
1461 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462 if (!*args[2]) { /* no argument */
1463 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1464 curproxy->check_len = strlen(DEF_CHECK_REQ);
1465 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001466 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467 curproxy->check_req = (char *)malloc(reqlen);
1468 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1469 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1470 } else { /* more arguments : METHOD URI [HTTP_VER] */
1471 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1472 if (*args[4])
1473 reqlen += strlen(args[4]);
1474 else
1475 reqlen += strlen("HTTP/1.0");
1476
1477 curproxy->check_req = (char *)malloc(reqlen);
1478 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1479 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1480 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001481 }
1482 else if (!strcmp(args[1], "ssl-hello-chk")) {
1483 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001484 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1485 return 0;
1486
Willy Tarreaua534fea2008-08-03 12:19:50 +02001487 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001488 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001489 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001490 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491 }
Willy Tarreau23677902007-05-08 23:50:35 +02001492 else if (!strcmp(args[1], "smtpchk")) {
1493 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001494 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001495 curproxy->options &= ~PR_O_HTTP_CHK;
1496 curproxy->options &= ~PR_O_SSL3_CHK;
1497 curproxy->options |= PR_O_SMTP_CHK;
1498
1499 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1500 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1501 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1502 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1503 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1504 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1505 curproxy->check_req = (char *)malloc(reqlen);
1506 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1507 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1508 } else {
1509 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1510 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1511 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1512 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1513 }
1514 }
1515 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001516 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001517 int cur_arg;
1518
1519 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1520 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001521 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001522
1523 curproxy->options |= PR_O_FWDFOR;
1524
1525 free(curproxy->fwdfor_hdr_name);
1526 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1527 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1528
1529 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1530 cur_arg = 2;
1531 while (*(args[cur_arg])) {
1532 if (!strcmp(args[cur_arg], "except")) {
1533 /* suboption except - needs additional argument for it */
1534 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1535 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1536 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001537 return -1;
1538 }
1539 /* flush useless bits */
1540 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001541 cur_arg += 2;
1542 } else if (!strcmp(args[cur_arg], "header")) {
1543 /* suboption header - needs additional argument for it */
1544 if (*(args[cur_arg+1]) == 0) {
1545 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1546 file, linenum, args[0], args[1], args[cur_arg]);
1547 return -1;
1548 }
1549 free(curproxy->fwdfor_hdr_name);
1550 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1551 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1552 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001553 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001554 /* unknown suboption - catchall */
1555 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1556 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001557 return -1;
1558 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001559 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561 else {
1562 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1563 return -1;
1564 }
1565 return 0;
1566 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001567 else if (!strcmp(args[0], "default_backend")) {
1568 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1569 return 0;
1570
1571 if (*(args[1]) == 0) {
1572 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1573 return -1;
1574 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001575 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001576 curproxy->defbe.name = strdup(args[1]);
1577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001579 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1580 return 0;
1581
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001582 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1583 file, linenum, args[0]);
1584
Willy Tarreaubaaee002006-06-26 02:48:02 +02001585 /* enable reconnections to dispatch */
1586 curproxy->options |= PR_O_REDISP;
1587 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001588 else if (!strcmp(args[0], "http-check")) {
1589 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1590 return 0;
1591
1592 if (strcmp(args[1], "disable-on-404") == 0) {
1593 /* enable a graceful server shutdown on an HTTP 404 response */
1594 curproxy->options |= PR_O_DISABLE404;
1595 }
1596 else {
1597 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1598 return -1;
1599 }
1600 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001601 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001602 if (curproxy == &defproxy) {
1603 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1604 return -1;
1605 }
1606
Willy Tarreaub80c2302007-11-30 20:51:32 +01001607 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1608 return 0;
1609
1610 if (strcmp(args[1], "fail") == 0) {
1611 /* add a condition to fail monitor requests */
1612 int pol = ACL_COND_NONE;
1613 struct acl_cond *cond;
1614
1615 if (!strcmp(args[2], "if"))
1616 pol = ACL_COND_IF;
1617 else if (!strcmp(args[2], "unless"))
1618 pol = ACL_COND_UNLESS;
1619
1620 if (pol == ACL_COND_NONE) {
1621 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1622 file, linenum, args[0], args[1]);
1623 return -1;
1624 }
1625
1626 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1627 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1628 file, linenum, args[0], args[1]);
1629 return -1;
1630 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001631 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001632 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1633 }
1634 else {
1635 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1636 return -1;
1637 }
1638 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639#ifdef TPROXY
1640 else if (!strcmp(args[0], "transparent")) {
1641 /* enable transparent proxy connections */
1642 curproxy->options |= PR_O_TRANSP;
1643 }
1644#endif
1645 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001646 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1647 return 0;
1648
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 if (*(args[1]) == 0) {
1650 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1651 return -1;
1652 }
1653 curproxy->maxconn = atol(args[1]);
1654 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001655 else if (!strcmp(args[0], "backlog")) { /* backlog */
1656 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1657 return 0;
1658
1659 if (*(args[1]) == 0) {
1660 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1661 return -1;
1662 }
1663 curproxy->backlog = atol(args[1]);
1664 }
Willy Tarreau86034312006-12-29 00:10:33 +01001665 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001666 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1667 return 0;
1668
Willy Tarreau86034312006-12-29 00:10:33 +01001669 if (*(args[1]) == 0) {
1670 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1671 return -1;
1672 }
1673 curproxy->fullconn = atol(args[1]);
1674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001675 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1676 if (*(args[1]) == 0) {
1677 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1678 return -1;
1679 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001680 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1681 if (err) {
1682 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1683 file, linenum, *err);
1684 return -1;
1685 }
1686 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001687 }
1688 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1689 if (curproxy == &defproxy) {
1690 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1691 return -1;
1692 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001693 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1694 return 0;
1695
Willy Tarreaubaaee002006-06-26 02:48:02 +02001696 if (strchr(args[1], ':') == NULL) {
1697 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1698 return -1;
1699 }
1700 curproxy->dispatch_addr = *str2sa(args[1]);
1701 }
1702 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001703 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1704 return 0;
1705
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02001706 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001707 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1708 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1709 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001711 }
1712 else if (!strcmp(args[0], "server")) { /* server address */
1713 int cur_arg;
1714 char *rport;
1715 char *raddr;
1716 short realport;
1717 int do_check;
1718
1719 if (curproxy == &defproxy) {
1720 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1721 return -1;
1722 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001723 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1724 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001725
1726 if (!*args[2]) {
1727 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1728 file, linenum, args[0]);
1729 return -1;
1730 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001731
1732 err = invalid_char(args[1]);
1733 if (err) {
1734 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1735 file, linenum, *err, args[1]);
1736 return -1;
1737 }
1738
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1740 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1741 return -1;
1742 }
1743
1744 /* the servers are linked backwards first */
1745 newsrv->next = curproxy->srv;
1746 curproxy->srv = newsrv;
1747 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001748 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001749
1750 LIST_INIT(&newsrv->pendconns);
1751 do_check = 0;
1752 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001753 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754 newsrv->id = strdup(args[1]);
1755
1756 /* several ways to check the port component :
1757 * - IP => port=+0, relative
1758 * - IP: => port=+0, relative
1759 * - IP:N => port=N, absolute
1760 * - IP:+N => port=+N, relative
1761 * - IP:-N => port=-N, relative
1762 */
1763 raddr = strdup(args[2]);
1764 rport = strchr(raddr, ':');
1765 if (rport) {
1766 *rport++ = 0;
1767 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001768 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001769 newsrv->state |= SRV_MAPPORTS;
1770 } else {
1771 realport = 0;
1772 newsrv->state |= SRV_MAPPORTS;
1773 }
1774
1775 newsrv->addr = *str2sa(raddr);
1776 newsrv->addr.sin_port = htons(realport);
1777 free(raddr);
1778
1779 newsrv->curfd = -1; /* no health-check in progress */
1780 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001781 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1782 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001783 newsrv->rise = DEF_RISETIME;
1784 newsrv->fall = DEF_FALLTIME;
1785 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001786 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001787 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001788 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001789
Willy Tarreaubaaee002006-06-26 02:48:02 +02001790 cur_arg = 3;
1791 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001792 if (!strcmp(args[cur_arg], "id")) {
1793 struct server *target;
1794
1795 if (!*args[cur_arg + 1]) {
1796 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1797 file, linenum, args[cur_arg]);
1798 return -1;
1799 }
1800
1801 newsrv->puid = atol(args[cur_arg + 1]);
1802
1803 if (newsrv->puid< 1001) {
1804 Alert("parsing [%s:%d]: custom id has to be > 1000",
1805 file, linenum);
1806 return -1;
1807 }
1808
1809 for (target = proxy->srv; target; target = target->next)
1810 if (newsrv != target && newsrv->puid == target->puid) {
1811 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1812 file, linenum, newsrv->id, target->id);
1813 return -1;
1814 }
1815 cur_arg += 2;
1816 }
1817 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001818 newsrv->cookie = strdup(args[cur_arg + 1]);
1819 newsrv->cklen = strlen(args[cur_arg + 1]);
1820 cur_arg += 2;
1821 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001822 else if (!strcmp(args[cur_arg], "redir")) {
1823 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1824 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1825 cur_arg += 2;
1826 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001827 else if (!strcmp(args[cur_arg], "rise")) {
1828 newsrv->rise = atol(args[cur_arg + 1]);
1829 newsrv->health = newsrv->rise;
1830 cur_arg += 2;
1831 }
1832 else if (!strcmp(args[cur_arg], "fall")) {
1833 newsrv->fall = atol(args[cur_arg + 1]);
1834 cur_arg += 2;
1835 }
1836 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001837 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1838 if (err) {
1839 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1840 file, linenum, *err, newsrv->id);
1841 return -1;
1842 }
1843 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844 cur_arg += 2;
1845 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001846 else if (!strcmp(args[cur_arg], "fastinter")) {
1847 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1848 if (err) {
1849 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1850 file, linenum, *err, newsrv->id);
1851 return -1;
1852 }
1853 newsrv->fastinter = val;
1854 cur_arg += 2;
1855 }
1856 else if (!strcmp(args[cur_arg], "downinter")) {
1857 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1858 if (err) {
1859 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1860 file, linenum, *err, newsrv->id);
1861 return -1;
1862 }
1863 newsrv->downinter = val;
1864 cur_arg += 2;
1865 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001866 else if (!strcmp(args[cur_arg], "addr")) {
1867 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001868 cur_arg += 2;
1869 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001870 else if (!strcmp(args[cur_arg], "port")) {
1871 newsrv->check_port = atol(args[cur_arg + 1]);
1872 cur_arg += 2;
1873 }
1874 else if (!strcmp(args[cur_arg], "backup")) {
1875 newsrv->state |= SRV_BACKUP;
1876 cur_arg ++;
1877 }
1878 else if (!strcmp(args[cur_arg], "weight")) {
1879 int w;
1880 w = atol(args[cur_arg + 1]);
1881 if (w < 1 || w > 256) {
1882 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1883 file, linenum, newsrv->id, w);
1884 return -1;
1885 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001886 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001887 cur_arg += 2;
1888 }
1889 else if (!strcmp(args[cur_arg], "minconn")) {
1890 newsrv->minconn = atol(args[cur_arg + 1]);
1891 cur_arg += 2;
1892 }
1893 else if (!strcmp(args[cur_arg], "maxconn")) {
1894 newsrv->maxconn = atol(args[cur_arg + 1]);
1895 cur_arg += 2;
1896 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001897 else if (!strcmp(args[cur_arg], "maxqueue")) {
1898 newsrv->maxqueue = atol(args[cur_arg + 1]);
1899 cur_arg += 2;
1900 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001901 else if (!strcmp(args[cur_arg], "slowstart")) {
1902 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001903 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001904 if (err) {
1905 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1906 file, linenum, *err, newsrv->id);
1907 return -1;
1908 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001909 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001910 cur_arg += 2;
1911 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001912 else if (!strcmp(args[cur_arg], "track")) {
1913
1914 if (!*args[cur_arg + 1]) {
1915 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1916 file, linenum);
1917 return -1;
1918 }
1919
1920 newsrv->trackit = strdup(args[cur_arg + 1]);
1921
1922 cur_arg += 2;
1923 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 else if (!strcmp(args[cur_arg], "check")) {
1925 global.maxsock++;
1926 do_check = 1;
1927 cur_arg += 1;
1928 }
1929 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1930 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001931#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001932 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1933 file, linenum, "source", "usesrc");
1934#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001935 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1936 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001937#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 return -1;
1939 }
1940 newsrv->state |= SRV_BIND_SRC;
1941 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1942 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001943 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001944#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1945#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001946 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001947 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1948 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001949 return -1;
1950 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001951#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001952 if (!*args[cur_arg + 1]) {
1953 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1954 file, linenum, "usesrc");
1955 return -1;
1956 }
1957 if (!strcmp(args[cur_arg + 1], "client")) {
1958 newsrv->state |= SRV_TPROXY_CLI;
1959 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1960 newsrv->state |= SRV_TPROXY_CIP;
1961 } else {
1962 newsrv->state |= SRV_TPROXY_ADDR;
1963 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1964 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001965 global.last_checks |= LSTCHK_NETADM;
1966#if !defined(CONFIG_HAP_LINUX_TPROXY)
1967 global.last_checks |= LSTCHK_CTTPROXY;
1968#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001969 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001970#else /* no TPROXY support */
1971 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001972 file, linenum, "usesrc");
1973 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001974#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001977 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1978 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1979 file, linenum, "usesrc", "source");
1980 return -1;
1981 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001982 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001983 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 +02001984 file, linenum, newsrv->id);
1985 return -1;
1986 }
1987 }
1988
1989 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001990 if (newsrv->trackit) {
1991 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1992 file, linenum);
1993 return -1;
1994 }
1995
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001996 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1997 newsrv->check_port = newsrv->check_addr.sin_port;
1998
Willy Tarreaubaaee002006-06-26 02:48:02 +02001999 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2000 newsrv->check_port = realport; /* by default */
2001 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002002 /* not yet valid, because no port was set on
2003 * the server either. We'll check if we have
2004 * a known port on the first listener.
2005 */
2006 struct listener *l;
2007 l = curproxy->listen;
2008 if (l) {
2009 int port;
2010 port = (l->addr.ss_family == AF_INET6)
2011 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2012 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2013 newsrv->check_port = port;
2014 }
2015 }
2016 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002017 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2018 file, linenum, newsrv->id);
2019 return -1;
2020 }
2021 newsrv->state |= SRV_CHECKED;
2022 }
2023
2024 if (newsrv->state & SRV_BACKUP)
2025 curproxy->srv_bck++;
2026 else
2027 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002028
2029 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002030 }
2031 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002032 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002033 int facility;
2034
2035 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2036 curproxy->logfac1 = global.logfac1;
2037 curproxy->logsrv1 = global.logsrv1;
2038 curproxy->loglev1 = global.loglev1;
2039 curproxy->logfac2 = global.logfac2;
2040 curproxy->logsrv2 = global.logsrv2;
2041 curproxy->loglev2 = global.loglev2;
2042 }
2043 else if (*(args[1]) && *(args[2])) {
2044 int level;
2045
2046 facility = get_log_facility(args[2]);
2047 if (facility < 0) {
2048 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2049 exit(1);
2050 }
2051
2052 level = 7; /* max syslog level = debug */
2053 if (*(args[3])) {
2054 level = get_log_level(args[3]);
2055 if (level < 0) {
2056 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2057 exit(1);
2058 }
2059 }
2060
Robert Tsai81ae1952007-12-05 10:47:29 +01002061 if (args[1][0] == '/') {
2062 logsrv.u.addr.sa_family = AF_UNIX;
2063 logsrv.u.un = *str2sun(args[1]);
2064 } else {
2065 logsrv.u.addr.sa_family = AF_INET;
2066 logsrv.u.in = *str2sa(args[1]);
2067 if (!logsrv.u.in.sin_port) {
2068 logsrv.u.in.sin_port =
2069 htons(SYSLOG_PORT);
2070 }
2071 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072
2073 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002074 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002075 curproxy->logfac1 = facility;
2076 curproxy->loglev1 = level;
2077 }
2078 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002079 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002080 curproxy->logfac2 = facility;
2081 curproxy->loglev2 = level;
2082 }
2083 else {
2084 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2085 return -1;
2086 }
2087 }
2088 else {
2089 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2090 file, linenum);
2091 return -1;
2092 }
2093 }
2094 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002095 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2096 return 0;
2097
Willy Tarreaubaaee002006-06-26 02:48:02 +02002098 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002099#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002100 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2101 file, linenum, "source", "usesrc");
2102#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2104 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002105#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 return -1;
2107 }
2108
2109 curproxy->source_addr = *str2sa(args[1]);
2110 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01002111 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002112#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2113#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002114 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2115 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2116 file, linenum, "usesrc");
2117 return -1;
2118 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002119#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002120 if (!*args[3]) {
2121 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2122 file, linenum, "usesrc");
2123 return -1;
2124 }
2125
2126 if (!strcmp(args[3], "client")) {
2127 curproxy->options |= PR_O_TPXY_CLI;
2128 } else if (!strcmp(args[3], "clientip")) {
2129 curproxy->options |= PR_O_TPXY_CIP;
2130 } else {
2131 curproxy->options |= PR_O_TPXY_ADDR;
2132 curproxy->tproxy_addr = *str2sa(args[3]);
2133 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002134 global.last_checks |= LSTCHK_NETADM;
2135#if !defined(CONFIG_HAP_LINUX_TPROXY)
2136 global.last_checks |= LSTCHK_CTTPROXY;
2137#endif
2138#else /* no TPROXY support */
2139 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002140 file, linenum, "usesrc");
2141 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002142#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002144 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002145 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2146 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2147 file, linenum, "usesrc", "source");
2148 return -1;
2149 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002150 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2151 regex_t *preg;
2152 if (curproxy == &defproxy) {
2153 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2154 return -1;
2155 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002156 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2157 return 0;
2158
Willy Tarreaubaaee002006-06-26 02:48:02 +02002159 if (*(args[1]) == 0 || *(args[2]) == 0) {
2160 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2161 file, linenum, args[0]);
2162 return -1;
2163 }
2164
2165 preg = calloc(1, sizeof(regex_t));
2166 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2167 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2168 return -1;
2169 }
2170
2171 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2172 if (err) {
2173 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2174 file, linenum, *err);
2175 return -1;
2176 }
2177 }
2178 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2179 regex_t *preg;
2180 if (curproxy == &defproxy) {
2181 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2182 return -1;
2183 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002184 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2185 return 0;
2186
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187 if (*(args[1]) == 0) {
2188 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2189 return -1;
2190 }
2191
2192 preg = calloc(1, sizeof(regex_t));
2193 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2194 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2195 return -1;
2196 }
2197
2198 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2199 }
2200 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2201 regex_t *preg;
2202 if (curproxy == &defproxy) {
2203 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2204 return -1;
2205 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002206 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2207 return 0;
2208
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 if (*(args[1]) == 0) {
2210 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2211 return -1;
2212 }
2213
2214 preg = calloc(1, sizeof(regex_t));
2215 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2216 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2217 return -1;
2218 }
2219
2220 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2221 }
2222 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2223 regex_t *preg;
2224 if (curproxy == &defproxy) {
2225 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2226 return -1;
2227 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002228 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2229 return 0;
2230
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 if (*(args[1]) == 0) {
2232 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2233 return -1;
2234 }
2235
2236 preg = calloc(1, sizeof(regex_t));
2237 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2238 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2239 return -1;
2240 }
2241
2242 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2243 }
2244 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2245 regex_t *preg;
2246 if (curproxy == &defproxy) {
2247 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2248 return -1;
2249 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002250 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2251 return 0;
2252
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253 if (*(args[1]) == 0) {
2254 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2255 return -1;
2256 }
2257
2258 preg = calloc(1, sizeof(regex_t));
2259 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2260 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2261 return -1;
2262 }
2263
2264 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2265 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002266 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2267 regex_t *preg;
2268 if (curproxy == &defproxy) {
2269 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2270 return -1;
2271 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002272 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2273 return 0;
2274
Willy Tarreaub8750a82006-09-03 09:56:00 +02002275 if (*(args[1]) == 0) {
2276 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2277 return -1;
2278 }
2279
2280 preg = calloc(1, sizeof(regex_t));
2281 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2282 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2283 return -1;
2284 }
2285
2286 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2287 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002288 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2289 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002290 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002291 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2292 return -1;
2293 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002294 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2295 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002296
Willy Tarreau977b8e42006-12-29 14:19:17 +01002297 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002298 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2299 file, linenum, args[0]);
2300 return -1;
2301 }
2302
2303 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002304 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002305 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2306 }
2307
2308 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2309 }
2310 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2311 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002312 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002313 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2314 return -1;
2315 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002316 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2317 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002318
Willy Tarreau977b8e42006-12-29 14:19:17 +01002319 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002320 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2321 file, linenum, args[0]);
2322 return -1;
2323 }
2324
2325 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002326 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002327 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2328 }
2329
2330 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002332 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2333 regex_t *preg;
2334 if (curproxy == &defproxy) {
2335 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2336 return -1;
2337 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002338 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2339 return 0;
2340
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 if (*(args[1]) == 0 || *(args[2]) == 0) {
2342 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2343 file, linenum, args[0]);
2344 return -1;
2345 }
2346
2347 preg = calloc(1, sizeof(regex_t));
2348 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2349 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2350 return -1;
2351 }
2352
2353 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2354 if (err) {
2355 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2356 file, linenum, *err);
2357 return -1;
2358 }
2359 }
2360 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2361 regex_t *preg;
2362 if (curproxy == &defproxy) {
2363 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2364 return -1;
2365 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002366 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2367 return 0;
2368
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 if (*(args[1]) == 0) {
2370 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2371 return -1;
2372 }
2373
2374 preg = calloc(1, sizeof(regex_t));
2375 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2376 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2377 return -1;
2378 }
2379
2380 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2381 }
2382 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2383 regex_t *preg;
2384 if (curproxy == &defproxy) {
2385 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2386 return -1;
2387 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002388 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2389 return 0;
2390
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 if (*(args[1]) == 0) {
2392 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2393 return -1;
2394 }
2395
2396 preg = calloc(1, sizeof(regex_t));
2397 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2398 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2399 return -1;
2400 }
2401
2402 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2403 }
2404 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2405 regex_t *preg;
2406 if (curproxy == &defproxy) {
2407 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2408 return -1;
2409 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002410 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2411 return 0;
2412
Willy Tarreaubaaee002006-06-26 02:48:02 +02002413 if (*(args[1]) == 0) {
2414 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2415 return -1;
2416 }
2417
2418 preg = calloc(1, sizeof(regex_t));
2419 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2420 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2421 return -1;
2422 }
2423
2424 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2425 }
2426 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2427 regex_t *preg;
2428 if (curproxy == &defproxy) {
2429 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2430 return -1;
2431 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002432 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2433 return 0;
2434
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 if (*(args[1]) == 0) {
2436 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2437 return -1;
2438 }
2439
2440 preg = calloc(1, sizeof(regex_t));
2441 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2442 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2443 return -1;
2444 }
2445
2446 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2447 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002448 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2449 regex_t *preg;
2450 if (curproxy == &defproxy) {
2451 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2452 return -1;
2453 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002454 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2455 return 0;
2456
Willy Tarreaub8750a82006-09-03 09:56:00 +02002457 if (*(args[1]) == 0) {
2458 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2459 return -1;
2460 }
2461
2462 preg = calloc(1, sizeof(regex_t));
2463 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2464 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2465 return -1;
2466 }
2467
2468 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2471 if (curproxy == &defproxy) {
2472 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2473 return -1;
2474 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002475 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2476 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477
2478 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2479 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2480 return 0;
2481 }
2482
2483 if (*(args[1]) == 0) {
2484 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2485 return -1;
2486 }
2487
2488 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2489 }
2490 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2491 regex_t *preg;
2492
2493 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 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002498 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2499 return 0;
2500
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 preg = calloc(1, sizeof(regex_t));
2502 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2503 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2504 return -1;
2505 }
2506
2507 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2508 if (err) {
2509 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2510 file, linenum, *err);
2511 return -1;
2512 }
2513 }
2514 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2515 regex_t *preg;
2516 if (curproxy == &defproxy) {
2517 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2518 return -1;
2519 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002520 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2521 return 0;
2522
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 if (*(args[1]) == 0) {
2524 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2525 return -1;
2526 }
2527
2528 preg = calloc(1, sizeof(regex_t));
2529 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2530 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2531 return -1;
2532 }
2533
2534 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2535 if (err) {
2536 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2537 file, linenum, *err);
2538 return -1;
2539 }
2540 }
2541 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2542 regex_t *preg;
2543 if (curproxy == &defproxy) {
2544 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2545 return -1;
2546 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002547 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2548 return 0;
2549
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 if (*(args[1]) == 0) {
2551 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2552 return -1;
2553 }
2554
2555 preg = calloc(1, sizeof(regex_t));
2556 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2557 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2558 return -1;
2559 }
2560
2561 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2562 if (err) {
2563 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2564 file, linenum, *err);
2565 return -1;
2566 }
2567 }
2568 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2569 regex_t *preg;
2570 if (curproxy == &defproxy) {
2571 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2572 return -1;
2573 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002574 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2575 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576
2577 if (*(args[1]) == 0 || *(args[2]) == 0) {
2578 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2579 file, linenum, args[0]);
2580 return -1;
2581 }
2582
2583 preg = calloc(1, sizeof(regex_t));
2584 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2585 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2586 return -1;
2587 }
2588
2589 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2590 if (err) {
2591 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2592 file, linenum, *err);
2593 return -1;
2594 }
2595 }
2596 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2597 regex_t *preg;
2598 if (curproxy == &defproxy) {
2599 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2600 return -1;
2601 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002602 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2603 return 0;
2604
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 if (*(args[1]) == 0) {
2606 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2607 return -1;
2608 }
2609
2610 preg = calloc(1, sizeof(regex_t));
2611 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2612 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2613 return -1;
2614 }
2615
2616 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2617 if (err) {
2618 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2619 file, linenum, *err);
2620 return -1;
2621 }
2622 }
2623 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2624 regex_t *preg;
2625 if (curproxy == &defproxy) {
2626 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2627 return -1;
2628 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002629 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2630 return 0;
2631
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632 if (*(args[1]) == 0) {
2633 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2634 return -1;
2635 }
2636
2637 preg = calloc(1, sizeof(regex_t));
2638 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2639 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2640 return -1;
2641 }
2642
2643 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2644 if (err) {
2645 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2646 file, linenum, *err);
2647 return -1;
2648 }
2649 }
2650 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2651 if (curproxy == &defproxy) {
2652 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2653 return -1;
2654 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002655 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2656 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657
2658 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2659 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2660 return 0;
2661 }
2662
2663 if (*(args[1]) == 0) {
2664 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2665 return -1;
2666 }
2667
2668 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2669 }
2670 else if (!strcmp(args[0], "errorloc") ||
2671 !strcmp(args[0], "errorloc302") ||
2672 !strcmp(args[0], "errorloc303")) { /* error location */
2673 int errnum, errlen;
2674 char *err;
2675
Willy Tarreau977b8e42006-12-29 14:19:17 +01002676 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2677 return 0;
2678
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002680 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681 return -1;
2682 }
2683
2684 errnum = atol(args[1]);
2685 if (!strcmp(args[0], "errorloc303")) {
2686 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2687 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2688 } else {
2689 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2690 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2691 }
2692
Willy Tarreau0f772532006-12-23 20:51:41 +01002693 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2694 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002695 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002696 curproxy->errmsg[rc].str = err;
2697 curproxy->errmsg[rc].len = errlen;
2698 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002701
2702 if (rc >= HTTP_ERR_SIZE) {
2703 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2704 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 free(err);
2706 }
2707 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002708 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2709 int errnum, errlen, fd;
2710 char *err;
2711 struct stat stat;
2712
2713 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2714 return 0;
2715
2716 if (*(args[2]) == 0) {
2717 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2718 return -1;
2719 }
2720
2721 fd = open(args[2], O_RDONLY);
2722 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2723 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2724 file, linenum, args[2], args[1]);
2725 if (fd >= 0)
2726 close(fd);
2727 return -1;
2728 }
2729
2730 if (stat.st_size <= BUFSIZE) {
2731 errlen = stat.st_size;
2732 } else {
2733 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2734 file, linenum, args[2], BUFSIZE);
2735 errlen = BUFSIZE;
2736 }
2737
2738 err = malloc(errlen); /* malloc() must succeed during parsing */
2739 errnum = read(fd, err, errlen);
2740 if (errnum != errlen) {
2741 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2742 file, linenum, args[2], args[1]);
2743 close(fd);
2744 free(err);
2745 return -1;
2746 }
2747 close(fd);
2748
2749 errnum = atol(args[1]);
2750 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2751 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002752 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002753 curproxy->errmsg[rc].str = err;
2754 curproxy->errmsg[rc].len = errlen;
2755 break;
2756 }
2757 }
2758
2759 if (rc >= HTTP_ERR_SIZE) {
2760 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2761 file, linenum, errnum);
2762 free(err);
2763 }
2764 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002765 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002766 struct cfg_kw_list *kwl;
2767 int index;
2768
2769 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2770 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2771 if (kwl->kw[index].section != CFG_LISTEN)
2772 continue;
2773 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2774 /* prepare error message just in case */
2775 snprintf(trash, sizeof(trash),
2776 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002777 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2778 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002779 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2780 return -1;
2781 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002782 else if (rc > 0) {
2783 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2784 return 0;
2785 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002786 return 0;
2787 }
2788 }
2789 }
2790
Willy Tarreau6daf3432008-01-22 16:44:08 +01002791 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002792 return -1;
2793 }
2794 return 0;
2795}
2796
2797
2798/*
2799 * This function reads and parses the configuration file given in the argument.
2800 * returns 0 if OK, -1 if error.
2801 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002802int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002803{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002804 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002805 FILE *f;
2806 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002807 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808 int confsect = CFG_NONE;
2809
2810 struct proxy *curproxy = NULL;
2811 struct server *newsrv = NULL;
2812
2813 if ((f=fopen(file,"r")) == NULL)
2814 return -1;
2815
2816 init_default_instance();
2817
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002818 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002819 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002820 char *end;
2821 char *args[MAX_LINE_ARGS + 1];
2822 char *line = thisline;
2823
Willy Tarreaubaaee002006-06-26 02:48:02 +02002824 linenum++;
2825
2826 end = line + strlen(line);
2827
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002828 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2829 /* Check if we reached the limit and the last char is not \n.
2830 * Watch out for the last line without the terminating '\n'!
2831 */
2832 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2833 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002834 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002835 }
2836
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002838 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 line++;
2840
2841 arg = 0;
2842 args[arg] = line;
2843
2844 while (*line && arg < MAX_LINE_ARGS) {
2845 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2846 * C equivalent value. Other combinations left unchanged (eg: \1).
2847 */
2848 if (*line == '\\') {
2849 int skip = 0;
2850 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2851 *line = line[1];
2852 skip = 1;
2853 }
2854 else if (line[1] == 'r') {
2855 *line = '\r';
2856 skip = 1;
2857 }
2858 else if (line[1] == 'n') {
2859 *line = '\n';
2860 skip = 1;
2861 }
2862 else if (line[1] == 't') {
2863 *line = '\t';
2864 skip = 1;
2865 }
2866 else if (line[1] == 'x') {
2867 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2868 unsigned char hex1, hex2;
2869 hex1 = toupper(line[2]) - '0';
2870 hex2 = toupper(line[3]) - '0';
2871 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2872 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2873 *line = (hex1<<4) + hex2;
2874 skip = 3;
2875 }
2876 else {
2877 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002878 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879 }
2880 }
2881 if (skip) {
2882 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2883 end -= skip;
2884 }
2885 line++;
2886 }
2887 else if (*line == '#' || *line == '\n' || *line == '\r') {
2888 /* end of string, end of loop */
2889 *line = 0;
2890 break;
2891 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002892 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002893 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002894 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002895 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 line++;
2897 args[++arg] = line;
2898 }
2899 else {
2900 line++;
2901 }
2902 }
2903
2904 /* empty line */
2905 if (!**args)
2906 continue;
2907
Willy Tarreau540abe42007-05-02 20:50:16 +02002908 /* zero out remaining args and ensure that at least one entry
2909 * is zeroed out.
2910 */
2911 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 args[arg] = line;
2913 }
2914
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002915 if (!strcmp(args[0], "no")) {
2916 inv = 1;
2917 for (arg=0; *args[arg+1]; arg++)
2918 args[arg] = args[arg+1]; // shift args after inversion
2919 }
2920
2921 if (inv && strcmp(args[0], "option")) {
2922 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002923 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002924 }
2925
Willy Tarreau977b8e42006-12-29 14:19:17 +01002926 if (!strcmp(args[0], "listen") ||
2927 !strcmp(args[0], "frontend") ||
2928 !strcmp(args[0], "backend") ||
2929 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002930 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002931 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002932 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002933 cursection = strdup(args[0]);
2934 }
2935 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002936 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002937 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002938 cursection = strdup(args[0]);
2939 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940 /* else it's a section keyword */
2941
2942 switch (confsect) {
2943 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002944 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002945 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002946 break;
2947 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002948 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002949 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002950 break;
2951 default:
2952 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002953 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002954 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002955 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002956 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002957 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002958 fclose(f);
2959
2960 /*
2961 * Now, check for the integrity of all that we have collected.
2962 */
2963
2964 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002965 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966
2967 if ((curproxy = proxy) == NULL) {
2968 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2969 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002970 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 }
2972
2973 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002974 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002975 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002976
Willy Tarreaubaaee002006-06-26 02:48:02 +02002977 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02002978 /* ensure we don't keep listeners uselessly bound */
2979 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 curproxy = curproxy->next;
2981 continue;
2982 }
2983
Willy Tarreau977b8e42006-12-29 14:19:17 +01002984 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2985 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 +01002986 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002987 cfgerr++;
2988 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002989 else if (curproxy->cap & PR_CAP_BE &&
2990 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002991 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002992 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002993 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2994 Alert("parsing %s : %s '%s' has no dispatch address and is not in transparent or balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002995 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002996 cfgerr++;
2997 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002998
Willy Tarreau31682232007-11-29 15:38:04 +01002999 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003000 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003001 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003002 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 cfgerr++;
3004 }
3005#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
3006 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003007 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003008 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 cfgerr++;
3010 }
3011#endif
3012 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003013 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003014 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003015 }
3016 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003017
3018 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003019 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003020 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003021 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003022 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003024 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003025 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003026 }
3027 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003028 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003029 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003030 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003031 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003032 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003033 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003034 }
Willy Tarreaudf366142007-11-30 16:23:20 +01003035 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01003036 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3037 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003038
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01003039 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003040 file, proxy_type_str(curproxy), curproxy->id);
3041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003043
3044 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
3045 if ((newsrv = curproxy->srv) != NULL) {
3046 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
3047 file, proxy_type_str(curproxy), curproxy->id);
3048 }
3049 }
3050
3051 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
3053 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
3054 file, curproxy->id);
3055 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003056 }
3057 }
3058
Willy Tarreau82936582007-11-30 15:20:09 +01003059 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3060 curproxy->options &= ~PR_O_DISABLE404;
3061 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3062 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
3063 }
3064
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003065 /* if a default backend was specified, let's find it */
3066 if (curproxy->defbe.name) {
3067 struct proxy *target;
3068
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003069 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3070 if (!target) {
3071 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3072 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003073 cfgerr++;
3074 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003075 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3076 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003077 } else {
3078 free(curproxy->defbe.name);
3079 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 }
3081 }
3082
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003083 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003084 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3085 /* map jump target for ACT_SETBE in req_rep chain */
3086 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003087 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003088 struct proxy *target;
3089
Willy Tarreaua496b602006-12-17 23:15:24 +01003090 if (exp->action != ACT_SETBE)
3091 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003092
3093 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3094 if (!target) {
3095 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3096 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003097 cfgerr++;
3098 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003099 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3100 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003101 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003102 } else {
3103 free((void *)exp->replace);
3104 exp->replace = (const char *)target;
3105 }
3106 }
3107 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003108
3109 /* find the target proxy for 'use_backend' rules */
3110 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003111 struct proxy *target;
3112
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003113 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003114
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003115 if (!target) {
3116 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3117 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003118 cfgerr++;
3119 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003120 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3121 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003122 cfgerr++;
3123 } else {
3124 free((void *)rule->be.name);
3125 rule->be.backend = target;
3126 }
3127 }
3128
Willy Tarreau2738a142006-07-08 17:28:09 +02003129 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003130 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003131 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003132 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003133 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003134 " | While not properly invalid, you will certainly encounter various problems\n"
3135 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003136 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003137 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003138 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003139
Willy Tarreau1fa31262007-12-03 00:36:16 +01003140 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3141 * We must still support older configurations, so let's find out whether those
3142 * parameters have been set or must be copied from contimeouts.
3143 */
3144 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003145 if (!curproxy->timeout.tarpit ||
3146 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003147 /* tarpit timeout not set. We search in the following order:
3148 * default.tarpit, curr.connect, default.connect.
3149 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003150 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003151 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003152 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003153 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003154 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003155 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003156 }
3157 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003158 (!curproxy->timeout.queue ||
3159 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003160 /* queue timeout not set. We search in the following order:
3161 * default.queue, curr.connect, default.connect.
3162 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003163 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003164 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003165 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003166 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003167 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003168 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003169 }
3170 }
3171
Willy Tarreauf3c69202006-07-09 16:42:34 +02003172 if (curproxy->options & PR_O_SSL3_CHK) {
3173 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3174 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3175 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3176 }
3177
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003178 /* The small pools required for the capture lists */
3179 if (curproxy->nb_req_cap)
3180 curproxy->req_cap_pool = create_pool("ptrcap",
3181 curproxy->nb_req_cap * sizeof(char *),
3182 MEM_F_SHARED);
3183 if (curproxy->nb_rsp_cap)
3184 curproxy->rsp_cap_pool = create_pool("ptrcap",
3185 curproxy->nb_rsp_cap * sizeof(char *),
3186 MEM_F_SHARED);
3187
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003188 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3189 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3190 MEM_F_SHARED);
3191
Willy Tarreau86034312006-12-29 00:10:33 +01003192 /* for backwards compatibility with "listen" instances, if
3193 * fullconn is not set but maxconn is set, then maxconn
3194 * is used.
3195 */
3196 if (!curproxy->fullconn)
3197 curproxy->fullconn = curproxy->maxconn;
3198
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 /* first, we will invert the servers list order */
3200 newsrv = NULL;
3201 while (curproxy->srv) {
3202 struct server *next;
3203
3204 next = curproxy->srv->next;
3205 curproxy->srv->next = newsrv;
3206 newsrv = curproxy->srv;
3207 if (!next)
3208 break;
3209 curproxy->srv = next;
3210 }
3211
Willy Tarreau20697042007-11-15 23:26:18 +01003212 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003213 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003214
Willy Tarreaub625a082007-11-26 01:15:43 +01003215 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003216 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003217 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003218 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3219 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003220 else
3221 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222
3223 if (curproxy->options & PR_O_LOGASAP)
3224 curproxy->to_log &= ~LW_BYTES;
3225
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003227 * ensure that we're not cross-dressing a TCP server into HTTP.
3228 */
3229 newsrv = curproxy->srv;
3230 while (newsrv != NULL) {
3231 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3232 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3233 file, proxy_type_str(curproxy), curproxy->id, linenum);
3234 goto err;
3235 }
3236 newsrv = newsrv->next;
3237 }
3238
3239 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003240 * If this server supports a maxconn parameter, it needs a dedicated
3241 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003242 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 */
3244 newsrv = curproxy->srv;
3245 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003246 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 /* Only 'minconn' was specified, or it was higher than or equal
3248 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3249 * this will avoid further useless expensive computations.
3250 */
3251 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003252 } else if (newsrv->maxconn && !newsrv->minconn) {
3253 /* minconn was not specified, so we set it to maxconn */
3254 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003255 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3256 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003257 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003258 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259 }
3260
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003261 if (newsrv->trackit) {
3262 struct proxy *px;
3263 struct server *srv;
3264 char *pname, *sname;
3265
3266 pname = newsrv->trackit;
3267 sname = strrchr(pname, '/');
3268
3269 if (sname)
3270 *sname++ = '\0';
3271 else {
3272 sname = pname;
3273 pname = NULL;
3274 }
3275
3276 if (pname) {
3277 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3278 if (!px) {
3279 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3280 file, proxy_type_str(curproxy), curproxy->id,
3281 newsrv->id, pname);
3282 return -1;
3283 }
3284 } else
3285 px = curproxy;
3286
3287 srv = findserver(px, sname);
3288 if (!srv) {
3289 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3290 file, proxy_type_str(curproxy), curproxy->id,
3291 newsrv->id, sname);
3292 return -1;
3293 }
3294
3295 if (!(srv->state & SRV_CHECKED)) {
3296 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3297 "tracing as it does not have checks enabled.\n",
3298 file, proxy_type_str(curproxy), curproxy->id,
3299 newsrv->id, px->id, srv->id);
3300 return -1;
3301 }
3302
3303 if (curproxy != px &&
3304 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3305 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3306 "tracing: disable-on-404 option inconsistency.\n",
3307 file, proxy_type_str(curproxy), curproxy->id,
3308 newsrv->id, px->id, srv->id);
3309 return -1;
3310 }
3311
3312 newsrv->tracked = srv;
3313 newsrv->tracknext = srv->tracknext;
3314 srv->tracknext = newsrv;
3315
3316 free(newsrv->trackit);
3317 }
3318
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 newsrv = newsrv->next;
3320 }
3321
Willy Tarreaue6b98942007-10-29 01:09:36 +01003322 /* adjust this proxy's listeners */
3323 listener = curproxy->listen;
3324 while (listener) {
3325 if (curproxy->options & PR_O_TCP_NOLING)
3326 listener->options |= LI_O_NOLINGER;
3327 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003328 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003329 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003330 listener->accept = event_accept;
3331 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003332 listener->handler = process_session;
3333
3334 if (curproxy->mode == PR_MODE_HTTP)
3335 listener->analysers |= AN_REQ_HTTP_HDR;
3336
3337 if (curproxy->tcp_req.inspect_delay)
3338 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003339
3340 listener = listener->next;
3341 }
3342
Willy Tarreaubaaee002006-06-26 02:48:02 +02003343 curproxy = curproxy->next;
3344 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003345
Willy Tarreaubaaee002006-06-26 02:48:02 +02003346 if (cfgerr > 0) {
3347 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003348 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003349 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003350
3351 /*
3352 * Recount currently required checks.
3353 */
3354
3355 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3356 int optnum;
3357
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003358 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3359 if (curproxy->options & cfg_opts[optnum].val)
3360 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003361
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003362 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3363 if (curproxy->options2 & cfg_opts2[optnum].val)
3364 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003365 }
3366
Willy Tarreaua534fea2008-08-03 12:19:50 +02003367 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003368 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003369 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003370
3371 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003372 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003373 cursection = NULL;
3374 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375}
3376
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003377/*
3378 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3379 * parsing sessions.
3380 */
3381void cfg_register_keywords(struct cfg_kw_list *kwl)
3382{
3383 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3384}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003386/*
3387 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3388 */
3389void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3390{
3391 LIST_DEL(&kwl->list);
3392 LIST_INIT(&kwl->list);
3393}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394
3395/*
3396 * Local variables:
3397 * c-indent-level: 8
3398 * c-basic-offset: 8
3399 * End:
3400 */