blob: 5d70341d74aa68807964b1140602d22251c619bf [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau7c669d72008-06-20 15:04:11 +02004 * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
27#include <common/config.h>
28#include <common/memory.h>
29#include <common/standard.h>
30#include <common/time.h>
31#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020032
33#include <types/capture.h>
34#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreaueb0c6142007-05-07 00:53:22 +020036#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010038#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020040#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010041#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010043#include <proto/protocols.h>
44#include <proto/proto_tcp.h>
45#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010046#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010048#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <proto/task.h>
50
51
Willy Tarreauf3c69202006-07-09 16:42:34 +020052/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
53 * ssl-hello-chk option to ensure that the remote server speaks SSL.
54 *
55 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
56 */
57const char sslv3_client_hello_pkt[] = {
58 "\x16" /* ContentType : 0x16 = Hanshake */
59 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
60 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
61 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
62 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
63 "\x03\x00" /* Hello Version : 0x0300 = v3 */
64 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
65 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
66 "\x00" /* Session ID length : empty (no session ID) */
67 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
68 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
69 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
70 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
71 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
72 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
73 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
74 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
75 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
76 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
77 "\x00\x38" "\x00\x39" "\x00\x3A"
78 "\x01" /* Compression Length : 0x01 = 1 byte for types */
79 "\x00" /* Compression Type : 0x00 = NULL compression */
80};
81
Willy Tarreau13943ab2006-12-31 00:24:10 +010082/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010083struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010084 const char *name;
85 unsigned int val;
86 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010087 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +010088};
89
90/* proxy->options */
91static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +010092{
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010094 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010095 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010096 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010097 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
98 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
99 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
100 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
101 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
102 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
103 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
104 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100106 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
107 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100108#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100109 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
110#endif
111#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100112 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100113#endif
114
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116};
117
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100118/* proxy->options2 */
119static const struct cfg_opt cfg_opts2[] =
120{
121#ifdef CONFIG_HAP_LINUX_SPLICE
122 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
123 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
124 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
125#endif
126 { NULL, 0, 0, 0 }
127};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200128
Willy Tarreau6daf3432008-01-22 16:44:08 +0100129static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200130static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
131int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
132int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
133
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200134/* List head of all known configuration keywords */
135static struct cfg_kw_list cfg_keywords = {
136 .list = LIST_HEAD_INIT(cfg_keywords.list)
137};
138
Willy Tarreaubaaee002006-06-26 02:48:02 +0200139/*
140 * converts <str> to a list of listeners which are dynamically allocated.
141 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
142 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
143 * - <port> is a numerical port from 1 to 65535 ;
144 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
145 * This can be repeated as many times as necessary, separated by a coma.
146 * The <tail> argument is a pointer to a current list which should be appended
147 * to the tail of the new list. The pointer to the new list is returned.
148 */
149static struct listener *str2listener(char *str, struct listener *tail)
150{
151 struct listener *l;
152 char *c, *next, *range, *dupstr;
153 int port, end;
154
155 next = dupstr = strdup(str);
156
157 while (next && *next) {
158 struct sockaddr_storage ss;
159
160 str = next;
161 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100162 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200163 *next++ = 0;
164 }
165
166 /* 2) look for the addr/port delimiter, it's the last colon. */
167 if ((range = strrchr(str, ':')) == NULL) {
168 Alert("Missing port number: '%s'\n", str);
169 goto fail;
170 }
171
172 *range++ = 0;
173
174 if (strrchr(str, ':') != NULL) {
175 /* IPv6 address contains ':' */
176 memset(&ss, 0, sizeof(ss));
177 ss.ss_family = AF_INET6;
178
179 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
180 Alert("Invalid server address: '%s'\n", str);
181 goto fail;
182 }
183 }
184 else {
185 memset(&ss, 0, sizeof(ss));
186 ss.ss_family = AF_INET;
187
188 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
189 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
190 }
191 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
192 struct hostent *he;
193
194 if ((he = gethostbyname(str)) == NULL) {
195 Alert("Invalid server name: '%s'\n", str);
196 goto fail;
197 }
198 else
199 ((struct sockaddr_in *)&ss)->sin_addr =
200 *(struct in_addr *) *(he->h_addr_list);
201 }
202 }
203
204 /* 3) look for the port-end delimiter */
205 if ((c = strchr(range, '-')) != NULL) {
206 *c++ = 0;
207 end = atol(c);
208 }
209 else {
210 end = atol(range);
211 }
212
213 port = atol(range);
214
215 if (port < 1 || port > 65535) {
216 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
217 goto fail;
218 }
219
220 if (end < 1 || end > 65535) {
221 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
222 goto fail;
223 }
224
225 for (; port <= end; port++) {
226 l = (struct listener *)calloc(1, sizeof(struct listener));
227 l->next = tail;
228 tail = l;
229
230 l->fd = -1;
231 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100232 l->state = LI_INIT;
233
234 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100236 tcpv6_add_listener(l);
237 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100239 tcpv4_add_listener(l);
240 }
241 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242 } /* end for(port) */
243 } /* end while(next) */
244 free(dupstr);
245 return tail;
246 fail:
247 free(dupstr);
248 return NULL;
249}
250
Willy Tarreau977b8e42006-12-29 14:19:17 +0100251/*
252 * Sends a warning if proxy <proxy> does not have at least one of the
253 * capabilities in <cap>. An optionnal <hint> may be added at the end
254 * of the warning to help the user. Returns 1 if a warning was emitted
255 * or 0 if the condition is valid.
256 */
257int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
258{
259 char *msg;
260
261 switch (cap) {
262 case PR_CAP_BE: msg = "no backend"; break;
263 case PR_CAP_FE: msg = "no frontend"; break;
264 case PR_CAP_RS: msg = "no ruleset"; break;
265 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
266 default: msg = "not enough"; break;
267 }
268
269 if (!(proxy->cap & cap)) {
270 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100271 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100272 return 1;
273 }
274 return 0;
275}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200276
277/*
278 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
279 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100280int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281{
282
283 if (!strcmp(args[0], "global")) { /* new section */
284 /* no option, nothing special to do */
285 return 0;
286 }
287 else if (!strcmp(args[0], "daemon")) {
288 global.mode |= MODE_DAEMON;
289 }
290 else if (!strcmp(args[0], "debug")) {
291 global.mode |= MODE_DEBUG;
292 }
293 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100294 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200296 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100297 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200298 }
299 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100300 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100303 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100305 else if (!strcmp(args[0], "nosplice")) {
306 global.tune.options &= ~GTUNE_USE_SPLICE;
307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308 else if (!strcmp(args[0], "quiet")) {
309 global.mode |= MODE_QUIET;
310 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200311 else if (!strcmp(args[0], "tune.maxpollevents")) {
312 if (global.tune.maxpollevents != 0) {
313 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
314 return 0;
315 }
316 if (*(args[1]) == 0) {
317 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
318 return -1;
319 }
320 global.tune.maxpollevents = atol(args[1]);
321 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100322 else if (!strcmp(args[0], "tune.maxaccept")) {
323 if (global.tune.maxaccept != 0) {
324 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
325 return 0;
326 }
327 if (*(args[1]) == 0) {
328 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
329 return -1;
330 }
331 global.tune.maxaccept = atol(args[1]);
332 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200333 else if (!strcmp(args[0], "uid")) {
334 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200335 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200336 return 0;
337 }
338 if (*(args[1]) == 0) {
339 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
340 return -1;
341 }
342 global.uid = atol(args[1]);
343 }
344 else if (!strcmp(args[0], "gid")) {
345 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200346 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200347 return 0;
348 }
349 if (*(args[1]) == 0) {
350 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
351 return -1;
352 }
353 global.gid = atol(args[1]);
354 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200355 /* user/group name handling */
356 else if (!strcmp(args[0], "user")) {
357 struct passwd *ha_user;
358 if (global.uid != 0) {
359 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
360 return 0;
361 }
362 errno = 0;
363 ha_user = getpwnam(args[1]);
364 if (ha_user != NULL) {
365 global.uid = (int)ha_user->pw_uid;
366 }
367 else {
368 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
369 exit(1);
370 }
371 }
372 else if (!strcmp(args[0], "group")) {
373 struct group *ha_group;
374 if (global.gid != 0) {
375 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
376 return 0;
377 }
378 errno = 0;
379 ha_group = getgrnam(args[1]);
380 if (ha_group != NULL) {
381 global.gid = (int)ha_group->gr_gid;
382 }
383 else {
384 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
385 exit(1);
386 }
387 }
388 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200389 else if (!strcmp(args[0], "nbproc")) {
390 if (global.nbproc != 0) {
391 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
392 return 0;
393 }
394 if (*(args[1]) == 0) {
395 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
396 return -1;
397 }
398 global.nbproc = atol(args[1]);
399 }
400 else if (!strcmp(args[0], "maxconn")) {
401 if (global.maxconn != 0) {
402 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
403 return 0;
404 }
405 if (*(args[1]) == 0) {
406 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
407 return -1;
408 }
409 global.maxconn = atol(args[1]);
410#ifdef SYSTEM_MAXCONN
411 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
412 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
413 global.maxconn = DEFAULT_MAXCONN;
414 }
415#endif /* SYSTEM_MAXCONN */
416 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100417 else if (!strcmp(args[0], "maxpipes")) {
418 if (global.maxpipes != 0) {
419 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
420 return 0;
421 }
422 if (*(args[1]) == 0) {
423 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
424 return -1;
425 }
426 global.maxpipes = atol(args[1]);
427 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200428 else if (!strcmp(args[0], "ulimit-n")) {
429 if (global.rlimit_nofile != 0) {
430 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
431 return 0;
432 }
433 if (*(args[1]) == 0) {
434 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
435 return -1;
436 }
437 global.rlimit_nofile = atol(args[1]);
438 }
439 else if (!strcmp(args[0], "chroot")) {
440 if (global.chroot != NULL) {
441 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
442 return 0;
443 }
444 if (*(args[1]) == 0) {
445 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
446 return -1;
447 }
448 global.chroot = strdup(args[1]);
449 }
450 else if (!strcmp(args[0], "pidfile")) {
451 if (global.pidfile != NULL) {
452 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
453 return 0;
454 }
455 if (*(args[1]) == 0) {
456 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
457 return -1;
458 }
459 global.pidfile = strdup(args[1]);
460 }
461 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100462 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463 int facility, level;
464
465 if (*(args[1]) == 0 || *(args[2]) == 0) {
466 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
467 return -1;
468 }
469
470 facility = get_log_facility(args[2]);
471 if (facility < 0) {
472 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
473 exit(1);
474 }
475
476 level = 7; /* max syslog level = debug */
477 if (*(args[3])) {
478 level = get_log_level(args[3]);
479 if (level < 0) {
480 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
481 exit(1);
482 }
483 }
484
Robert Tsai81ae1952007-12-05 10:47:29 +0100485 if (args[1][0] == '/') {
486 logsrv.u.addr.sa_family = AF_UNIX;
487 logsrv.u.un = *str2sun(args[1]);
488 } else {
489 logsrv.u.addr.sa_family = AF_INET;
490 logsrv.u.in = *str2sa(args[1]);
491 if (!logsrv.u.in.sin_port)
492 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
493 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200494
495 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100496 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200497 global.logfac1 = facility;
498 global.loglev1 = level;
499 }
500 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100501 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200502 global.logfac2 = facility;
503 global.loglev2 = level;
504 }
505 else {
506 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
507 return -1;
508 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200509 }
510 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
511 if (global.spread_checks != 0) {
512 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
513 return 0;
514 }
515 if (*(args[1]) == 0) {
516 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
517 return -1;
518 }
519 global.spread_checks = atol(args[1]);
520 if (global.spread_checks < 0 || global.spread_checks > 50) {
521 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
522 return -1;
523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200524 }
525 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200526 struct cfg_kw_list *kwl;
527 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200528 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200529
530 list_for_each_entry(kwl, &cfg_keywords.list, list) {
531 for (index = 0; kwl->kw[index].kw != NULL; index++) {
532 if (kwl->kw[index].section != CFG_GLOBAL)
533 continue;
534 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
535 /* prepare error message just in case */
536 snprintf(trash, sizeof(trash),
537 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200538 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
539 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200540 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
541 return -1;
542 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200543 else if (rc > 0) {
544 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
545 return 0;
546 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200547 return 0;
548 }
549 }
550 }
551
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
553 return -1;
554 }
555 return 0;
556}
557
558
559static void init_default_instance()
560{
561 memset(&defproxy, 0, sizeof(defproxy));
562 defproxy.mode = PR_MODE_TCP;
563 defproxy.state = PR_STNEW;
564 defproxy.maxconn = cfg_maxpconn;
565 defproxy.conn_retries = CONN_RETRIES;
566 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200567
568 LIST_INIT(&defproxy.pendconns);
569 LIST_INIT(&defproxy.acl);
570 LIST_INIT(&defproxy.block_cond);
571 LIST_INIT(&defproxy.mon_fail_cond);
572 LIST_INIT(&defproxy.switching_rules);
573
Willy Tarreau3a70f942008-02-15 11:15:34 +0100574 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575}
576
577/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100578 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
579 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100581int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582{
583 static struct proxy *curproxy = NULL;
584 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200585 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100586 int rc;
587 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200588
Willy Tarreau977b8e42006-12-29 14:19:17 +0100589 if (!strcmp(args[0], "listen"))
590 rc = PR_CAP_LISTEN;
591 else if (!strcmp(args[0], "frontend"))
592 rc = PR_CAP_FE | PR_CAP_RS;
593 else if (!strcmp(args[0], "backend"))
594 rc = PR_CAP_BE | PR_CAP_RS;
595 else if (!strcmp(args[0], "ruleset"))
596 rc = PR_CAP_RS;
597 else
598 rc = PR_CAP_NONE;
599
600 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 if (!*args[1]) {
602 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
603 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
604 file, linenum, args[0]);
605 return -1;
606 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200607
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100608 err = invalid_char(args[1]);
609 if (err) {
610 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
611 file, linenum, *err, args[0], args[1]);
612 return -1;
613 }
614
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200615 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
616 /*
617 * If there are two proxies with the same name only following
618 * combinations are allowed:
619 *
620 * listen backend frontend ruleset
621 * listen - - - -
622 * backend - - OK -
623 * frontend - OK - -
624 * ruleset - - - -
625 */
626
627 if (!strcmp(curproxy->id, args[1]) &&
628 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
629 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100630 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
631 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200632 }
633 }
634
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
636 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
637 return -1;
638 }
639
640 curproxy->next = proxy;
641 proxy = curproxy;
642 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200643 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200644 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200645 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100646 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200647 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200648 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200649
Willy Tarreauee991362007-05-14 14:37:50 +0200650 /* Timeouts are defined as -1, so we cannot use the zeroed area
651 * as a default value.
652 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100653 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200654
655 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100657 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658
659 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100660 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 curproxy->listen = str2listener(args[2], curproxy->listen);
662 if (!curproxy->listen)
663 return -1;
664 global.maxsock++;
665 }
666
667 /* set default values */
668 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100670 curproxy->options2 = defproxy.options2;
Willy Tarreau31682232007-11-29 15:38:04 +0100671 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200672 curproxy->except_net = defproxy.except_net;
673 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200675 if (defproxy.fwdfor_hdr_len) {
676 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
677 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
678 }
679
Willy Tarreau977b8e42006-12-29 14:19:17 +0100680 if (curproxy->cap & PR_CAP_FE) {
681 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100682 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100683
684 /* initialize error relocations */
685 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
686 if (defproxy.errmsg[rc].str)
687 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
688 }
689
690 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
691 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692
Willy Tarreau977b8e42006-12-29 14:19:17 +0100693 if (curproxy->cap & PR_CAP_BE) {
694 curproxy->fullconn = defproxy.fullconn;
695 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696
Willy Tarreau977b8e42006-12-29 14:19:17 +0100697 if (defproxy.check_req)
698 curproxy->check_req = strdup(defproxy.check_req);
699 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700
Willy Tarreau977b8e42006-12-29 14:19:17 +0100701 if (defproxy.cookie_name)
702 curproxy->cookie_name = strdup(defproxy.cookie_name);
703 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100704
705 if (defproxy.url_param_name)
706 curproxy->url_param_name = strdup(defproxy.url_param_name);
707 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709
Willy Tarreau977b8e42006-12-29 14:19:17 +0100710 if (curproxy->cap & PR_CAP_RS) {
711 if (defproxy.capture_name)
712 curproxy->capture_name = strdup(defproxy.capture_name);
713 curproxy->capture_namelen = defproxy.capture_namelen;
714 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100715 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716
Willy Tarreau977b8e42006-12-29 14:19:17 +0100717 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100718 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100719 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100720 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100721 curproxy->uri_auth = defproxy.uri_auth;
722 curproxy->mon_net = defproxy.mon_net;
723 curproxy->mon_mask = defproxy.mon_mask;
724 if (defproxy.monitor_uri)
725 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
726 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100727 if (defproxy.defbe.name)
728 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100729 }
730
731 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100732 curproxy->timeout.connect = defproxy.timeout.connect;
733 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100734 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100735 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100736 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100737 curproxy->source_addr = defproxy.source_addr;
738 }
739
Willy Tarreaubaaee002006-06-26 02:48:02 +0200740 curproxy->mode = defproxy.mode;
741 curproxy->logfac1 = defproxy.logfac1;
742 curproxy->logsrv1 = defproxy.logsrv1;
743 curproxy->loglev1 = defproxy.loglev1;
744 curproxy->logfac2 = defproxy.logfac2;
745 curproxy->logsrv2 = defproxy.logsrv2;
746 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100748 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
749 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200750
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751 return 0;
752 }
753 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
754 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100755 /* FIXME-20070101: we should do this too at the end of the
756 * config parsing to free all default values.
757 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200758 free(defproxy.check_req);
759 free(defproxy.cookie_name);
760 free(defproxy.url_param_name);
761 free(defproxy.capture_name);
762 free(defproxy.monitor_uri);
763 free(defproxy.defbe.name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200764 free(defproxy.fwdfor_hdr_name);
765 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100766
Willy Tarreaua534fea2008-08-03 12:19:50 +0200767 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
768 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100769
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 /* we cannot free uri_auth because it might already be used */
771 init_default_instance();
772 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100773 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200774 return 0;
775 }
776 else if (curproxy == NULL) {
777 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
778 return -1;
779 }
780
Willy Tarreau977b8e42006-12-29 14:19:17 +0100781
782 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200783 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100784 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200785 if (curproxy == &defproxy) {
786 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
787 return -1;
788 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100789 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
790 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200791
792 if (strchr(args[1], ':') == NULL) {
793 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
794 file, linenum, args[0]);
795 return -1;
796 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100797
798 last_listen = curproxy->listen;
799 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200800 if (!curproxy->listen)
801 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100802 if (*args[2]) {
803#ifdef CONFIG_HAP_LINUX_TPROXY
804 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
805 struct listener *l;
806
807 for (l = curproxy->listen; l != last_listen; l = l->next)
808 l->options |= LI_O_FOREIGN;
809 }
810 else {
811 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
812 file, linenum, args[0]);
813 return -1;
814 }
815#else
816 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
817 file, linenum, args[0]);
818 return -1;
819#endif
820 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821 global.maxsock++;
822 return 0;
823 }
824 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
825 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
826 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
827 file, linenum, args[0]);
828 return -1;
829 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100830 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
831 return 0;
832
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 /* flush useless bits */
834 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
835 return 0;
836 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200837 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100838 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
839 return 0;
840
Willy Tarreau1c47f852006-07-09 08:22:27 +0200841 if (!*args[1]) {
842 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
843 file, linenum, args[0]);
844 return -1;
845 }
846
Willy Tarreaua534fea2008-08-03 12:19:50 +0200847 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100848 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200849 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100850 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200851 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
852
853 return 0;
854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200855 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
856 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
857 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
858 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
859 else {
860 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
861 return -1;
862 }
863 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100864 else if (!strcmp(args[0], "id")) {
865 struct proxy *target;
866
867 if (curproxy == &defproxy) {
868 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
869 file, linenum, args[0]);
870 return -1;
871 }
872
873 if (!*args[1]) {
874 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
875 file, linenum, args[0]);
876 return -1;
877 }
878
879 curproxy->uuid = atol(args[1]);
880
881 if (curproxy->uuid < 1001) {
882 Alert("parsing [%s:%d]: custom id has to be > 1000",
883 file, linenum);
884 return -1;
885 }
886
887 for (target = proxy; target; target = target->next)
888 if (curproxy != target && curproxy->uuid == target->uuid) {
889 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
890 file, linenum, curproxy->id, target->id);
891 return -1;
892 }
893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200894 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
895 curproxy->state = PR_STSTOPPED;
896 }
897 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
898 curproxy->state = PR_STNEW;
899 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200900 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200901 if (curproxy == &defproxy) {
902 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
903 return -1;
904 }
905
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100906 err = invalid_char(args[1]);
907 if (err) {
908 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
909 file, linenum, *err, args[1]);
910 return -1;
911 }
912
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200913 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
914 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
915 file, linenum, args[1]);
916 return -1;
917 }
918 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 else if (!strcmp(args[0], "cookie")) { /* cookie name */
920 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921
Willy Tarreau977b8e42006-12-29 14:19:17 +0100922 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
923 return 0;
924
Willy Tarreaubaaee002006-06-26 02:48:02 +0200925 if (*(args[1]) == 0) {
926 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
927 file, linenum, args[0]);
928 return -1;
929 }
Willy Tarreaua534fea2008-08-03 12:19:50 +0200930
931 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 curproxy->cookie_name = strdup(args[1]);
933 curproxy->cookie_len = strlen(curproxy->cookie_name);
934
935 cur_arg = 2;
936 while (*(args[cur_arg])) {
937 if (!strcmp(args[cur_arg], "rewrite")) {
938 curproxy->options |= PR_O_COOK_RW;
939 }
940 else if (!strcmp(args[cur_arg], "indirect")) {
941 curproxy->options |= PR_O_COOK_IND;
942 }
943 else if (!strcmp(args[cur_arg], "insert")) {
944 curproxy->options |= PR_O_COOK_INS;
945 }
946 else if (!strcmp(args[cur_arg], "nocache")) {
947 curproxy->options |= PR_O_COOK_NOC;
948 }
949 else if (!strcmp(args[cur_arg], "postonly")) {
950 curproxy->options |= PR_O_COOK_POST;
951 }
952 else if (!strcmp(args[cur_arg], "prefix")) {
953 curproxy->options |= PR_O_COOK_PFX;
954 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200955 else if (!strcmp(args[cur_arg], "domain")) {
956 if (!*args[cur_arg + 1]) {
957 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
958 file, linenum, args[cur_arg]);
959 return -1;
960 }
961
962 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
963 /* rfc2109, 4.3.2 Rejecting Cookies */
964 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
965 " dots or does not start with a dot.\n",
966 file, linenum, args[cur_arg + 1]);
967 return -1;
968 }
969
970 err = invalid_domainchar(args[cur_arg + 1]);
971 if (err) {
972 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
973 file, linenum, *err, args[cur_arg + 1]);
974 return -1;
975 }
976
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +0200977 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200978 cur_arg++;
979 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200981 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982 file, linenum, args[0]);
983 return -1;
984 }
985 cur_arg++;
986 }
987 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
988 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
989 file, linenum);
990 return -1;
991 }
992
993 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
994 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
995 file, linenum);
996 return -1;
997 }
998 }/* end else if (!strcmp(args[0], "cookie")) */
999 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001000
Willy Tarreau977b8e42006-12-29 14:19:17 +01001001 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1002 return 0;
1003
Willy Tarreaubaaee002006-06-26 02:48:02 +02001004 if (*(args[5]) == 0) {
1005 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1006 file, linenum, args[0]);
1007 return -1;
1008 }
1009 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001010 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001011 curproxy->appsession_name = strdup(args[1]);
1012 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1013 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001014 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1015 if (err) {
1016 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1017 file, linenum, *err, args[0]);
1018 return -1;
1019 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001020 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001021
Willy Tarreau51041c72007-09-09 21:56:53 +02001022 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1023 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001024 return -1;
1025 }
1026 } /* Url App Session */
1027 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001028 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1029 return 0;
1030
Willy Tarreaubaaee002006-06-26 02:48:02 +02001031 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001032 if (*(args[4]) == 0) {
1033 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1034 file, linenum, args[0]);
1035 return -1;
1036 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001037 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001038 curproxy->capture_name = strdup(args[2]);
1039 curproxy->capture_namelen = strlen(curproxy->capture_name);
1040 curproxy->capture_len = atol(args[4]);
1041 if (curproxy->capture_len >= CAPTURE_LEN) {
1042 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1043 file, linenum, CAPTURE_LEN - 1);
1044 curproxy->capture_len = CAPTURE_LEN - 1;
1045 }
1046 curproxy->to_log |= LW_COOKIE;
1047 }
1048 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1049 struct cap_hdr *hdr;
1050
1051 if (curproxy == &defproxy) {
1052 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1053 return -1;
1054 }
1055
1056 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1057 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1058 file, linenum, args[0], args[1]);
1059 return -1;
1060 }
1061
1062 hdr = calloc(sizeof(struct cap_hdr), 1);
1063 hdr->next = curproxy->req_cap;
1064 hdr->name = strdup(args[3]);
1065 hdr->namelen = strlen(args[3]);
1066 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001067 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 hdr->index = curproxy->nb_req_cap++;
1069 curproxy->req_cap = hdr;
1070 curproxy->to_log |= LW_REQHDR;
1071 }
1072 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1073 struct cap_hdr *hdr;
1074
1075 if (curproxy == &defproxy) {
1076 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1077 return -1;
1078 }
1079
1080 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1081 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1082 file, linenum, args[0], args[1]);
1083 return -1;
1084 }
1085 hdr = calloc(sizeof(struct cap_hdr), 1);
1086 hdr->next = curproxy->rsp_cap;
1087 hdr->name = strdup(args[3]);
1088 hdr->namelen = strlen(args[3]);
1089 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001090 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 hdr->index = curproxy->nb_rsp_cap++;
1092 curproxy->rsp_cap = hdr;
1093 curproxy->to_log |= LW_RSPHDR;
1094 }
1095 else {
1096 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1097 file, linenum, args[0]);
1098 return -1;
1099 }
1100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001102 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1103 return 0;
1104
Willy Tarreaubaaee002006-06-26 02:48:02 +02001105 if (*(args[1]) == 0) {
1106 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1107 file, linenum, args[0]);
1108 return -1;
1109 }
1110 curproxy->conn_retries = atol(args[1]);
1111 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001112 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1113 int pol = ACL_COND_NONE;
1114 struct acl_cond *cond;
1115
Willy Tarreaub099aca2008-10-12 17:26:37 +02001116 if (curproxy == &defproxy) {
1117 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1118 return -1;
1119 }
1120
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001121 if (!strcmp(args[1], "if"))
1122 pol = ACL_COND_IF;
1123 else if (!strcmp(args[1], "unless"))
1124 pol = ACL_COND_UNLESS;
1125
1126 if (pol == ACL_COND_NONE) {
1127 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1128 file, linenum, args[0]);
1129 return -1;
1130 }
1131
1132 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1133 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1134 file, linenum);
1135 return -1;
1136 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001137 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001138 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1139 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001140 else if (!strcmp(args[0], "redirect")) {
1141 int pol = ACL_COND_NONE;
1142 struct acl_cond *cond;
1143 struct redirect_rule *rule;
1144 int cur_arg;
1145 int type = REDIRECT_TYPE_NONE;
1146 int code = 302;
1147 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001148 char *cookie = NULL;
1149 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001150 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001151
1152 cur_arg = 1;
1153 while (*(args[cur_arg])) {
1154 if (!strcmp(args[cur_arg], "location")) {
1155 if (!*args[cur_arg + 1]) {
1156 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1157 file, linenum, args[0], args[cur_arg]);
1158 return -1;
1159 }
1160
1161 type = REDIRECT_TYPE_LOCATION;
1162 cur_arg++;
1163 destination = args[cur_arg];
1164 }
1165 else if (!strcmp(args[cur_arg], "prefix")) {
1166 if (!*args[cur_arg + 1]) {
1167 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1168 file, linenum, args[0], args[cur_arg]);
1169 return -1;
1170 }
1171
1172 type = REDIRECT_TYPE_PREFIX;
1173 cur_arg++;
1174 destination = args[cur_arg];
1175 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001176 else if (!strcmp(args[cur_arg], "set-cookie")) {
1177 if (!*args[cur_arg + 1]) {
1178 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1179 file, linenum, args[0], args[cur_arg]);
1180 return -1;
1181 }
1182
1183 cur_arg++;
1184 cookie = args[cur_arg];
1185 cookie_set = 1;
1186 }
1187 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1188 if (!*args[cur_arg + 1]) {
1189 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1190 file, linenum, args[0], args[cur_arg]);
1191 return -1;
1192 }
1193
1194 cur_arg++;
1195 cookie = args[cur_arg];
1196 cookie_set = 0;
1197 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001198 else if (!strcmp(args[cur_arg],"code")) {
1199 if (!*args[cur_arg + 1]) {
1200 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1201 file, linenum, args[0]);
1202 return -1;
1203 }
1204 cur_arg++;
1205 code = atol(args[cur_arg]);
1206 if (code < 301 || code > 303) {
1207 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1208 file, linenum, args[0], code);
1209 return -1;
1210 }
1211 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001212 else if (!strcmp(args[cur_arg],"drop-query")) {
1213 flags |= REDIRECT_FLAG_DROP_QS;
1214 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001215 else if (!strcmp(args[cur_arg], "if")) {
1216 pol = ACL_COND_IF;
1217 cur_arg++;
1218 break;
1219 }
1220 else if (!strcmp(args[cur_arg], "unless")) {
1221 pol = ACL_COND_UNLESS;
1222 cur_arg++;
1223 break;
1224 }
1225 else {
1226 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1227 file, linenum, args[0], args[cur_arg]);
1228 return -1;
1229 }
1230 cur_arg++;
1231 }
1232
1233 if (type == REDIRECT_TYPE_NONE) {
1234 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1235 file, linenum, args[0]);
1236 return -1;
1237 }
1238
1239 if (pol == ACL_COND_NONE) {
1240 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1241 file, linenum, args[0]);
1242 return -1;
1243 }
1244
1245 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1246 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1247 file, linenum, args[0]);
1248 return -1;
1249 }
1250
Willy Tarreaua9802632008-07-25 19:13:19 +02001251 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001252 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1253 rule->cond = cond;
1254 rule->rdr_str = strdup(destination);
1255 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001256 if (cookie) {
1257 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1258 * a clear consists in appending "; Max-Age=0" at the end.
1259 */
1260 rule->cookie_len = strlen(cookie);
1261 if (cookie_set)
1262 rule->cookie_str = strdup(cookie);
1263 else {
1264 rule->cookie_str = malloc(rule->cookie_len + 12);
1265 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1266 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1267 rule->cookie_len += 11;
1268 }
1269 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001270 rule->type = type;
1271 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001272 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001273 LIST_INIT(&rule->list);
1274 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1275 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001276 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1277 int pol = ACL_COND_NONE;
1278 struct acl_cond *cond;
1279 struct switching_rule *rule;
1280
Willy Tarreaub099aca2008-10-12 17:26:37 +02001281 if (curproxy == &defproxy) {
1282 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1283 return -1;
1284 }
1285
Willy Tarreau55ea7572007-06-17 19:56:27 +02001286 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1287 return 0;
1288
1289 if (*(args[1]) == 0) {
1290 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1291 return -1;
1292 }
1293
1294 if (!strcmp(args[2], "if"))
1295 pol = ACL_COND_IF;
1296 else if (!strcmp(args[2], "unless"))
1297 pol = ACL_COND_UNLESS;
1298
1299 if (pol == ACL_COND_NONE) {
1300 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1301 file, linenum, args[0]);
1302 return -1;
1303 }
1304
1305 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001306 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001307 file, linenum);
1308 return -1;
1309 }
1310
Willy Tarreaua9802632008-07-25 19:13:19 +02001311 cond->line = linenum;
1312 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001313 struct acl *acl;
1314 const char *name;
1315
1316 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1317 name = acl ? acl->name : "(unknown)";
1318 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1319 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001320 }
1321
Willy Tarreau55ea7572007-06-17 19:56:27 +02001322 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1323 rule->cond = cond;
1324 rule->be.name = strdup(args[1]);
1325 LIST_INIT(&rule->list);
1326 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1327 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001328 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001329 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1330 return 0;
1331
Willy Tarreaubaaee002006-06-26 02:48:02 +02001332 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1333 curproxy->uri_auth = NULL; /* we must detach from the default config */
1334
1335 if (*(args[1]) == 0) {
1336 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1337 return -1;
1338 } else if (!strcmp(args[1], "uri")) {
1339 if (*(args[2]) == 0) {
1340 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1341 return -1;
1342 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1343 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1344 return -1;
1345 }
1346 } else if (!strcmp(args[1], "realm")) {
1347 if (*(args[2]) == 0) {
1348 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1349 return -1;
1350 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1351 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1352 return -1;
1353 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001354 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001355 unsigned interval;
1356
1357 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1358 if (err) {
1359 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1360 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001361 return -1;
1362 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1363 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1364 return -1;
1365 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001366 } else if (!strcmp(args[1], "auth")) {
1367 if (*(args[2]) == 0) {
1368 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1369 return -1;
1370 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1371 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1372 return -1;
1373 }
1374 } else if (!strcmp(args[1], "scope")) {
1375 if (*(args[2]) == 0) {
1376 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1377 return -1;
1378 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1379 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1380 return -1;
1381 }
1382 } else if (!strcmp(args[1], "enable")) {
1383 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1384 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1385 return -1;
1386 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001387 } else if (!strcmp(args[1], "hide-version")) {
1388 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1389 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1390 return -1;
1391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001393 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 file, linenum, args[0]);
1395 return -1;
1396 }
1397 }
1398 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001399 int optnum;
1400
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001401 if (*(args[1]) == '\0') {
1402 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1403 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001404 return -1;
1405 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001406
1407 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1408 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1409 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1410 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001411
1412 if (!inv)
1413 curproxy->options |= cfg_opts[optnum].val;
1414 else
1415 curproxy->options &= ~cfg_opts[optnum].val;
1416
Willy Tarreau13943ab2006-12-31 00:24:10 +01001417 return 0;
1418 }
1419 }
1420
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001421 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1422 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
1423 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
1424 return 0;
1425
1426 if (!inv)
1427 curproxy->options2 |= cfg_opts2[optnum].val;
1428 else
1429 curproxy->options2 &= ~cfg_opts2[optnum].val;
1430
1431 return 0;
1432 }
1433 }
1434
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001435 if (inv) {
1436 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1437 file, linenum, args[1]);
1438 return -1;
1439 }
1440
Willy Tarreau13943ab2006-12-31 00:24:10 +01001441 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001442 /* generate a complete HTTP log */
1443 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1444 else if (!strcmp(args[1], "tcplog"))
1445 /* generate a detailed TCP log */
1446 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001447 else if (!strcmp(args[1], "tcpka")) {
1448 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001449 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1450 return 0;
1451
1452 if (curproxy->cap & PR_CAP_FE)
1453 curproxy->options |= PR_O_TCP_CLI_KA;
1454 if (curproxy->cap & PR_CAP_BE)
1455 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456 }
1457 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001458 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1459 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001460 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001461 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001462 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001463 curproxy->options &= ~PR_O_SMTP_CHK;
1464 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001465 if (!*args[2]) { /* no argument */
1466 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1467 curproxy->check_len = strlen(DEF_CHECK_REQ);
1468 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001469 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470 curproxy->check_req = (char *)malloc(reqlen);
1471 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1472 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1473 } else { /* more arguments : METHOD URI [HTTP_VER] */
1474 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1475 if (*args[4])
1476 reqlen += strlen(args[4]);
1477 else
1478 reqlen += strlen("HTTP/1.0");
1479
1480 curproxy->check_req = (char *)malloc(reqlen);
1481 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1482 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1483 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001484 }
1485 else if (!strcmp(args[1], "ssl-hello-chk")) {
1486 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001487 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1488 return 0;
1489
Willy Tarreaua534fea2008-08-03 12:19:50 +02001490 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001491 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001492 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001493 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001494 }
Willy Tarreau23677902007-05-08 23:50:35 +02001495 else if (!strcmp(args[1], "smtpchk")) {
1496 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001497 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001498 curproxy->options &= ~PR_O_HTTP_CHK;
1499 curproxy->options &= ~PR_O_SSL3_CHK;
1500 curproxy->options |= PR_O_SMTP_CHK;
1501
1502 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1503 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1504 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1505 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1506 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1507 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1508 curproxy->check_req = (char *)malloc(reqlen);
1509 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1510 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1511 } else {
1512 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1513 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1514 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1515 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1516 }
1517 }
1518 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001519 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001520 int cur_arg;
1521
1522 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1523 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001524 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001525
1526 curproxy->options |= PR_O_FWDFOR;
1527
1528 free(curproxy->fwdfor_hdr_name);
1529 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1530 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1531
1532 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1533 cur_arg = 2;
1534 while (*(args[cur_arg])) {
1535 if (!strcmp(args[cur_arg], "except")) {
1536 /* suboption except - needs additional argument for it */
1537 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1538 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1539 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001540 return -1;
1541 }
1542 /* flush useless bits */
1543 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001544 cur_arg += 2;
1545 } else if (!strcmp(args[cur_arg], "header")) {
1546 /* suboption header - needs additional argument for it */
1547 if (*(args[cur_arg+1]) == 0) {
1548 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1549 file, linenum, args[0], args[1], args[cur_arg]);
1550 return -1;
1551 }
1552 free(curproxy->fwdfor_hdr_name);
1553 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1554 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1555 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001556 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001557 /* unknown suboption - catchall */
1558 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1559 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001560 return -1;
1561 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001562 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001563 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564 else {
1565 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1566 return -1;
1567 }
1568 return 0;
1569 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001570 else if (!strcmp(args[0], "default_backend")) {
1571 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1572 return 0;
1573
1574 if (*(args[1]) == 0) {
1575 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1576 return -1;
1577 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001578 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001579 curproxy->defbe.name = strdup(args[1]);
1580 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001582 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1583 return 0;
1584
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001585 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1586 file, linenum, args[0]);
1587
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 /* enable reconnections to dispatch */
1589 curproxy->options |= PR_O_REDISP;
1590 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001591 else if (!strcmp(args[0], "http-check")) {
1592 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1593 return 0;
1594
1595 if (strcmp(args[1], "disable-on-404") == 0) {
1596 /* enable a graceful server shutdown on an HTTP 404 response */
1597 curproxy->options |= PR_O_DISABLE404;
1598 }
1599 else {
1600 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1601 return -1;
1602 }
1603 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001604 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001605 if (curproxy == &defproxy) {
1606 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1607 return -1;
1608 }
1609
Willy Tarreaub80c2302007-11-30 20:51:32 +01001610 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1611 return 0;
1612
1613 if (strcmp(args[1], "fail") == 0) {
1614 /* add a condition to fail monitor requests */
1615 int pol = ACL_COND_NONE;
1616 struct acl_cond *cond;
1617
1618 if (!strcmp(args[2], "if"))
1619 pol = ACL_COND_IF;
1620 else if (!strcmp(args[2], "unless"))
1621 pol = ACL_COND_UNLESS;
1622
1623 if (pol == ACL_COND_NONE) {
1624 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1625 file, linenum, args[0], args[1]);
1626 return -1;
1627 }
1628
1629 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1630 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1631 file, linenum, args[0], args[1]);
1632 return -1;
1633 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001634 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001635 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1636 }
1637 else {
1638 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1639 return -1;
1640 }
1641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642#ifdef TPROXY
1643 else if (!strcmp(args[0], "transparent")) {
1644 /* enable transparent proxy connections */
1645 curproxy->options |= PR_O_TRANSP;
1646 }
1647#endif
1648 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001649 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1650 return 0;
1651
Willy Tarreaubaaee002006-06-26 02:48:02 +02001652 if (*(args[1]) == 0) {
1653 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1654 return -1;
1655 }
1656 curproxy->maxconn = atol(args[1]);
1657 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001658 else if (!strcmp(args[0], "backlog")) { /* backlog */
1659 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1660 return 0;
1661
1662 if (*(args[1]) == 0) {
1663 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1664 return -1;
1665 }
1666 curproxy->backlog = atol(args[1]);
1667 }
Willy Tarreau86034312006-12-29 00:10:33 +01001668 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001669 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1670 return 0;
1671
Willy Tarreau86034312006-12-29 00:10:33 +01001672 if (*(args[1]) == 0) {
1673 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1674 return -1;
1675 }
1676 curproxy->fullconn = atol(args[1]);
1677 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001678 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1679 if (*(args[1]) == 0) {
1680 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1681 return -1;
1682 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001683 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1684 if (err) {
1685 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1686 file, linenum, *err);
1687 return -1;
1688 }
1689 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001690 }
1691 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1692 if (curproxy == &defproxy) {
1693 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1694 return -1;
1695 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001696 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1697 return 0;
1698
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699 if (strchr(args[1], ':') == NULL) {
1700 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1701 return -1;
1702 }
1703 curproxy->dispatch_addr = *str2sa(args[1]);
1704 }
1705 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001706 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1707 return 0;
1708
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02001709 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001710 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1711 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1712 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 }
1715 else if (!strcmp(args[0], "server")) { /* server address */
1716 int cur_arg;
1717 char *rport;
1718 char *raddr;
1719 short realport;
1720 int do_check;
1721
1722 if (curproxy == &defproxy) {
1723 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1724 return -1;
1725 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001726 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1727 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728
1729 if (!*args[2]) {
1730 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1731 file, linenum, args[0]);
1732 return -1;
1733 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001734
1735 err = invalid_char(args[1]);
1736 if (err) {
1737 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1738 file, linenum, *err, args[1]);
1739 return -1;
1740 }
1741
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1743 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1744 return -1;
1745 }
1746
1747 /* the servers are linked backwards first */
1748 newsrv->next = curproxy->srv;
1749 curproxy->srv = newsrv;
1750 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001751 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752
1753 LIST_INIT(&newsrv->pendconns);
1754 do_check = 0;
1755 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001756 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001757 newsrv->id = strdup(args[1]);
1758
1759 /* several ways to check the port component :
1760 * - IP => port=+0, relative
1761 * - IP: => port=+0, relative
1762 * - IP:N => port=N, absolute
1763 * - IP:+N => port=+N, relative
1764 * - IP:-N => port=-N, relative
1765 */
1766 raddr = strdup(args[2]);
1767 rport = strchr(raddr, ':');
1768 if (rport) {
1769 *rport++ = 0;
1770 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001771 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001772 newsrv->state |= SRV_MAPPORTS;
1773 } else {
1774 realport = 0;
1775 newsrv->state |= SRV_MAPPORTS;
1776 }
1777
1778 newsrv->addr = *str2sa(raddr);
1779 newsrv->addr.sin_port = htons(realport);
1780 free(raddr);
1781
1782 newsrv->curfd = -1; /* no health-check in progress */
1783 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001784 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1785 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001786 newsrv->rise = DEF_RISETIME;
1787 newsrv->fall = DEF_FALLTIME;
1788 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001789 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001790 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001791 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001792
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793 cur_arg = 3;
1794 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001795 if (!strcmp(args[cur_arg], "id")) {
1796 struct server *target;
1797
1798 if (!*args[cur_arg + 1]) {
1799 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1800 file, linenum, args[cur_arg]);
1801 return -1;
1802 }
1803
1804 newsrv->puid = atol(args[cur_arg + 1]);
1805
1806 if (newsrv->puid< 1001) {
1807 Alert("parsing [%s:%d]: custom id has to be > 1000",
1808 file, linenum);
1809 return -1;
1810 }
1811
1812 for (target = proxy->srv; target; target = target->next)
1813 if (newsrv != target && newsrv->puid == target->puid) {
1814 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1815 file, linenum, newsrv->id, target->id);
1816 return -1;
1817 }
1818 cur_arg += 2;
1819 }
1820 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001821 newsrv->cookie = strdup(args[cur_arg + 1]);
1822 newsrv->cklen = strlen(args[cur_arg + 1]);
1823 cur_arg += 2;
1824 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001825 else if (!strcmp(args[cur_arg], "redir")) {
1826 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1827 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1828 cur_arg += 2;
1829 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001830 else if (!strcmp(args[cur_arg], "rise")) {
1831 newsrv->rise = atol(args[cur_arg + 1]);
1832 newsrv->health = newsrv->rise;
1833 cur_arg += 2;
1834 }
1835 else if (!strcmp(args[cur_arg], "fall")) {
1836 newsrv->fall = atol(args[cur_arg + 1]);
1837 cur_arg += 2;
1838 }
1839 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001840 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1841 if (err) {
1842 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1843 file, linenum, *err, newsrv->id);
1844 return -1;
1845 }
1846 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001847 cur_arg += 2;
1848 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001849 else if (!strcmp(args[cur_arg], "fastinter")) {
1850 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1851 if (err) {
1852 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1853 file, linenum, *err, newsrv->id);
1854 return -1;
1855 }
1856 newsrv->fastinter = val;
1857 cur_arg += 2;
1858 }
1859 else if (!strcmp(args[cur_arg], "downinter")) {
1860 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1861 if (err) {
1862 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1863 file, linenum, *err, newsrv->id);
1864 return -1;
1865 }
1866 newsrv->downinter = val;
1867 cur_arg += 2;
1868 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001869 else if (!strcmp(args[cur_arg], "addr")) {
1870 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001871 cur_arg += 2;
1872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001873 else if (!strcmp(args[cur_arg], "port")) {
1874 newsrv->check_port = atol(args[cur_arg + 1]);
1875 cur_arg += 2;
1876 }
1877 else if (!strcmp(args[cur_arg], "backup")) {
1878 newsrv->state |= SRV_BACKUP;
1879 cur_arg ++;
1880 }
1881 else if (!strcmp(args[cur_arg], "weight")) {
1882 int w;
1883 w = atol(args[cur_arg + 1]);
1884 if (w < 1 || w > 256) {
1885 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1886 file, linenum, newsrv->id, w);
1887 return -1;
1888 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001889 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890 cur_arg += 2;
1891 }
1892 else if (!strcmp(args[cur_arg], "minconn")) {
1893 newsrv->minconn = atol(args[cur_arg + 1]);
1894 cur_arg += 2;
1895 }
1896 else if (!strcmp(args[cur_arg], "maxconn")) {
1897 newsrv->maxconn = atol(args[cur_arg + 1]);
1898 cur_arg += 2;
1899 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001900 else if (!strcmp(args[cur_arg], "maxqueue")) {
1901 newsrv->maxqueue = atol(args[cur_arg + 1]);
1902 cur_arg += 2;
1903 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001904 else if (!strcmp(args[cur_arg], "slowstart")) {
1905 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001906 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001907 if (err) {
1908 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1909 file, linenum, *err, newsrv->id);
1910 return -1;
1911 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001912 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001913 cur_arg += 2;
1914 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001915 else if (!strcmp(args[cur_arg], "track")) {
1916
1917 if (!*args[cur_arg + 1]) {
1918 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1919 file, linenum);
1920 return -1;
1921 }
1922
1923 newsrv->trackit = strdup(args[cur_arg + 1]);
1924
1925 cur_arg += 2;
1926 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001927 else if (!strcmp(args[cur_arg], "check")) {
1928 global.maxsock++;
1929 do_check = 1;
1930 cur_arg += 1;
1931 }
1932 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1933 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001934#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001935 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1936 file, linenum, "source", "usesrc");
1937#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1939 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001940#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001941 return -1;
1942 }
1943 newsrv->state |= SRV_BIND_SRC;
1944 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1945 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001946 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001947#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1948#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001949 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001950 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1951 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001952 return -1;
1953 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001954#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001955 if (!*args[cur_arg + 1]) {
1956 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1957 file, linenum, "usesrc");
1958 return -1;
1959 }
1960 if (!strcmp(args[cur_arg + 1], "client")) {
1961 newsrv->state |= SRV_TPROXY_CLI;
1962 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1963 newsrv->state |= SRV_TPROXY_CIP;
1964 } else {
1965 newsrv->state |= SRV_TPROXY_ADDR;
1966 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1967 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001968 global.last_checks |= LSTCHK_NETADM;
1969#if !defined(CONFIG_HAP_LINUX_TPROXY)
1970 global.last_checks |= LSTCHK_CTTPROXY;
1971#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001972 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001973#else /* no TPROXY support */
1974 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001975 file, linenum, "usesrc");
1976 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001977#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001978 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001979 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001980 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1981 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1982 file, linenum, "usesrc", "source");
1983 return -1;
1984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001985 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001986 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 +02001987 file, linenum, newsrv->id);
1988 return -1;
1989 }
1990 }
1991
1992 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001993 if (newsrv->trackit) {
1994 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1995 file, linenum);
1996 return -1;
1997 }
1998
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001999 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2000 newsrv->check_port = newsrv->check_addr.sin_port;
2001
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2003 newsrv->check_port = realport; /* by default */
2004 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002005 /* not yet valid, because no port was set on
2006 * the server either. We'll check if we have
2007 * a known port on the first listener.
2008 */
2009 struct listener *l;
2010 l = curproxy->listen;
2011 if (l) {
2012 int port;
2013 port = (l->addr.ss_family == AF_INET6)
2014 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2015 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2016 newsrv->check_port = port;
2017 }
2018 }
2019 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002020 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2021 file, linenum, newsrv->id);
2022 return -1;
2023 }
2024 newsrv->state |= SRV_CHECKED;
2025 }
2026
2027 if (newsrv->state & SRV_BACKUP)
2028 curproxy->srv_bck++;
2029 else
2030 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002031
2032 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002033 }
2034 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002035 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002036 int facility;
2037
2038 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2039 curproxy->logfac1 = global.logfac1;
2040 curproxy->logsrv1 = global.logsrv1;
2041 curproxy->loglev1 = global.loglev1;
2042 curproxy->logfac2 = global.logfac2;
2043 curproxy->logsrv2 = global.logsrv2;
2044 curproxy->loglev2 = global.loglev2;
2045 }
2046 else if (*(args[1]) && *(args[2])) {
2047 int level;
2048
2049 facility = get_log_facility(args[2]);
2050 if (facility < 0) {
2051 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2052 exit(1);
2053 }
2054
2055 level = 7; /* max syslog level = debug */
2056 if (*(args[3])) {
2057 level = get_log_level(args[3]);
2058 if (level < 0) {
2059 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2060 exit(1);
2061 }
2062 }
2063
Robert Tsai81ae1952007-12-05 10:47:29 +01002064 if (args[1][0] == '/') {
2065 logsrv.u.addr.sa_family = AF_UNIX;
2066 logsrv.u.un = *str2sun(args[1]);
2067 } else {
2068 logsrv.u.addr.sa_family = AF_INET;
2069 logsrv.u.in = *str2sa(args[1]);
2070 if (!logsrv.u.in.sin_port) {
2071 logsrv.u.in.sin_port =
2072 htons(SYSLOG_PORT);
2073 }
2074 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002075
2076 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002077 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002078 curproxy->logfac1 = facility;
2079 curproxy->loglev1 = level;
2080 }
2081 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002082 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002083 curproxy->logfac2 = facility;
2084 curproxy->loglev2 = level;
2085 }
2086 else {
2087 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2088 return -1;
2089 }
2090 }
2091 else {
2092 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2093 file, linenum);
2094 return -1;
2095 }
2096 }
2097 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002098 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2099 return 0;
2100
Willy Tarreaubaaee002006-06-26 02:48:02 +02002101 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002102#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002103 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2104 file, linenum, "source", "usesrc");
2105#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2107 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002108#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109 return -1;
2110 }
2111
2112 curproxy->source_addr = *str2sa(args[1]);
2113 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01002114 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002115#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2116#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002117 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2118 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2119 file, linenum, "usesrc");
2120 return -1;
2121 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002122#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002123 if (!*args[3]) {
2124 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2125 file, linenum, "usesrc");
2126 return -1;
2127 }
2128
2129 if (!strcmp(args[3], "client")) {
2130 curproxy->options |= PR_O_TPXY_CLI;
2131 } else if (!strcmp(args[3], "clientip")) {
2132 curproxy->options |= PR_O_TPXY_CIP;
2133 } else {
2134 curproxy->options |= PR_O_TPXY_ADDR;
2135 curproxy->tproxy_addr = *str2sa(args[3]);
2136 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002137 global.last_checks |= LSTCHK_NETADM;
2138#if !defined(CONFIG_HAP_LINUX_TPROXY)
2139 global.last_checks |= LSTCHK_CTTPROXY;
2140#endif
2141#else /* no TPROXY support */
2142 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002143 file, linenum, "usesrc");
2144 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002145#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002146 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002147 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002148 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2149 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2150 file, linenum, "usesrc", "source");
2151 return -1;
2152 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002153 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2154 regex_t *preg;
2155 if (curproxy == &defproxy) {
2156 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2157 return -1;
2158 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002159 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2160 return 0;
2161
Willy Tarreaubaaee002006-06-26 02:48:02 +02002162 if (*(args[1]) == 0 || *(args[2]) == 0) {
2163 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2164 file, linenum, args[0]);
2165 return -1;
2166 }
2167
2168 preg = calloc(1, sizeof(regex_t));
2169 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2170 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2171 return -1;
2172 }
2173
2174 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2175 if (err) {
2176 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2177 file, linenum, *err);
2178 return -1;
2179 }
2180 }
2181 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2182 regex_t *preg;
2183 if (curproxy == &defproxy) {
2184 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2185 return -1;
2186 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002187 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2188 return 0;
2189
Willy Tarreaubaaee002006-06-26 02:48:02 +02002190 if (*(args[1]) == 0) {
2191 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2192 return -1;
2193 }
2194
2195 preg = calloc(1, sizeof(regex_t));
2196 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2197 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2198 return -1;
2199 }
2200
2201 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2202 }
2203 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2204 regex_t *preg;
2205 if (curproxy == &defproxy) {
2206 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2207 return -1;
2208 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002209 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2210 return 0;
2211
Willy Tarreaubaaee002006-06-26 02:48:02 +02002212 if (*(args[1]) == 0) {
2213 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2214 return -1;
2215 }
2216
2217 preg = calloc(1, sizeof(regex_t));
2218 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2219 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2220 return -1;
2221 }
2222
2223 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2224 }
2225 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2226 regex_t *preg;
2227 if (curproxy == &defproxy) {
2228 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2229 return -1;
2230 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002231 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2232 return 0;
2233
Willy Tarreaubaaee002006-06-26 02:48:02 +02002234 if (*(args[1]) == 0) {
2235 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2236 return -1;
2237 }
2238
2239 preg = calloc(1, sizeof(regex_t));
2240 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2241 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2242 return -1;
2243 }
2244
2245 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2246 }
2247 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2248 regex_t *preg;
2249 if (curproxy == &defproxy) {
2250 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2251 return -1;
2252 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002253 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2254 return 0;
2255
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 if (*(args[1]) == 0) {
2257 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2258 return -1;
2259 }
2260
2261 preg = calloc(1, sizeof(regex_t));
2262 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2263 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2264 return -1;
2265 }
2266
2267 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2268 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002269 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2270 regex_t *preg;
2271 if (curproxy == &defproxy) {
2272 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2273 return -1;
2274 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002275 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2276 return 0;
2277
Willy Tarreaub8750a82006-09-03 09:56:00 +02002278 if (*(args[1]) == 0) {
2279 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2280 return -1;
2281 }
2282
2283 preg = calloc(1, sizeof(regex_t));
2284 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2285 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2286 return -1;
2287 }
2288
2289 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2290 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002291 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2292 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002293 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002294 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2295 return -1;
2296 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002297 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2298 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002299
Willy Tarreau977b8e42006-12-29 14:19:17 +01002300 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002301 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2302 file, linenum, args[0]);
2303 return -1;
2304 }
2305
2306 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002307 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002308 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2309 }
2310
2311 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2312 }
2313 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2314 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002315 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002316 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2317 return -1;
2318 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002319 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2320 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002321
Willy Tarreau977b8e42006-12-29 14:19:17 +01002322 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002323 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2324 file, linenum, args[0]);
2325 return -1;
2326 }
2327
2328 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002329 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002330 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2331 }
2332
2333 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2334 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2336 regex_t *preg;
2337 if (curproxy == &defproxy) {
2338 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2339 return -1;
2340 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002341 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2342 return 0;
2343
Willy Tarreaubaaee002006-06-26 02:48:02 +02002344 if (*(args[1]) == 0 || *(args[2]) == 0) {
2345 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2346 file, linenum, args[0]);
2347 return -1;
2348 }
2349
2350 preg = calloc(1, sizeof(regex_t));
2351 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2352 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2353 return -1;
2354 }
2355
2356 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2357 if (err) {
2358 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2359 file, linenum, *err);
2360 return -1;
2361 }
2362 }
2363 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2364 regex_t *preg;
2365 if (curproxy == &defproxy) {
2366 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2367 return -1;
2368 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002369 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2370 return 0;
2371
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 if (*(args[1]) == 0) {
2373 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2374 return -1;
2375 }
2376
2377 preg = calloc(1, sizeof(regex_t));
2378 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2379 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2380 return -1;
2381 }
2382
2383 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2384 }
2385 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2386 regex_t *preg;
2387 if (curproxy == &defproxy) {
2388 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2389 return -1;
2390 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002391 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2392 return 0;
2393
Willy Tarreaubaaee002006-06-26 02:48:02 +02002394 if (*(args[1]) == 0) {
2395 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2396 return -1;
2397 }
2398
2399 preg = calloc(1, sizeof(regex_t));
2400 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2401 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2402 return -1;
2403 }
2404
2405 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2406 }
2407 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2408 regex_t *preg;
2409 if (curproxy == &defproxy) {
2410 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2411 return -1;
2412 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002413 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2414 return 0;
2415
Willy Tarreaubaaee002006-06-26 02:48:02 +02002416 if (*(args[1]) == 0) {
2417 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2418 return -1;
2419 }
2420
2421 preg = calloc(1, sizeof(regex_t));
2422 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2423 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2424 return -1;
2425 }
2426
2427 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2428 }
2429 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2430 regex_t *preg;
2431 if (curproxy == &defproxy) {
2432 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2433 return -1;
2434 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002435 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2436 return 0;
2437
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 if (*(args[1]) == 0) {
2439 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2440 return -1;
2441 }
2442
2443 preg = calloc(1, sizeof(regex_t));
2444 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2445 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2446 return -1;
2447 }
2448
2449 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2450 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002451 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2452 regex_t *preg;
2453 if (curproxy == &defproxy) {
2454 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2455 return -1;
2456 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002457 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2458 return 0;
2459
Willy Tarreaub8750a82006-09-03 09:56:00 +02002460 if (*(args[1]) == 0) {
2461 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2462 return -1;
2463 }
2464
2465 preg = calloc(1, sizeof(regex_t));
2466 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2467 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2468 return -1;
2469 }
2470
2471 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2474 if (curproxy == &defproxy) {
2475 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2476 return -1;
2477 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002478 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2479 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480
2481 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2482 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2483 return 0;
2484 }
2485
2486 if (*(args[1]) == 0) {
2487 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2488 return -1;
2489 }
2490
2491 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2492 }
2493 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2494 regex_t *preg;
2495
2496 if (*(args[1]) == 0 || *(args[2]) == 0) {
2497 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2498 file, linenum, args[0]);
2499 return -1;
2500 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002501 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2502 return 0;
2503
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504 preg = calloc(1, sizeof(regex_t));
2505 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2506 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2507 return -1;
2508 }
2509
2510 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2511 if (err) {
2512 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2513 file, linenum, *err);
2514 return -1;
2515 }
2516 }
2517 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2518 regex_t *preg;
2519 if (curproxy == &defproxy) {
2520 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2521 return -1;
2522 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002523 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2524 return 0;
2525
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 if (*(args[1]) == 0) {
2527 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2528 return -1;
2529 }
2530
2531 preg = calloc(1, sizeof(regex_t));
2532 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2533 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2534 return -1;
2535 }
2536
2537 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2538 if (err) {
2539 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2540 file, linenum, *err);
2541 return -1;
2542 }
2543 }
2544 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2545 regex_t *preg;
2546 if (curproxy == &defproxy) {
2547 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2548 return -1;
2549 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002550 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2551 return 0;
2552
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 if (*(args[1]) == 0) {
2554 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2555 return -1;
2556 }
2557
2558 preg = calloc(1, sizeof(regex_t));
2559 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2560 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2561 return -1;
2562 }
2563
2564 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2565 if (err) {
2566 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2567 file, linenum, *err);
2568 return -1;
2569 }
2570 }
2571 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2572 regex_t *preg;
2573 if (curproxy == &defproxy) {
2574 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2575 return -1;
2576 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002577 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2578 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579
2580 if (*(args[1]) == 0 || *(args[2]) == 0) {
2581 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2582 file, linenum, args[0]);
2583 return -1;
2584 }
2585
2586 preg = calloc(1, sizeof(regex_t));
2587 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2588 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2589 return -1;
2590 }
2591
2592 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2593 if (err) {
2594 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2595 file, linenum, *err);
2596 return -1;
2597 }
2598 }
2599 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2600 regex_t *preg;
2601 if (curproxy == &defproxy) {
2602 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2603 return -1;
2604 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002605 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2606 return 0;
2607
Willy Tarreaubaaee002006-06-26 02:48:02 +02002608 if (*(args[1]) == 0) {
2609 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2610 return -1;
2611 }
2612
2613 preg = calloc(1, sizeof(regex_t));
2614 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2615 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2616 return -1;
2617 }
2618
2619 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2620 if (err) {
2621 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2622 file, linenum, *err);
2623 return -1;
2624 }
2625 }
2626 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2627 regex_t *preg;
2628 if (curproxy == &defproxy) {
2629 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2630 return -1;
2631 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002632 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2633 return 0;
2634
Willy Tarreaubaaee002006-06-26 02:48:02 +02002635 if (*(args[1]) == 0) {
2636 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2637 return -1;
2638 }
2639
2640 preg = calloc(1, sizeof(regex_t));
2641 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2642 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2643 return -1;
2644 }
2645
2646 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2647 if (err) {
2648 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2649 file, linenum, *err);
2650 return -1;
2651 }
2652 }
2653 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2654 if (curproxy == &defproxy) {
2655 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2656 return -1;
2657 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002658 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2659 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002660
2661 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2662 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2663 return 0;
2664 }
2665
2666 if (*(args[1]) == 0) {
2667 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2668 return -1;
2669 }
2670
2671 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2672 }
2673 else if (!strcmp(args[0], "errorloc") ||
2674 !strcmp(args[0], "errorloc302") ||
2675 !strcmp(args[0], "errorloc303")) { /* error location */
2676 int errnum, errlen;
2677 char *err;
2678
Willy Tarreau977b8e42006-12-29 14:19:17 +01002679 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2680 return 0;
2681
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002683 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 return -1;
2685 }
2686
2687 errnum = atol(args[1]);
2688 if (!strcmp(args[0], "errorloc303")) {
2689 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2690 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2691 } else {
2692 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2693 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2694 }
2695
Willy Tarreau0f772532006-12-23 20:51:41 +01002696 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2697 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002698 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002699 curproxy->errmsg[rc].str = err;
2700 curproxy->errmsg[rc].len = errlen;
2701 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002703 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002704
2705 if (rc >= HTTP_ERR_SIZE) {
2706 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2707 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002708 free(err);
2709 }
2710 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002711 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2712 int errnum, errlen, fd;
2713 char *err;
2714 struct stat stat;
2715
2716 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2717 return 0;
2718
2719 if (*(args[2]) == 0) {
2720 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2721 return -1;
2722 }
2723
2724 fd = open(args[2], O_RDONLY);
2725 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2726 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2727 file, linenum, args[2], args[1]);
2728 if (fd >= 0)
2729 close(fd);
2730 return -1;
2731 }
2732
2733 if (stat.st_size <= BUFSIZE) {
2734 errlen = stat.st_size;
2735 } else {
2736 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2737 file, linenum, args[2], BUFSIZE);
2738 errlen = BUFSIZE;
2739 }
2740
2741 err = malloc(errlen); /* malloc() must succeed during parsing */
2742 errnum = read(fd, err, errlen);
2743 if (errnum != errlen) {
2744 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2745 file, linenum, args[2], args[1]);
2746 close(fd);
2747 free(err);
2748 return -1;
2749 }
2750 close(fd);
2751
2752 errnum = atol(args[1]);
2753 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2754 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002755 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002756 curproxy->errmsg[rc].str = err;
2757 curproxy->errmsg[rc].len = errlen;
2758 break;
2759 }
2760 }
2761
2762 if (rc >= HTTP_ERR_SIZE) {
2763 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2764 file, linenum, errnum);
2765 free(err);
2766 }
2767 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002768 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002769 struct cfg_kw_list *kwl;
2770 int index;
2771
2772 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2773 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2774 if (kwl->kw[index].section != CFG_LISTEN)
2775 continue;
2776 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2777 /* prepare error message just in case */
2778 snprintf(trash, sizeof(trash),
2779 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002780 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2781 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002782 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2783 return -1;
2784 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002785 else if (rc > 0) {
2786 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2787 return 0;
2788 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002789 return 0;
2790 }
2791 }
2792 }
2793
Willy Tarreau6daf3432008-01-22 16:44:08 +01002794 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002795 return -1;
2796 }
2797 return 0;
2798}
2799
2800
2801/*
2802 * This function reads and parses the configuration file given in the argument.
2803 * returns 0 if OK, -1 if error.
2804 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002805int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002806{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002807 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808 FILE *f;
2809 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002810 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002811 int confsect = CFG_NONE;
2812
2813 struct proxy *curproxy = NULL;
2814 struct server *newsrv = NULL;
2815
2816 if ((f=fopen(file,"r")) == NULL)
2817 return -1;
2818
2819 init_default_instance();
2820
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002821 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002822 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002823 char *end;
2824 char *args[MAX_LINE_ARGS + 1];
2825 char *line = thisline;
2826
Willy Tarreaubaaee002006-06-26 02:48:02 +02002827 linenum++;
2828
2829 end = line + strlen(line);
2830
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002831 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2832 /* Check if we reached the limit and the last char is not \n.
2833 * Watch out for the last line without the terminating '\n'!
2834 */
2835 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2836 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002837 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002838 }
2839
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002841 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002842 line++;
2843
2844 arg = 0;
2845 args[arg] = line;
2846
2847 while (*line && arg < MAX_LINE_ARGS) {
2848 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2849 * C equivalent value. Other combinations left unchanged (eg: \1).
2850 */
2851 if (*line == '\\') {
2852 int skip = 0;
2853 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2854 *line = line[1];
2855 skip = 1;
2856 }
2857 else if (line[1] == 'r') {
2858 *line = '\r';
2859 skip = 1;
2860 }
2861 else if (line[1] == 'n') {
2862 *line = '\n';
2863 skip = 1;
2864 }
2865 else if (line[1] == 't') {
2866 *line = '\t';
2867 skip = 1;
2868 }
2869 else if (line[1] == 'x') {
2870 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2871 unsigned char hex1, hex2;
2872 hex1 = toupper(line[2]) - '0';
2873 hex2 = toupper(line[3]) - '0';
2874 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2875 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2876 *line = (hex1<<4) + hex2;
2877 skip = 3;
2878 }
2879 else {
2880 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002881 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882 }
2883 }
2884 if (skip) {
2885 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2886 end -= skip;
2887 }
2888 line++;
2889 }
2890 else if (*line == '#' || *line == '\n' || *line == '\r') {
2891 /* end of string, end of loop */
2892 *line = 0;
2893 break;
2894 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002895 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002897 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002898 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899 line++;
2900 args[++arg] = line;
2901 }
2902 else {
2903 line++;
2904 }
2905 }
2906
2907 /* empty line */
2908 if (!**args)
2909 continue;
2910
Willy Tarreau540abe42007-05-02 20:50:16 +02002911 /* zero out remaining args and ensure that at least one entry
2912 * is zeroed out.
2913 */
2914 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 args[arg] = line;
2916 }
2917
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002918 if (!strcmp(args[0], "no")) {
2919 inv = 1;
2920 for (arg=0; *args[arg+1]; arg++)
2921 args[arg] = args[arg+1]; // shift args after inversion
2922 }
2923
2924 if (inv && strcmp(args[0], "option")) {
2925 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002926 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002927 }
2928
Willy Tarreau977b8e42006-12-29 14:19:17 +01002929 if (!strcmp(args[0], "listen") ||
2930 !strcmp(args[0], "frontend") ||
2931 !strcmp(args[0], "backend") ||
2932 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002933 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002935 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002936 cursection = strdup(args[0]);
2937 }
2938 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002939 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002940 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002941 cursection = strdup(args[0]);
2942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002943 /* else it's a section keyword */
2944
2945 switch (confsect) {
2946 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002947 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002948 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002949 break;
2950 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002951 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002952 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002953 break;
2954 default:
2955 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002956 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002957 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002958 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002959 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002960 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002961 fclose(f);
2962
2963 /*
2964 * Now, check for the integrity of all that we have collected.
2965 */
2966
2967 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002968 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969
2970 if ((curproxy = proxy) == NULL) {
2971 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2972 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002973 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002974 }
2975
2976 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002977 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002978 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002979
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02002981 /* ensure we don't keep listeners uselessly bound */
2982 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002983 curproxy = curproxy->next;
2984 continue;
2985 }
2986
Willy Tarreau977b8e42006-12-29 14:19:17 +01002987 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2988 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 +01002989 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002990 cfgerr++;
2991 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002992 else if (curproxy->cap & PR_CAP_BE &&
2993 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002994 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002995 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002996 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2997 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 +01002998 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002999 cfgerr++;
3000 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003001
Willy Tarreau31682232007-11-29 15:38:04 +01003002 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003004 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003005 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003006 cfgerr++;
3007 }
3008#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
3009 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003010 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003011 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003012 cfgerr++;
3013 }
3014#endif
3015 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003016 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003017 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018 }
3019 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003020
3021 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003022 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003023 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003024 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003025 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003026 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003027 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003028 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 }
3030 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003031 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003032 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003034 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003035 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003036 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003037 }
Willy Tarreaudf366142007-11-30 16:23:20 +01003038 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01003039 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3040 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003041
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01003042 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003043 file, proxy_type_str(curproxy), curproxy->id);
3044 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003045 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003046
3047 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
3048 if ((newsrv = curproxy->srv) != NULL) {
3049 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
3050 file, proxy_type_str(curproxy), curproxy->id);
3051 }
3052 }
3053
3054 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
3056 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
3057 file, curproxy->id);
3058 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003059 }
3060 }
3061
Willy Tarreau82936582007-11-30 15:20:09 +01003062 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3063 curproxy->options &= ~PR_O_DISABLE404;
3064 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3065 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
3066 }
3067
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003068 /* if a default backend was specified, let's find it */
3069 if (curproxy->defbe.name) {
3070 struct proxy *target;
3071
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003072 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3073 if (!target) {
3074 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3075 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003076 cfgerr++;
3077 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003078 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3079 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003080 } else {
3081 free(curproxy->defbe.name);
3082 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 }
3084 }
3085
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003086 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003087 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3088 /* map jump target for ACT_SETBE in req_rep chain */
3089 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003090 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003091 struct proxy *target;
3092
Willy Tarreaua496b602006-12-17 23:15:24 +01003093 if (exp->action != ACT_SETBE)
3094 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003095
3096 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3097 if (!target) {
3098 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3099 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003100 cfgerr++;
3101 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003102 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3103 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003104 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003105 } else {
3106 free((void *)exp->replace);
3107 exp->replace = (const char *)target;
3108 }
3109 }
3110 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003111
3112 /* find the target proxy for 'use_backend' rules */
3113 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003114 struct proxy *target;
3115
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003116 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003117
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003118 if (!target) {
3119 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3120 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003121 cfgerr++;
3122 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003123 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3124 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003125 cfgerr++;
3126 } else {
3127 free((void *)rule->be.name);
3128 rule->be.backend = target;
3129 }
3130 }
3131
Willy Tarreau2738a142006-07-08 17:28:09 +02003132 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003133 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003134 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003135 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003136 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003137 " | While not properly invalid, you will certainly encounter various problems\n"
3138 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003139 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003140 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003141 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003142
Willy Tarreau1fa31262007-12-03 00:36:16 +01003143 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3144 * We must still support older configurations, so let's find out whether those
3145 * parameters have been set or must be copied from contimeouts.
3146 */
3147 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003148 if (!curproxy->timeout.tarpit ||
3149 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003150 /* tarpit timeout not set. We search in the following order:
3151 * default.tarpit, curr.connect, default.connect.
3152 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003153 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003154 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003155 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003156 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003157 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003158 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003159 }
3160 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003161 (!curproxy->timeout.queue ||
3162 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003163 /* queue timeout not set. We search in the following order:
3164 * default.queue, curr.connect, default.connect.
3165 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003166 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003167 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003168 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003169 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003170 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003171 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003172 }
3173 }
3174
Willy Tarreauf3c69202006-07-09 16:42:34 +02003175 if (curproxy->options & PR_O_SSL3_CHK) {
3176 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3177 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3178 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3179 }
3180
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003181 /* The small pools required for the capture lists */
3182 if (curproxy->nb_req_cap)
3183 curproxy->req_cap_pool = create_pool("ptrcap",
3184 curproxy->nb_req_cap * sizeof(char *),
3185 MEM_F_SHARED);
3186 if (curproxy->nb_rsp_cap)
3187 curproxy->rsp_cap_pool = create_pool("ptrcap",
3188 curproxy->nb_rsp_cap * sizeof(char *),
3189 MEM_F_SHARED);
3190
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003191 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3192 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3193 MEM_F_SHARED);
3194
Willy Tarreau86034312006-12-29 00:10:33 +01003195 /* for backwards compatibility with "listen" instances, if
3196 * fullconn is not set but maxconn is set, then maxconn
3197 * is used.
3198 */
3199 if (!curproxy->fullconn)
3200 curproxy->fullconn = curproxy->maxconn;
3201
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202 /* first, we will invert the servers list order */
3203 newsrv = NULL;
3204 while (curproxy->srv) {
3205 struct server *next;
3206
3207 next = curproxy->srv->next;
3208 curproxy->srv->next = newsrv;
3209 newsrv = curproxy->srv;
3210 if (!next)
3211 break;
3212 curproxy->srv = next;
3213 }
3214
Willy Tarreau20697042007-11-15 23:26:18 +01003215 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003216 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217
Willy Tarreaub625a082007-11-26 01:15:43 +01003218 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003219 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003220 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003221 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3222 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003223 else
3224 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003225
3226 if (curproxy->options & PR_O_LOGASAP)
3227 curproxy->to_log &= ~LW_BYTES;
3228
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003230 * ensure that we're not cross-dressing a TCP server into HTTP.
3231 */
3232 newsrv = curproxy->srv;
3233 while (newsrv != NULL) {
3234 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3235 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3236 file, proxy_type_str(curproxy), curproxy->id, linenum);
3237 goto err;
3238 }
3239 newsrv = newsrv->next;
3240 }
3241
3242 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 * If this server supports a maxconn parameter, it needs a dedicated
3244 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003245 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003246 */
3247 newsrv = curproxy->srv;
3248 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003249 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 /* Only 'minconn' was specified, or it was higher than or equal
3251 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3252 * this will avoid further useless expensive computations.
3253 */
3254 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003255 } else if (newsrv->maxconn && !newsrv->minconn) {
3256 /* minconn was not specified, so we set it to maxconn */
3257 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003258 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3259 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003260 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003261 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003262 }
3263
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003264 if (newsrv->trackit) {
3265 struct proxy *px;
3266 struct server *srv;
3267 char *pname, *sname;
3268
3269 pname = newsrv->trackit;
3270 sname = strrchr(pname, '/');
3271
3272 if (sname)
3273 *sname++ = '\0';
3274 else {
3275 sname = pname;
3276 pname = NULL;
3277 }
3278
3279 if (pname) {
3280 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3281 if (!px) {
3282 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3283 file, proxy_type_str(curproxy), curproxy->id,
3284 newsrv->id, pname);
3285 return -1;
3286 }
3287 } else
3288 px = curproxy;
3289
3290 srv = findserver(px, sname);
3291 if (!srv) {
3292 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3293 file, proxy_type_str(curproxy), curproxy->id,
3294 newsrv->id, sname);
3295 return -1;
3296 }
3297
3298 if (!(srv->state & SRV_CHECKED)) {
3299 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3300 "tracing as it does not have checks enabled.\n",
3301 file, proxy_type_str(curproxy), curproxy->id,
3302 newsrv->id, px->id, srv->id);
3303 return -1;
3304 }
3305
3306 if (curproxy != px &&
3307 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3308 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3309 "tracing: disable-on-404 option inconsistency.\n",
3310 file, proxy_type_str(curproxy), curproxy->id,
3311 newsrv->id, px->id, srv->id);
3312 return -1;
3313 }
3314
3315 newsrv->tracked = srv;
3316 newsrv->tracknext = srv->tracknext;
3317 srv->tracknext = newsrv;
3318
3319 free(newsrv->trackit);
3320 }
3321
Willy Tarreaubaaee002006-06-26 02:48:02 +02003322 newsrv = newsrv->next;
3323 }
3324
Willy Tarreaue6b98942007-10-29 01:09:36 +01003325 /* adjust this proxy's listeners */
3326 listener = curproxy->listen;
3327 while (listener) {
3328 if (curproxy->options & PR_O_TCP_NOLING)
3329 listener->options |= LI_O_NOLINGER;
3330 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003331 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003332 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003333 listener->accept = event_accept;
3334 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003335 listener->handler = process_session;
3336
3337 if (curproxy->mode == PR_MODE_HTTP)
3338 listener->analysers |= AN_REQ_HTTP_HDR;
3339
3340 if (curproxy->tcp_req.inspect_delay)
3341 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003342
3343 listener = listener->next;
3344 }
3345
Willy Tarreaubaaee002006-06-26 02:48:02 +02003346 curproxy = curproxy->next;
3347 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003348
Willy Tarreaubaaee002006-06-26 02:48:02 +02003349 if (cfgerr > 0) {
3350 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003351 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003353
3354 /*
3355 * Recount currently required checks.
3356 */
3357
3358 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3359 int optnum;
3360
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003361 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3362 if (curproxy->options & cfg_opts[optnum].val)
3363 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003364
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003365 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3366 if (curproxy->options2 & cfg_opts2[optnum].val)
3367 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003368 }
3369
Willy Tarreaua534fea2008-08-03 12:19:50 +02003370 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003371 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003372 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003373
3374 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003375 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003376 cursection = NULL;
3377 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378}
3379
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003380/*
3381 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3382 * parsing sessions.
3383 */
3384void cfg_register_keywords(struct cfg_kw_list *kwl)
3385{
3386 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3387}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003388
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003389/*
3390 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3391 */
3392void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3393{
3394 LIST_DEL(&kwl->list);
3395 LIST_INIT(&kwl->list);
3396}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397
3398/*
3399 * Local variables:
3400 * c-indent-level: 8
3401 * c-basic-offset: 8
3402 * End:
3403 */