blob: af72b15f292c1ba3bb391dee700014d74dcb6c9e [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>
35#include <types/polling.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036
Willy Tarreaueb0c6142007-05-07 00:53:22 +020037#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010039#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020041#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010044#include <proto/protocols.h>
45#include <proto/proto_tcp.h>
46#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010047#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010049#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <proto/task.h>
51
52
Willy Tarreauf3c69202006-07-09 16:42:34 +020053/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
54 * ssl-hello-chk option to ensure that the remote server speaks SSL.
55 *
56 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
57 */
58const char sslv3_client_hello_pkt[] = {
59 "\x16" /* ContentType : 0x16 = Hanshake */
60 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
61 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
62 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
63 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
64 "\x03\x00" /* Hello Version : 0x0300 = v3 */
65 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
66 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
67 "\x00" /* Session ID length : empty (no session ID) */
68 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
69 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
70 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
71 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
72 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
73 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
74 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
75 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
76 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
77 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
78 "\x00\x38" "\x00\x39" "\x00\x3A"
79 "\x01" /* Compression Length : 0x01 = 1 byte for types */
80 "\x00" /* Compression Type : 0x00 = NULL compression */
81};
82
Willy Tarreau13943ab2006-12-31 00:24:10 +010083/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010084struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010085 const char *name;
86 unsigned int val;
87 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010088 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +010089};
90
91/* proxy->options */
92static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +010093{
Willy Tarreau4fee4e92007-01-06 21:09:17 +010094 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010095 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010096 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010097 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010098 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
99 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
100 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
101 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
102 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
103 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
104 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
105 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100106 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100107 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
108 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100109#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100110 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
111#endif
112#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100113 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100114#endif
115
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100116 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100117};
118
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100119/* proxy->options2 */
120static const struct cfg_opt cfg_opts2[] =
121{
122#ifdef CONFIG_HAP_LINUX_SPLICE
123 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
124 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
125 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
126#endif
127 { NULL, 0, 0, 0 }
128};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200129
Willy Tarreau6daf3432008-01-22 16:44:08 +0100130static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200131static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
132int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
133int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
134
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200135/* List head of all known configuration keywords */
136static struct cfg_kw_list cfg_keywords = {
137 .list = LIST_HEAD_INIT(cfg_keywords.list)
138};
139
Willy Tarreaubaaee002006-06-26 02:48:02 +0200140/*
141 * converts <str> to a list of listeners which are dynamically allocated.
142 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
143 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
144 * - <port> is a numerical port from 1 to 65535 ;
145 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
146 * This can be repeated as many times as necessary, separated by a coma.
147 * The <tail> argument is a pointer to a current list which should be appended
148 * to the tail of the new list. The pointer to the new list is returned.
149 */
150static struct listener *str2listener(char *str, struct listener *tail)
151{
152 struct listener *l;
153 char *c, *next, *range, *dupstr;
154 int port, end;
155
156 next = dupstr = strdup(str);
157
158 while (next && *next) {
159 struct sockaddr_storage ss;
160
161 str = next;
162 /* 1) look for the end of the first address */
163 if ((next = strrchr(str, ',')) != NULL) {
164 *next++ = 0;
165 }
166
167 /* 2) look for the addr/port delimiter, it's the last colon. */
168 if ((range = strrchr(str, ':')) == NULL) {
169 Alert("Missing port number: '%s'\n", str);
170 goto fail;
171 }
172
173 *range++ = 0;
174
175 if (strrchr(str, ':') != NULL) {
176 /* IPv6 address contains ':' */
177 memset(&ss, 0, sizeof(ss));
178 ss.ss_family = AF_INET6;
179
180 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
181 Alert("Invalid server address: '%s'\n", str);
182 goto fail;
183 }
184 }
185 else {
186 memset(&ss, 0, sizeof(ss));
187 ss.ss_family = AF_INET;
188
189 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
190 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
191 }
192 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
193 struct hostent *he;
194
195 if ((he = gethostbyname(str)) == NULL) {
196 Alert("Invalid server name: '%s'\n", str);
197 goto fail;
198 }
199 else
200 ((struct sockaddr_in *)&ss)->sin_addr =
201 *(struct in_addr *) *(he->h_addr_list);
202 }
203 }
204
205 /* 3) look for the port-end delimiter */
206 if ((c = strchr(range, '-')) != NULL) {
207 *c++ = 0;
208 end = atol(c);
209 }
210 else {
211 end = atol(range);
212 }
213
214 port = atol(range);
215
216 if (port < 1 || port > 65535) {
217 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
218 goto fail;
219 }
220
221 if (end < 1 || end > 65535) {
222 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
223 goto fail;
224 }
225
226 for (; port <= end; port++) {
227 l = (struct listener *)calloc(1, sizeof(struct listener));
228 l->next = tail;
229 tail = l;
230
231 l->fd = -1;
232 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100233 l->state = LI_INIT;
234
235 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100237 tcpv6_add_listener(l);
238 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100240 tcpv4_add_listener(l);
241 }
242 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 } /* end for(port) */
244 } /* end while(next) */
245 free(dupstr);
246 return tail;
247 fail:
248 free(dupstr);
249 return NULL;
250}
251
Willy Tarreau977b8e42006-12-29 14:19:17 +0100252/*
253 * Sends a warning if proxy <proxy> does not have at least one of the
254 * capabilities in <cap>. An optionnal <hint> may be added at the end
255 * of the warning to help the user. Returns 1 if a warning was emitted
256 * or 0 if the condition is valid.
257 */
258int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
259{
260 char *msg;
261
262 switch (cap) {
263 case PR_CAP_BE: msg = "no backend"; break;
264 case PR_CAP_FE: msg = "no frontend"; break;
265 case PR_CAP_RS: msg = "no ruleset"; break;
266 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
267 default: msg = "not enough"; break;
268 }
269
270 if (!(proxy->cap & cap)) {
271 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100272 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100273 return 1;
274 }
275 return 0;
276}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200277
278/*
279 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
280 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100281int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200282{
283
284 if (!strcmp(args[0], "global")) { /* new section */
285 /* no option, nothing special to do */
286 return 0;
287 }
288 else if (!strcmp(args[0], "daemon")) {
289 global.mode |= MODE_DAEMON;
290 }
291 else if (!strcmp(args[0], "debug")) {
292 global.mode |= MODE_DEBUG;
293 }
294 else if (!strcmp(args[0], "noepoll")) {
295 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
296 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200297 else if (!strcmp(args[0], "nosepoll")) {
298 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
299 }
300 else if (!strcmp(args[0], "nokqueue")) {
301 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
302 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200303 else if (!strcmp(args[0], "nopoll")) {
304 cfg_polling_mechanism &= ~POLL_USE_POLL;
305 }
306 else if (!strcmp(args[0], "quiet")) {
307 global.mode |= MODE_QUIET;
308 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200309 else if (!strcmp(args[0], "tune.maxpollevents")) {
310 if (global.tune.maxpollevents != 0) {
311 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
312 return 0;
313 }
314 if (*(args[1]) == 0) {
315 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
316 return -1;
317 }
318 global.tune.maxpollevents = atol(args[1]);
319 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100320 else if (!strcmp(args[0], "tune.maxaccept")) {
321 if (global.tune.maxaccept != 0) {
322 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
323 return 0;
324 }
325 if (*(args[1]) == 0) {
326 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
327 return -1;
328 }
329 global.tune.maxaccept = atol(args[1]);
330 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200331 else if (!strcmp(args[0], "uid")) {
332 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200333 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200334 return 0;
335 }
336 if (*(args[1]) == 0) {
337 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
338 return -1;
339 }
340 global.uid = atol(args[1]);
341 }
342 else if (!strcmp(args[0], "gid")) {
343 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200344 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200345 return 0;
346 }
347 if (*(args[1]) == 0) {
348 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
349 return -1;
350 }
351 global.gid = atol(args[1]);
352 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200353 /* user/group name handling */
354 else if (!strcmp(args[0], "user")) {
355 struct passwd *ha_user;
356 if (global.uid != 0) {
357 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
358 return 0;
359 }
360 errno = 0;
361 ha_user = getpwnam(args[1]);
362 if (ha_user != NULL) {
363 global.uid = (int)ha_user->pw_uid;
364 }
365 else {
366 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
367 exit(1);
368 }
369 }
370 else if (!strcmp(args[0], "group")) {
371 struct group *ha_group;
372 if (global.gid != 0) {
373 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
374 return 0;
375 }
376 errno = 0;
377 ha_group = getgrnam(args[1]);
378 if (ha_group != NULL) {
379 global.gid = (int)ha_group->gr_gid;
380 }
381 else {
382 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
383 exit(1);
384 }
385 }
386 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200387 else if (!strcmp(args[0], "nbproc")) {
388 if (global.nbproc != 0) {
389 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
390 return 0;
391 }
392 if (*(args[1]) == 0) {
393 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
394 return -1;
395 }
396 global.nbproc = atol(args[1]);
397 }
398 else if (!strcmp(args[0], "maxconn")) {
399 if (global.maxconn != 0) {
400 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
401 return 0;
402 }
403 if (*(args[1]) == 0) {
404 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
405 return -1;
406 }
407 global.maxconn = atol(args[1]);
408#ifdef SYSTEM_MAXCONN
409 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
410 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);
411 global.maxconn = DEFAULT_MAXCONN;
412 }
413#endif /* SYSTEM_MAXCONN */
414 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100415 else if (!strcmp(args[0], "maxpipes")) {
416 if (global.maxpipes != 0) {
417 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
418 return 0;
419 }
420 if (*(args[1]) == 0) {
421 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
422 return -1;
423 }
424 global.maxpipes = atol(args[1]);
425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200426 else if (!strcmp(args[0], "ulimit-n")) {
427 if (global.rlimit_nofile != 0) {
428 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
429 return 0;
430 }
431 if (*(args[1]) == 0) {
432 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
433 return -1;
434 }
435 global.rlimit_nofile = atol(args[1]);
436 }
437 else if (!strcmp(args[0], "chroot")) {
438 if (global.chroot != NULL) {
439 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
440 return 0;
441 }
442 if (*(args[1]) == 0) {
443 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
444 return -1;
445 }
446 global.chroot = strdup(args[1]);
447 }
448 else if (!strcmp(args[0], "pidfile")) {
449 if (global.pidfile != NULL) {
450 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
451 return 0;
452 }
453 if (*(args[1]) == 0) {
454 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
455 return -1;
456 }
457 global.pidfile = strdup(args[1]);
458 }
459 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100460 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 int facility, level;
462
463 if (*(args[1]) == 0 || *(args[2]) == 0) {
464 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
465 return -1;
466 }
467
468 facility = get_log_facility(args[2]);
469 if (facility < 0) {
470 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
471 exit(1);
472 }
473
474 level = 7; /* max syslog level = debug */
475 if (*(args[3])) {
476 level = get_log_level(args[3]);
477 if (level < 0) {
478 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
479 exit(1);
480 }
481 }
482
Robert Tsai81ae1952007-12-05 10:47:29 +0100483 if (args[1][0] == '/') {
484 logsrv.u.addr.sa_family = AF_UNIX;
485 logsrv.u.un = *str2sun(args[1]);
486 } else {
487 logsrv.u.addr.sa_family = AF_INET;
488 logsrv.u.in = *str2sa(args[1]);
489 if (!logsrv.u.in.sin_port)
490 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
491 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200492
493 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100494 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200495 global.logfac1 = facility;
496 global.loglev1 = level;
497 }
498 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100499 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200500 global.logfac2 = facility;
501 global.loglev2 = level;
502 }
503 else {
504 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
505 return -1;
506 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200507 }
508 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
509 if (global.spread_checks != 0) {
510 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
511 return 0;
512 }
513 if (*(args[1]) == 0) {
514 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
515 return -1;
516 }
517 global.spread_checks = atol(args[1]);
518 if (global.spread_checks < 0 || global.spread_checks > 50) {
519 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
520 return -1;
521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200522 }
523 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200524 struct cfg_kw_list *kwl;
525 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200526 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200527
528 list_for_each_entry(kwl, &cfg_keywords.list, list) {
529 for (index = 0; kwl->kw[index].kw != NULL; index++) {
530 if (kwl->kw[index].section != CFG_GLOBAL)
531 continue;
532 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
533 /* prepare error message just in case */
534 snprintf(trash, sizeof(trash),
535 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200536 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
537 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200538 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
539 return -1;
540 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200541 else if (rc > 0) {
542 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
543 return 0;
544 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200545 return 0;
546 }
547 }
548 }
549
Willy Tarreaubaaee002006-06-26 02:48:02 +0200550 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
551 return -1;
552 }
553 return 0;
554}
555
556
557static void init_default_instance()
558{
559 memset(&defproxy, 0, sizeof(defproxy));
560 defproxy.mode = PR_MODE_TCP;
561 defproxy.state = PR_STNEW;
562 defproxy.maxconn = cfg_maxpconn;
563 defproxy.conn_retries = CONN_RETRIES;
564 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200565
566 LIST_INIT(&defproxy.pendconns);
567 LIST_INIT(&defproxy.acl);
568 LIST_INIT(&defproxy.block_cond);
569 LIST_INIT(&defproxy.mon_fail_cond);
570 LIST_INIT(&defproxy.switching_rules);
571
Willy Tarreau3a70f942008-02-15 11:15:34 +0100572 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200573}
574
575/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100576 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
577 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200578 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100579int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580{
581 static struct proxy *curproxy = NULL;
582 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200583 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100584 int rc;
585 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200586
Willy Tarreau977b8e42006-12-29 14:19:17 +0100587 if (!strcmp(args[0], "listen"))
588 rc = PR_CAP_LISTEN;
589 else if (!strcmp(args[0], "frontend"))
590 rc = PR_CAP_FE | PR_CAP_RS;
591 else if (!strcmp(args[0], "backend"))
592 rc = PR_CAP_BE | PR_CAP_RS;
593 else if (!strcmp(args[0], "ruleset"))
594 rc = PR_CAP_RS;
595 else
596 rc = PR_CAP_NONE;
597
598 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 if (!*args[1]) {
600 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
601 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
602 file, linenum, args[0]);
603 return -1;
604 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200605
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100606 err = invalid_char(args[1]);
607 if (err) {
608 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
609 file, linenum, *err, args[0], args[1]);
610 return -1;
611 }
612
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200613 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
614 /*
615 * If there are two proxies with the same name only following
616 * combinations are allowed:
617 *
618 * listen backend frontend ruleset
619 * listen - - - -
620 * backend - - OK -
621 * frontend - OK - -
622 * ruleset - - - -
623 */
624
625 if (!strcmp(curproxy->id, args[1]) &&
626 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
627 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100628 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
629 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200630 }
631 }
632
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
634 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
635 return -1;
636 }
637
638 curproxy->next = proxy;
639 proxy = curproxy;
640 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200641 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200642 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200643 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100644 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200645 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200646 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647
Willy Tarreauee991362007-05-14 14:37:50 +0200648 /* Timeouts are defined as -1, so we cannot use the zeroed area
649 * as a default value.
650 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100651 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200652
653 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200654 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100655 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656
657 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100658 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200659 curproxy->listen = str2listener(args[2], curproxy->listen);
660 if (!curproxy->listen)
661 return -1;
662 global.maxsock++;
663 }
664
665 /* set default values */
666 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200667 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100668 curproxy->options2 = defproxy.options2;
Willy Tarreau31682232007-11-29 15:38:04 +0100669 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200670 curproxy->except_net = defproxy.except_net;
671 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200672
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200673 if (defproxy.fwdfor_hdr_len) {
674 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
675 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
676 }
677
Willy Tarreau977b8e42006-12-29 14:19:17 +0100678 if (curproxy->cap & PR_CAP_FE) {
679 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100680 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100681
682 /* initialize error relocations */
683 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
684 if (defproxy.errmsg[rc].str)
685 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
686 }
687
688 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
689 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200690
Willy Tarreau977b8e42006-12-29 14:19:17 +0100691 if (curproxy->cap & PR_CAP_BE) {
692 curproxy->fullconn = defproxy.fullconn;
693 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200694
Willy Tarreau977b8e42006-12-29 14:19:17 +0100695 if (defproxy.check_req)
696 curproxy->check_req = strdup(defproxy.check_req);
697 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698
Willy Tarreau977b8e42006-12-29 14:19:17 +0100699 if (defproxy.cookie_name)
700 curproxy->cookie_name = strdup(defproxy.cookie_name);
701 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100702
703 if (defproxy.url_param_name)
704 curproxy->url_param_name = strdup(defproxy.url_param_name);
705 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200707
Willy Tarreau977b8e42006-12-29 14:19:17 +0100708 if (curproxy->cap & PR_CAP_RS) {
709 if (defproxy.capture_name)
710 curproxy->capture_name = strdup(defproxy.capture_name);
711 curproxy->capture_namelen = defproxy.capture_namelen;
712 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714
Willy Tarreau977b8e42006-12-29 14:19:17 +0100715 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100716 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100717 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100718 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100719 curproxy->uri_auth = defproxy.uri_auth;
720 curproxy->mon_net = defproxy.mon_net;
721 curproxy->mon_mask = defproxy.mon_mask;
722 if (defproxy.monitor_uri)
723 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
724 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100725 if (defproxy.defbe.name)
726 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100727 }
728
729 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100730 curproxy->timeout.connect = defproxy.timeout.connect;
731 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100732 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100733 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100734 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100735 curproxy->source_addr = defproxy.source_addr;
736 }
737
Willy Tarreaubaaee002006-06-26 02:48:02 +0200738 curproxy->mode = defproxy.mode;
739 curproxy->logfac1 = defproxy.logfac1;
740 curproxy->logsrv1 = defproxy.logsrv1;
741 curproxy->loglev1 = defproxy.loglev1;
742 curproxy->logfac2 = defproxy.logfac2;
743 curproxy->logsrv2 = defproxy.logsrv2;
744 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200745 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100746 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
747 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200748
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 return 0;
750 }
751 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
752 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100753 /* FIXME-20070101: we should do this too at the end of the
754 * config parsing to free all default values.
755 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200756 free(defproxy.check_req);
757 free(defproxy.cookie_name);
758 free(defproxy.url_param_name);
759 free(defproxy.capture_name);
760 free(defproxy.monitor_uri);
761 free(defproxy.defbe.name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200762 free(defproxy.fwdfor_hdr_name);
763 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100764
Willy Tarreaua534fea2008-08-03 12:19:50 +0200765 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
766 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100767
Willy Tarreaubaaee002006-06-26 02:48:02 +0200768 /* we cannot free uri_auth because it might already be used */
769 init_default_instance();
770 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100771 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200772 return 0;
773 }
774 else if (curproxy == NULL) {
775 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
776 return -1;
777 }
778
Willy Tarreau977b8e42006-12-29 14:19:17 +0100779
780 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100782 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200783 if (curproxy == &defproxy) {
784 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
785 return -1;
786 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100787 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
788 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789
790 if (strchr(args[1], ':') == NULL) {
791 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
792 file, linenum, args[0]);
793 return -1;
794 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100795
796 last_listen = curproxy->listen;
797 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200798 if (!curproxy->listen)
799 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100800 if (*args[2]) {
801#ifdef CONFIG_HAP_LINUX_TPROXY
802 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
803 struct listener *l;
804
805 for (l = curproxy->listen; l != last_listen; l = l->next)
806 l->options |= LI_O_FOREIGN;
807 }
808 else {
809 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
810 file, linenum, args[0]);
811 return -1;
812 }
813#else
814 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
815 file, linenum, args[0]);
816 return -1;
817#endif
818 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200819 global.maxsock++;
820 return 0;
821 }
822 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
823 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
824 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
825 file, linenum, args[0]);
826 return -1;
827 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100828 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
829 return 0;
830
Willy Tarreaubaaee002006-06-26 02:48:02 +0200831 /* flush useless bits */
832 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
833 return 0;
834 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200835 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100836 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
837 return 0;
838
Willy Tarreau1c47f852006-07-09 08:22:27 +0200839 if (!*args[1]) {
840 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
841 file, linenum, args[0]);
842 return -1;
843 }
844
Willy Tarreaua534fea2008-08-03 12:19:50 +0200845 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100846 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200847 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100848 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200849 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
850
851 return 0;
852 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200853 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
854 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
855 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
856 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
857 else {
858 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
859 return -1;
860 }
861 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100862 else if (!strcmp(args[0], "id")) {
863 struct proxy *target;
864
865 if (curproxy == &defproxy) {
866 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
867 file, linenum, args[0]);
868 return -1;
869 }
870
871 if (!*args[1]) {
872 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
873 file, linenum, args[0]);
874 return -1;
875 }
876
877 curproxy->uuid = atol(args[1]);
878
879 if (curproxy->uuid < 1001) {
880 Alert("parsing [%s:%d]: custom id has to be > 1000",
881 file, linenum);
882 return -1;
883 }
884
885 for (target = proxy; target; target = target->next)
886 if (curproxy != target && curproxy->uuid == target->uuid) {
887 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
888 file, linenum, curproxy->id, target->id);
889 return -1;
890 }
891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
893 curproxy->state = PR_STSTOPPED;
894 }
895 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
896 curproxy->state = PR_STNEW;
897 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200898 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200899 if (curproxy == &defproxy) {
900 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
901 return -1;
902 }
903
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100904 err = invalid_char(args[1]);
905 if (err) {
906 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
907 file, linenum, *err, args[1]);
908 return -1;
909 }
910
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200911 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
912 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
913 file, linenum, args[1]);
914 return -1;
915 }
916 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 else if (!strcmp(args[0], "cookie")) { /* cookie name */
918 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919
Willy Tarreau977b8e42006-12-29 14:19:17 +0100920 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
921 return 0;
922
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 if (*(args[1]) == 0) {
924 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
925 file, linenum, args[0]);
926 return -1;
927 }
Willy Tarreaua534fea2008-08-03 12:19:50 +0200928
929 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 curproxy->cookie_name = strdup(args[1]);
931 curproxy->cookie_len = strlen(curproxy->cookie_name);
932
933 cur_arg = 2;
934 while (*(args[cur_arg])) {
935 if (!strcmp(args[cur_arg], "rewrite")) {
936 curproxy->options |= PR_O_COOK_RW;
937 }
938 else if (!strcmp(args[cur_arg], "indirect")) {
939 curproxy->options |= PR_O_COOK_IND;
940 }
941 else if (!strcmp(args[cur_arg], "insert")) {
942 curproxy->options |= PR_O_COOK_INS;
943 }
944 else if (!strcmp(args[cur_arg], "nocache")) {
945 curproxy->options |= PR_O_COOK_NOC;
946 }
947 else if (!strcmp(args[cur_arg], "postonly")) {
948 curproxy->options |= PR_O_COOK_POST;
949 }
950 else if (!strcmp(args[cur_arg], "prefix")) {
951 curproxy->options |= PR_O_COOK_PFX;
952 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200953 else if (!strcmp(args[cur_arg], "domain")) {
954 if (!*args[cur_arg + 1]) {
955 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
956 file, linenum, args[cur_arg]);
957 return -1;
958 }
959
960 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
961 /* rfc2109, 4.3.2 Rejecting Cookies */
962 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
963 " dots or does not start with a dot.\n",
964 file, linenum, args[cur_arg + 1]);
965 return -1;
966 }
967
968 err = invalid_domainchar(args[cur_arg + 1]);
969 if (err) {
970 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
971 file, linenum, *err, args[cur_arg + 1]);
972 return -1;
973 }
974
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +0200975 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200976 cur_arg++;
977 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200979 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 file, linenum, args[0]);
981 return -1;
982 }
983 cur_arg++;
984 }
985 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
986 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
987 file, linenum);
988 return -1;
989 }
990
991 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
992 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
993 file, linenum);
994 return -1;
995 }
996 }/* end else if (!strcmp(args[0], "cookie")) */
997 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200998
Willy Tarreau977b8e42006-12-29 14:19:17 +0100999 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1000 return 0;
1001
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 if (*(args[5]) == 0) {
1003 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1004 file, linenum, args[0]);
1005 return -1;
1006 }
1007 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001008 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001009 curproxy->appsession_name = strdup(args[1]);
1010 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1011 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001012 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1013 if (err) {
1014 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1015 file, linenum, *err, args[0]);
1016 return -1;
1017 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001018 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001019
Willy Tarreau51041c72007-09-09 21:56:53 +02001020 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1021 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001022 return -1;
1023 }
1024 } /* Url App Session */
1025 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001026 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1027 return 0;
1028
Willy Tarreaubaaee002006-06-26 02:48:02 +02001029 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001030 if (*(args[4]) == 0) {
1031 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1032 file, linenum, args[0]);
1033 return -1;
1034 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001035 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036 curproxy->capture_name = strdup(args[2]);
1037 curproxy->capture_namelen = strlen(curproxy->capture_name);
1038 curproxy->capture_len = atol(args[4]);
1039 if (curproxy->capture_len >= CAPTURE_LEN) {
1040 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1041 file, linenum, CAPTURE_LEN - 1);
1042 curproxy->capture_len = CAPTURE_LEN - 1;
1043 }
1044 curproxy->to_log |= LW_COOKIE;
1045 }
1046 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1047 struct cap_hdr *hdr;
1048
1049 if (curproxy == &defproxy) {
1050 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1051 return -1;
1052 }
1053
1054 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1055 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1056 file, linenum, args[0], args[1]);
1057 return -1;
1058 }
1059
1060 hdr = calloc(sizeof(struct cap_hdr), 1);
1061 hdr->next = curproxy->req_cap;
1062 hdr->name = strdup(args[3]);
1063 hdr->namelen = strlen(args[3]);
1064 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001065 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066 hdr->index = curproxy->nb_req_cap++;
1067 curproxy->req_cap = hdr;
1068 curproxy->to_log |= LW_REQHDR;
1069 }
1070 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1071 struct cap_hdr *hdr;
1072
1073 if (curproxy == &defproxy) {
1074 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1075 return -1;
1076 }
1077
1078 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1079 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1080 file, linenum, args[0], args[1]);
1081 return -1;
1082 }
1083 hdr = calloc(sizeof(struct cap_hdr), 1);
1084 hdr->next = curproxy->rsp_cap;
1085 hdr->name = strdup(args[3]);
1086 hdr->namelen = strlen(args[3]);
1087 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001088 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 hdr->index = curproxy->nb_rsp_cap++;
1090 curproxy->rsp_cap = hdr;
1091 curproxy->to_log |= LW_RSPHDR;
1092 }
1093 else {
1094 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1095 file, linenum, args[0]);
1096 return -1;
1097 }
1098 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001100 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1101 return 0;
1102
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 if (*(args[1]) == 0) {
1104 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1105 file, linenum, args[0]);
1106 return -1;
1107 }
1108 curproxy->conn_retries = atol(args[1]);
1109 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001110 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1111 int pol = ACL_COND_NONE;
1112 struct acl_cond *cond;
1113
Willy Tarreaub099aca2008-10-12 17:26:37 +02001114 if (curproxy == &defproxy) {
1115 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1116 return -1;
1117 }
1118
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001119 if (!strcmp(args[1], "if"))
1120 pol = ACL_COND_IF;
1121 else if (!strcmp(args[1], "unless"))
1122 pol = ACL_COND_UNLESS;
1123
1124 if (pol == ACL_COND_NONE) {
1125 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1126 file, linenum, args[0]);
1127 return -1;
1128 }
1129
1130 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1131 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1132 file, linenum);
1133 return -1;
1134 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001135 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001136 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1137 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001138 else if (!strcmp(args[0], "redirect")) {
1139 int pol = ACL_COND_NONE;
1140 struct acl_cond *cond;
1141 struct redirect_rule *rule;
1142 int cur_arg;
1143 int type = REDIRECT_TYPE_NONE;
1144 int code = 302;
1145 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001146 char *cookie = NULL;
1147 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001148 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001149
1150 cur_arg = 1;
1151 while (*(args[cur_arg])) {
1152 if (!strcmp(args[cur_arg], "location")) {
1153 if (!*args[cur_arg + 1]) {
1154 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1155 file, linenum, args[0], args[cur_arg]);
1156 return -1;
1157 }
1158
1159 type = REDIRECT_TYPE_LOCATION;
1160 cur_arg++;
1161 destination = args[cur_arg];
1162 }
1163 else if (!strcmp(args[cur_arg], "prefix")) {
1164 if (!*args[cur_arg + 1]) {
1165 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1166 file, linenum, args[0], args[cur_arg]);
1167 return -1;
1168 }
1169
1170 type = REDIRECT_TYPE_PREFIX;
1171 cur_arg++;
1172 destination = args[cur_arg];
1173 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001174 else if (!strcmp(args[cur_arg], "set-cookie")) {
1175 if (!*args[cur_arg + 1]) {
1176 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1177 file, linenum, args[0], args[cur_arg]);
1178 return -1;
1179 }
1180
1181 cur_arg++;
1182 cookie = args[cur_arg];
1183 cookie_set = 1;
1184 }
1185 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1186 if (!*args[cur_arg + 1]) {
1187 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1188 file, linenum, args[0], args[cur_arg]);
1189 return -1;
1190 }
1191
1192 cur_arg++;
1193 cookie = args[cur_arg];
1194 cookie_set = 0;
1195 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001196 else if (!strcmp(args[cur_arg],"code")) {
1197 if (!*args[cur_arg + 1]) {
1198 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1199 file, linenum, args[0]);
1200 return -1;
1201 }
1202 cur_arg++;
1203 code = atol(args[cur_arg]);
1204 if (code < 301 || code > 303) {
1205 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1206 file, linenum, args[0], code);
1207 return -1;
1208 }
1209 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001210 else if (!strcmp(args[cur_arg],"drop-query")) {
1211 flags |= REDIRECT_FLAG_DROP_QS;
1212 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001213 else if (!strcmp(args[cur_arg], "if")) {
1214 pol = ACL_COND_IF;
1215 cur_arg++;
1216 break;
1217 }
1218 else if (!strcmp(args[cur_arg], "unless")) {
1219 pol = ACL_COND_UNLESS;
1220 cur_arg++;
1221 break;
1222 }
1223 else {
1224 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1225 file, linenum, args[0], args[cur_arg]);
1226 return -1;
1227 }
1228 cur_arg++;
1229 }
1230
1231 if (type == REDIRECT_TYPE_NONE) {
1232 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1233 file, linenum, args[0]);
1234 return -1;
1235 }
1236
1237 if (pol == ACL_COND_NONE) {
1238 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1239 file, linenum, args[0]);
1240 return -1;
1241 }
1242
1243 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1244 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1245 file, linenum, args[0]);
1246 return -1;
1247 }
1248
Willy Tarreaua9802632008-07-25 19:13:19 +02001249 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001250 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1251 rule->cond = cond;
1252 rule->rdr_str = strdup(destination);
1253 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001254 if (cookie) {
1255 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1256 * a clear consists in appending "; Max-Age=0" at the end.
1257 */
1258 rule->cookie_len = strlen(cookie);
1259 if (cookie_set)
1260 rule->cookie_str = strdup(cookie);
1261 else {
1262 rule->cookie_str = malloc(rule->cookie_len + 12);
1263 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1264 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1265 rule->cookie_len += 11;
1266 }
1267 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001268 rule->type = type;
1269 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001270 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001271 LIST_INIT(&rule->list);
1272 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1273 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001274 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1275 int pol = ACL_COND_NONE;
1276 struct acl_cond *cond;
1277 struct switching_rule *rule;
1278
Willy Tarreaub099aca2008-10-12 17:26:37 +02001279 if (curproxy == &defproxy) {
1280 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1281 return -1;
1282 }
1283
Willy Tarreau55ea7572007-06-17 19:56:27 +02001284 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1285 return 0;
1286
1287 if (*(args[1]) == 0) {
1288 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1289 return -1;
1290 }
1291
1292 if (!strcmp(args[2], "if"))
1293 pol = ACL_COND_IF;
1294 else if (!strcmp(args[2], "unless"))
1295 pol = ACL_COND_UNLESS;
1296
1297 if (pol == ACL_COND_NONE) {
1298 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1299 file, linenum, args[0]);
1300 return -1;
1301 }
1302
1303 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001304 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001305 file, linenum);
1306 return -1;
1307 }
1308
Willy Tarreaua9802632008-07-25 19:13:19 +02001309 cond->line = linenum;
1310 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001311 struct acl *acl;
1312 const char *name;
1313
1314 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1315 name = acl ? acl->name : "(unknown)";
1316 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1317 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001318 }
1319
Willy Tarreau55ea7572007-06-17 19:56:27 +02001320 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1321 rule->cond = cond;
1322 rule->be.name = strdup(args[1]);
1323 LIST_INIT(&rule->list);
1324 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1325 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001327 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1328 return 0;
1329
Willy Tarreaubaaee002006-06-26 02:48:02 +02001330 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1331 curproxy->uri_auth = NULL; /* we must detach from the default config */
1332
1333 if (*(args[1]) == 0) {
1334 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1335 return -1;
1336 } else if (!strcmp(args[1], "uri")) {
1337 if (*(args[2]) == 0) {
1338 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1339 return -1;
1340 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1341 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1342 return -1;
1343 }
1344 } else if (!strcmp(args[1], "realm")) {
1345 if (*(args[2]) == 0) {
1346 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1347 return -1;
1348 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1349 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1350 return -1;
1351 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001352 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001353 unsigned interval;
1354
1355 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1356 if (err) {
1357 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1358 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001359 return -1;
1360 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1361 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1362 return -1;
1363 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001364 } else if (!strcmp(args[1], "auth")) {
1365 if (*(args[2]) == 0) {
1366 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1367 return -1;
1368 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1369 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1370 return -1;
1371 }
1372 } else if (!strcmp(args[1], "scope")) {
1373 if (*(args[2]) == 0) {
1374 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1375 return -1;
1376 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1377 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1378 return -1;
1379 }
1380 } else if (!strcmp(args[1], "enable")) {
1381 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1382 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1383 return -1;
1384 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001385 } else if (!strcmp(args[1], "hide-version")) {
1386 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1387 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1388 return -1;
1389 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001391 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 file, linenum, args[0]);
1393 return -1;
1394 }
1395 }
1396 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001397 int optnum;
1398
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001399 if (*(args[1]) == '\0') {
1400 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1401 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402 return -1;
1403 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001404
1405 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1406 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1407 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1408 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001409
1410 if (!inv)
1411 curproxy->options |= cfg_opts[optnum].val;
1412 else
1413 curproxy->options &= ~cfg_opts[optnum].val;
1414
Willy Tarreau13943ab2006-12-31 00:24:10 +01001415 return 0;
1416 }
1417 }
1418
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001419 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1420 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
1421 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
1422 return 0;
1423
1424 if (!inv)
1425 curproxy->options2 |= cfg_opts2[optnum].val;
1426 else
1427 curproxy->options2 &= ~cfg_opts2[optnum].val;
1428
1429 return 0;
1430 }
1431 }
1432
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001433 if (inv) {
1434 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1435 file, linenum, args[1]);
1436 return -1;
1437 }
1438
Willy Tarreau13943ab2006-12-31 00:24:10 +01001439 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001440 /* generate a complete HTTP log */
1441 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1442 else if (!strcmp(args[1], "tcplog"))
1443 /* generate a detailed TCP log */
1444 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445 else if (!strcmp(args[1], "tcpka")) {
1446 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001447 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1448 return 0;
1449
1450 if (curproxy->cap & PR_CAP_FE)
1451 curproxy->options |= PR_O_TCP_CLI_KA;
1452 if (curproxy->cap & PR_CAP_BE)
1453 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 }
1455 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001456 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1457 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001458 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001459 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001460 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001461 curproxy->options &= ~PR_O_SMTP_CHK;
1462 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463 if (!*args[2]) { /* no argument */
1464 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1465 curproxy->check_len = strlen(DEF_CHECK_REQ);
1466 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001467 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468 curproxy->check_req = (char *)malloc(reqlen);
1469 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1470 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1471 } else { /* more arguments : METHOD URI [HTTP_VER] */
1472 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1473 if (*args[4])
1474 reqlen += strlen(args[4]);
1475 else
1476 reqlen += strlen("HTTP/1.0");
1477
1478 curproxy->check_req = (char *)malloc(reqlen);
1479 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1480 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1481 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001482 }
1483 else if (!strcmp(args[1], "ssl-hello-chk")) {
1484 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001485 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1486 return 0;
1487
Willy Tarreaua534fea2008-08-03 12:19:50 +02001488 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001489 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001490 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001491 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492 }
Willy Tarreau23677902007-05-08 23:50:35 +02001493 else if (!strcmp(args[1], "smtpchk")) {
1494 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001495 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001496 curproxy->options &= ~PR_O_HTTP_CHK;
1497 curproxy->options &= ~PR_O_SSL3_CHK;
1498 curproxy->options |= PR_O_SMTP_CHK;
1499
1500 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1501 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1502 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1503 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1504 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1505 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1506 curproxy->check_req = (char *)malloc(reqlen);
1507 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1508 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1509 } else {
1510 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1511 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1512 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1513 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1514 }
1515 }
1516 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001517 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001518 int cur_arg;
1519
1520 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1521 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001522 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001523
1524 curproxy->options |= PR_O_FWDFOR;
1525
1526 free(curproxy->fwdfor_hdr_name);
1527 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1528 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1529
1530 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1531 cur_arg = 2;
1532 while (*(args[cur_arg])) {
1533 if (!strcmp(args[cur_arg], "except")) {
1534 /* suboption except - needs additional argument for it */
1535 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1536 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1537 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001538 return -1;
1539 }
1540 /* flush useless bits */
1541 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001542 cur_arg += 2;
1543 } else if (!strcmp(args[cur_arg], "header")) {
1544 /* suboption header - needs additional argument for it */
1545 if (*(args[cur_arg+1]) == 0) {
1546 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1547 file, linenum, args[0], args[1], args[cur_arg]);
1548 return -1;
1549 }
1550 free(curproxy->fwdfor_hdr_name);
1551 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1552 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1553 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001554 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001555 /* unknown suboption - catchall */
1556 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1557 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001558 return -1;
1559 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001560 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001561 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562 else {
1563 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1564 return -1;
1565 }
1566 return 0;
1567 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001568 else if (!strcmp(args[0], "default_backend")) {
1569 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1570 return 0;
1571
1572 if (*(args[1]) == 0) {
1573 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1574 return -1;
1575 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001576 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001577 curproxy->defbe.name = strdup(args[1]);
1578 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001580 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1581 return 0;
1582
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001583 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1584 file, linenum, args[0]);
1585
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 /* enable reconnections to dispatch */
1587 curproxy->options |= PR_O_REDISP;
1588 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001589 else if (!strcmp(args[0], "http-check")) {
1590 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1591 return 0;
1592
1593 if (strcmp(args[1], "disable-on-404") == 0) {
1594 /* enable a graceful server shutdown on an HTTP 404 response */
1595 curproxy->options |= PR_O_DISABLE404;
1596 }
1597 else {
1598 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1599 return -1;
1600 }
1601 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001602 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001603 if (curproxy == &defproxy) {
1604 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1605 return -1;
1606 }
1607
Willy Tarreaub80c2302007-11-30 20:51:32 +01001608 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1609 return 0;
1610
1611 if (strcmp(args[1], "fail") == 0) {
1612 /* add a condition to fail monitor requests */
1613 int pol = ACL_COND_NONE;
1614 struct acl_cond *cond;
1615
1616 if (!strcmp(args[2], "if"))
1617 pol = ACL_COND_IF;
1618 else if (!strcmp(args[2], "unless"))
1619 pol = ACL_COND_UNLESS;
1620
1621 if (pol == ACL_COND_NONE) {
1622 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1623 file, linenum, args[0], args[1]);
1624 return -1;
1625 }
1626
1627 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1628 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1629 file, linenum, args[0], args[1]);
1630 return -1;
1631 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001632 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001633 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1634 }
1635 else {
1636 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1637 return -1;
1638 }
1639 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640#ifdef TPROXY
1641 else if (!strcmp(args[0], "transparent")) {
1642 /* enable transparent proxy connections */
1643 curproxy->options |= PR_O_TRANSP;
1644 }
1645#endif
1646 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001647 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1648 return 0;
1649
Willy Tarreaubaaee002006-06-26 02:48:02 +02001650 if (*(args[1]) == 0) {
1651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1652 return -1;
1653 }
1654 curproxy->maxconn = atol(args[1]);
1655 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001656 else if (!strcmp(args[0], "backlog")) { /* backlog */
1657 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1658 return 0;
1659
1660 if (*(args[1]) == 0) {
1661 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1662 return -1;
1663 }
1664 curproxy->backlog = atol(args[1]);
1665 }
Willy Tarreau86034312006-12-29 00:10:33 +01001666 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001667 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1668 return 0;
1669
Willy Tarreau86034312006-12-29 00:10:33 +01001670 if (*(args[1]) == 0) {
1671 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1672 return -1;
1673 }
1674 curproxy->fullconn = atol(args[1]);
1675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1677 if (*(args[1]) == 0) {
1678 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1679 return -1;
1680 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001681 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1682 if (err) {
1683 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1684 file, linenum, *err);
1685 return -1;
1686 }
1687 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688 }
1689 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1690 if (curproxy == &defproxy) {
1691 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1692 return -1;
1693 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001694 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1695 return 0;
1696
Willy Tarreaubaaee002006-06-26 02:48:02 +02001697 if (strchr(args[1], ':') == NULL) {
1698 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1699 return -1;
1700 }
1701 curproxy->dispatch_addr = *str2sa(args[1]);
1702 }
1703 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001704 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1705 return 0;
1706
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02001707 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001708 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1709 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1710 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001711 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 }
1713 else if (!strcmp(args[0], "server")) { /* server address */
1714 int cur_arg;
1715 char *rport;
1716 char *raddr;
1717 short realport;
1718 int do_check;
1719
1720 if (curproxy == &defproxy) {
1721 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1722 return -1;
1723 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001724 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1725 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001726
1727 if (!*args[2]) {
1728 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1729 file, linenum, args[0]);
1730 return -1;
1731 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001732
1733 err = invalid_char(args[1]);
1734 if (err) {
1735 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1736 file, linenum, *err, args[1]);
1737 return -1;
1738 }
1739
Willy Tarreaubaaee002006-06-26 02:48:02 +02001740 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1741 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1742 return -1;
1743 }
1744
1745 /* the servers are linked backwards first */
1746 newsrv->next = curproxy->srv;
1747 curproxy->srv = newsrv;
1748 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001749 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001750
1751 LIST_INIT(&newsrv->pendconns);
1752 do_check = 0;
1753 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001754 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001755 newsrv->id = strdup(args[1]);
1756
1757 /* several ways to check the port component :
1758 * - IP => port=+0, relative
1759 * - IP: => port=+0, relative
1760 * - IP:N => port=N, absolute
1761 * - IP:+N => port=+N, relative
1762 * - IP:-N => port=-N, relative
1763 */
1764 raddr = strdup(args[2]);
1765 rport = strchr(raddr, ':');
1766 if (rport) {
1767 *rport++ = 0;
1768 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001769 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770 newsrv->state |= SRV_MAPPORTS;
1771 } else {
1772 realport = 0;
1773 newsrv->state |= SRV_MAPPORTS;
1774 }
1775
1776 newsrv->addr = *str2sa(raddr);
1777 newsrv->addr.sin_port = htons(realport);
1778 free(raddr);
1779
1780 newsrv->curfd = -1; /* no health-check in progress */
1781 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001782 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1783 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001784 newsrv->rise = DEF_RISETIME;
1785 newsrv->fall = DEF_FALLTIME;
1786 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001787 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001788 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001789 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001790
Willy Tarreaubaaee002006-06-26 02:48:02 +02001791 cur_arg = 3;
1792 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001793 if (!strcmp(args[cur_arg], "id")) {
1794 struct server *target;
1795
1796 if (!*args[cur_arg + 1]) {
1797 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1798 file, linenum, args[cur_arg]);
1799 return -1;
1800 }
1801
1802 newsrv->puid = atol(args[cur_arg + 1]);
1803
1804 if (newsrv->puid< 1001) {
1805 Alert("parsing [%s:%d]: custom id has to be > 1000",
1806 file, linenum);
1807 return -1;
1808 }
1809
1810 for (target = proxy->srv; target; target = target->next)
1811 if (newsrv != target && newsrv->puid == target->puid) {
1812 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1813 file, linenum, newsrv->id, target->id);
1814 return -1;
1815 }
1816 cur_arg += 2;
1817 }
1818 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001819 newsrv->cookie = strdup(args[cur_arg + 1]);
1820 newsrv->cklen = strlen(args[cur_arg + 1]);
1821 cur_arg += 2;
1822 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001823 else if (!strcmp(args[cur_arg], "redir")) {
1824 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1825 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1826 cur_arg += 2;
1827 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001828 else if (!strcmp(args[cur_arg], "rise")) {
1829 newsrv->rise = atol(args[cur_arg + 1]);
1830 newsrv->health = newsrv->rise;
1831 cur_arg += 2;
1832 }
1833 else if (!strcmp(args[cur_arg], "fall")) {
1834 newsrv->fall = atol(args[cur_arg + 1]);
1835 cur_arg += 2;
1836 }
1837 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001838 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1839 if (err) {
1840 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1841 file, linenum, *err, newsrv->id);
1842 return -1;
1843 }
1844 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001845 cur_arg += 2;
1846 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001847 else if (!strcmp(args[cur_arg], "fastinter")) {
1848 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1849 if (err) {
1850 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1851 file, linenum, *err, newsrv->id);
1852 return -1;
1853 }
1854 newsrv->fastinter = val;
1855 cur_arg += 2;
1856 }
1857 else if (!strcmp(args[cur_arg], "downinter")) {
1858 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1859 if (err) {
1860 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1861 file, linenum, *err, newsrv->id);
1862 return -1;
1863 }
1864 newsrv->downinter = val;
1865 cur_arg += 2;
1866 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001867 else if (!strcmp(args[cur_arg], "addr")) {
1868 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001869 cur_arg += 2;
1870 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 else if (!strcmp(args[cur_arg], "port")) {
1872 newsrv->check_port = atol(args[cur_arg + 1]);
1873 cur_arg += 2;
1874 }
1875 else if (!strcmp(args[cur_arg], "backup")) {
1876 newsrv->state |= SRV_BACKUP;
1877 cur_arg ++;
1878 }
1879 else if (!strcmp(args[cur_arg], "weight")) {
1880 int w;
1881 w = atol(args[cur_arg + 1]);
1882 if (w < 1 || w > 256) {
1883 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1884 file, linenum, newsrv->id, w);
1885 return -1;
1886 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001887 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001888 cur_arg += 2;
1889 }
1890 else if (!strcmp(args[cur_arg], "minconn")) {
1891 newsrv->minconn = atol(args[cur_arg + 1]);
1892 cur_arg += 2;
1893 }
1894 else if (!strcmp(args[cur_arg], "maxconn")) {
1895 newsrv->maxconn = atol(args[cur_arg + 1]);
1896 cur_arg += 2;
1897 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001898 else if (!strcmp(args[cur_arg], "maxqueue")) {
1899 newsrv->maxqueue = atol(args[cur_arg + 1]);
1900 cur_arg += 2;
1901 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001902 else if (!strcmp(args[cur_arg], "slowstart")) {
1903 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001904 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001905 if (err) {
1906 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1907 file, linenum, *err, newsrv->id);
1908 return -1;
1909 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001910 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001911 cur_arg += 2;
1912 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001913 else if (!strcmp(args[cur_arg], "track")) {
1914
1915 if (!*args[cur_arg + 1]) {
1916 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1917 file, linenum);
1918 return -1;
1919 }
1920
1921 newsrv->trackit = strdup(args[cur_arg + 1]);
1922
1923 cur_arg += 2;
1924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 else if (!strcmp(args[cur_arg], "check")) {
1926 global.maxsock++;
1927 do_check = 1;
1928 cur_arg += 1;
1929 }
1930 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1931 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001932#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001933 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1934 file, linenum, "source", "usesrc");
1935#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1937 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001938#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939 return -1;
1940 }
1941 newsrv->state |= SRV_BIND_SRC;
1942 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1943 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001944 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001945#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1946#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001947 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001948 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1949 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001950 return -1;
1951 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001952#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001953 if (!*args[cur_arg + 1]) {
1954 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1955 file, linenum, "usesrc");
1956 return -1;
1957 }
1958 if (!strcmp(args[cur_arg + 1], "client")) {
1959 newsrv->state |= SRV_TPROXY_CLI;
1960 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1961 newsrv->state |= SRV_TPROXY_CIP;
1962 } else {
1963 newsrv->state |= SRV_TPROXY_ADDR;
1964 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1965 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001966 global.last_checks |= LSTCHK_NETADM;
1967#if !defined(CONFIG_HAP_LINUX_TPROXY)
1968 global.last_checks |= LSTCHK_CTTPROXY;
1969#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001970 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001971#else /* no TPROXY support */
1972 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001973 file, linenum, "usesrc");
1974 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001975#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001977 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001978 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1979 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1980 file, linenum, "usesrc", "source");
1981 return -1;
1982 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001984 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 +02001985 file, linenum, newsrv->id);
1986 return -1;
1987 }
1988 }
1989
1990 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001991 if (newsrv->trackit) {
1992 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
1993 file, linenum);
1994 return -1;
1995 }
1996
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001997 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1998 newsrv->check_port = newsrv->check_addr.sin_port;
1999
Willy Tarreaubaaee002006-06-26 02:48:02 +02002000 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2001 newsrv->check_port = realport; /* by default */
2002 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002003 /* not yet valid, because no port was set on
2004 * the server either. We'll check if we have
2005 * a known port on the first listener.
2006 */
2007 struct listener *l;
2008 l = curproxy->listen;
2009 if (l) {
2010 int port;
2011 port = (l->addr.ss_family == AF_INET6)
2012 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2013 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2014 newsrv->check_port = port;
2015 }
2016 }
2017 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002018 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2019 file, linenum, newsrv->id);
2020 return -1;
2021 }
2022 newsrv->state |= SRV_CHECKED;
2023 }
2024
2025 if (newsrv->state & SRV_BACKUP)
2026 curproxy->srv_bck++;
2027 else
2028 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002029
2030 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 }
2032 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002033 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002034 int facility;
2035
2036 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2037 curproxy->logfac1 = global.logfac1;
2038 curproxy->logsrv1 = global.logsrv1;
2039 curproxy->loglev1 = global.loglev1;
2040 curproxy->logfac2 = global.logfac2;
2041 curproxy->logsrv2 = global.logsrv2;
2042 curproxy->loglev2 = global.loglev2;
2043 }
2044 else if (*(args[1]) && *(args[2])) {
2045 int level;
2046
2047 facility = get_log_facility(args[2]);
2048 if (facility < 0) {
2049 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2050 exit(1);
2051 }
2052
2053 level = 7; /* max syslog level = debug */
2054 if (*(args[3])) {
2055 level = get_log_level(args[3]);
2056 if (level < 0) {
2057 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2058 exit(1);
2059 }
2060 }
2061
Robert Tsai81ae1952007-12-05 10:47:29 +01002062 if (args[1][0] == '/') {
2063 logsrv.u.addr.sa_family = AF_UNIX;
2064 logsrv.u.un = *str2sun(args[1]);
2065 } else {
2066 logsrv.u.addr.sa_family = AF_INET;
2067 logsrv.u.in = *str2sa(args[1]);
2068 if (!logsrv.u.in.sin_port) {
2069 logsrv.u.in.sin_port =
2070 htons(SYSLOG_PORT);
2071 }
2072 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002073
2074 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002075 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002076 curproxy->logfac1 = facility;
2077 curproxy->loglev1 = level;
2078 }
2079 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002080 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081 curproxy->logfac2 = facility;
2082 curproxy->loglev2 = level;
2083 }
2084 else {
2085 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2086 return -1;
2087 }
2088 }
2089 else {
2090 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2091 file, linenum);
2092 return -1;
2093 }
2094 }
2095 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002096 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2097 return 0;
2098
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002100#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002101 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2102 file, linenum, "source", "usesrc");
2103#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2105 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002106#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002107 return -1;
2108 }
2109
2110 curproxy->source_addr = *str2sa(args[1]);
2111 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01002112 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002113#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2114#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002115 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2116 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2117 file, linenum, "usesrc");
2118 return -1;
2119 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002120#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002121 if (!*args[3]) {
2122 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2123 file, linenum, "usesrc");
2124 return -1;
2125 }
2126
2127 if (!strcmp(args[3], "client")) {
2128 curproxy->options |= PR_O_TPXY_CLI;
2129 } else if (!strcmp(args[3], "clientip")) {
2130 curproxy->options |= PR_O_TPXY_CIP;
2131 } else {
2132 curproxy->options |= PR_O_TPXY_ADDR;
2133 curproxy->tproxy_addr = *str2sa(args[3]);
2134 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002135 global.last_checks |= LSTCHK_NETADM;
2136#if !defined(CONFIG_HAP_LINUX_TPROXY)
2137 global.last_checks |= LSTCHK_CTTPROXY;
2138#endif
2139#else /* no TPROXY support */
2140 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002141 file, linenum, "usesrc");
2142 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002143#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002144 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002145 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002146 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2147 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2148 file, linenum, "usesrc", "source");
2149 return -1;
2150 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002151 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2152 regex_t *preg;
2153 if (curproxy == &defproxy) {
2154 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2155 return -1;
2156 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002157 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2158 return 0;
2159
Willy Tarreaubaaee002006-06-26 02:48:02 +02002160 if (*(args[1]) == 0 || *(args[2]) == 0) {
2161 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2162 file, linenum, args[0]);
2163 return -1;
2164 }
2165
2166 preg = calloc(1, sizeof(regex_t));
2167 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2168 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2169 return -1;
2170 }
2171
2172 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2173 if (err) {
2174 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2175 file, linenum, *err);
2176 return -1;
2177 }
2178 }
2179 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2180 regex_t *preg;
2181 if (curproxy == &defproxy) {
2182 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2183 return -1;
2184 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002185 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2186 return 0;
2187
Willy Tarreaubaaee002006-06-26 02:48:02 +02002188 if (*(args[1]) == 0) {
2189 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2190 return -1;
2191 }
2192
2193 preg = calloc(1, sizeof(regex_t));
2194 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2195 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2196 return -1;
2197 }
2198
2199 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2200 }
2201 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2202 regex_t *preg;
2203 if (curproxy == &defproxy) {
2204 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2205 return -1;
2206 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002207 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2208 return 0;
2209
Willy Tarreaubaaee002006-06-26 02:48:02 +02002210 if (*(args[1]) == 0) {
2211 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2212 return -1;
2213 }
2214
2215 preg = calloc(1, sizeof(regex_t));
2216 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2217 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2218 return -1;
2219 }
2220
2221 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2222 }
2223 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2224 regex_t *preg;
2225 if (curproxy == &defproxy) {
2226 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2227 return -1;
2228 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002229 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2230 return 0;
2231
Willy Tarreaubaaee002006-06-26 02:48:02 +02002232 if (*(args[1]) == 0) {
2233 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2234 return -1;
2235 }
2236
2237 preg = calloc(1, sizeof(regex_t));
2238 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2239 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2240 return -1;
2241 }
2242
2243 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2244 }
2245 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2246 regex_t *preg;
2247 if (curproxy == &defproxy) {
2248 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2249 return -1;
2250 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002251 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2252 return 0;
2253
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254 if (*(args[1]) == 0) {
2255 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2256 return -1;
2257 }
2258
2259 preg = calloc(1, sizeof(regex_t));
2260 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2261 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2262 return -1;
2263 }
2264
2265 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2266 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002267 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2268 regex_t *preg;
2269 if (curproxy == &defproxy) {
2270 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2271 return -1;
2272 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002273 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2274 return 0;
2275
Willy Tarreaub8750a82006-09-03 09:56:00 +02002276 if (*(args[1]) == 0) {
2277 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2278 return -1;
2279 }
2280
2281 preg = calloc(1, sizeof(regex_t));
2282 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2283 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2284 return -1;
2285 }
2286
2287 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2288 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002289 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2290 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002291 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002292 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2293 return -1;
2294 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002295 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2296 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002297
Willy Tarreau977b8e42006-12-29 14:19:17 +01002298 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002299 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2300 file, linenum, args[0]);
2301 return -1;
2302 }
2303
2304 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002305 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002306 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2307 }
2308
2309 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2310 }
2311 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2312 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002313 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002314 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2315 return -1;
2316 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002317 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2318 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002319
Willy Tarreau977b8e42006-12-29 14:19:17 +01002320 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002321 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2322 file, linenum, args[0]);
2323 return -1;
2324 }
2325
2326 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002327 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002328 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2329 }
2330
2331 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2332 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2334 regex_t *preg;
2335 if (curproxy == &defproxy) {
2336 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2337 return -1;
2338 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002339 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2340 return 0;
2341
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 if (*(args[1]) == 0 || *(args[2]) == 0) {
2343 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2344 file, linenum, args[0]);
2345 return -1;
2346 }
2347
2348 preg = calloc(1, sizeof(regex_t));
2349 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2350 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2351 return -1;
2352 }
2353
2354 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2355 if (err) {
2356 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2357 file, linenum, *err);
2358 return -1;
2359 }
2360 }
2361 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2362 regex_t *preg;
2363 if (curproxy == &defproxy) {
2364 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2365 return -1;
2366 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002367 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2368 return 0;
2369
Willy Tarreaubaaee002006-06-26 02:48:02 +02002370 if (*(args[1]) == 0) {
2371 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2372 return -1;
2373 }
2374
2375 preg = calloc(1, sizeof(regex_t));
2376 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2377 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2378 return -1;
2379 }
2380
2381 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2382 }
2383 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2384 regex_t *preg;
2385 if (curproxy == &defproxy) {
2386 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2387 return -1;
2388 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002389 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2390 return 0;
2391
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 if (*(args[1]) == 0) {
2393 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2394 return -1;
2395 }
2396
2397 preg = calloc(1, sizeof(regex_t));
2398 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2399 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2400 return -1;
2401 }
2402
2403 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2404 }
2405 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2406 regex_t *preg;
2407 if (curproxy == &defproxy) {
2408 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2409 return -1;
2410 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002411 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2412 return 0;
2413
Willy Tarreaubaaee002006-06-26 02:48:02 +02002414 if (*(args[1]) == 0) {
2415 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2416 return -1;
2417 }
2418
2419 preg = calloc(1, sizeof(regex_t));
2420 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2421 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2422 return -1;
2423 }
2424
2425 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2426 }
2427 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2428 regex_t *preg;
2429 if (curproxy == &defproxy) {
2430 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2431 return -1;
2432 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002433 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2434 return 0;
2435
Willy Tarreaubaaee002006-06-26 02:48:02 +02002436 if (*(args[1]) == 0) {
2437 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2438 return -1;
2439 }
2440
2441 preg = calloc(1, sizeof(regex_t));
2442 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2443 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2444 return -1;
2445 }
2446
2447 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2448 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002449 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2450 regex_t *preg;
2451 if (curproxy == &defproxy) {
2452 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2453 return -1;
2454 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002455 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2456 return 0;
2457
Willy Tarreaub8750a82006-09-03 09:56:00 +02002458 if (*(args[1]) == 0) {
2459 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2460 return -1;
2461 }
2462
2463 preg = calloc(1, sizeof(regex_t));
2464 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2465 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2466 return -1;
2467 }
2468
2469 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2470 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2472 if (curproxy == &defproxy) {
2473 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2474 return -1;
2475 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002476 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2477 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478
2479 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2480 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2481 return 0;
2482 }
2483
2484 if (*(args[1]) == 0) {
2485 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2486 return -1;
2487 }
2488
2489 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2490 }
2491 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2492 regex_t *preg;
2493
2494 if (*(args[1]) == 0 || *(args[2]) == 0) {
2495 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2496 file, linenum, args[0]);
2497 return -1;
2498 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002499 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2500 return 0;
2501
Willy Tarreaubaaee002006-06-26 02:48:02 +02002502 preg = calloc(1, sizeof(regex_t));
2503 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2504 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2505 return -1;
2506 }
2507
2508 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2509 if (err) {
2510 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2511 file, linenum, *err);
2512 return -1;
2513 }
2514 }
2515 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2516 regex_t *preg;
2517 if (curproxy == &defproxy) {
2518 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2519 return -1;
2520 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002521 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2522 return 0;
2523
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 if (*(args[1]) == 0) {
2525 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2526 return -1;
2527 }
2528
2529 preg = calloc(1, sizeof(regex_t));
2530 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2531 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2532 return -1;
2533 }
2534
2535 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2536 if (err) {
2537 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2538 file, linenum, *err);
2539 return -1;
2540 }
2541 }
2542 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2543 regex_t *preg;
2544 if (curproxy == &defproxy) {
2545 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2546 return -1;
2547 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002548 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2549 return 0;
2550
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 if (*(args[1]) == 0) {
2552 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2553 return -1;
2554 }
2555
2556 preg = calloc(1, sizeof(regex_t));
2557 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2558 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2559 return -1;
2560 }
2561
2562 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2563 if (err) {
2564 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2565 file, linenum, *err);
2566 return -1;
2567 }
2568 }
2569 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2570 regex_t *preg;
2571 if (curproxy == &defproxy) {
2572 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2573 return -1;
2574 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002575 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2576 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577
2578 if (*(args[1]) == 0 || *(args[2]) == 0) {
2579 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2580 file, linenum, args[0]);
2581 return -1;
2582 }
2583
2584 preg = calloc(1, sizeof(regex_t));
2585 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2586 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2587 return -1;
2588 }
2589
2590 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2591 if (err) {
2592 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2593 file, linenum, *err);
2594 return -1;
2595 }
2596 }
2597 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2598 regex_t *preg;
2599 if (curproxy == &defproxy) {
2600 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2601 return -1;
2602 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002603 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2604 return 0;
2605
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 if (*(args[1]) == 0) {
2607 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2608 return -1;
2609 }
2610
2611 preg = calloc(1, sizeof(regex_t));
2612 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2613 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2614 return -1;
2615 }
2616
2617 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2618 if (err) {
2619 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2620 file, linenum, *err);
2621 return -1;
2622 }
2623 }
2624 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2625 regex_t *preg;
2626 if (curproxy == &defproxy) {
2627 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2628 return -1;
2629 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002630 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2631 return 0;
2632
Willy Tarreaubaaee002006-06-26 02:48:02 +02002633 if (*(args[1]) == 0) {
2634 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2635 return -1;
2636 }
2637
2638 preg = calloc(1, sizeof(regex_t));
2639 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2640 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2641 return -1;
2642 }
2643
2644 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2645 if (err) {
2646 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2647 file, linenum, *err);
2648 return -1;
2649 }
2650 }
2651 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2652 if (curproxy == &defproxy) {
2653 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2654 return -1;
2655 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002656 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2657 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002658
2659 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2660 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2661 return 0;
2662 }
2663
2664 if (*(args[1]) == 0) {
2665 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2666 return -1;
2667 }
2668
2669 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2670 }
2671 else if (!strcmp(args[0], "errorloc") ||
2672 !strcmp(args[0], "errorloc302") ||
2673 !strcmp(args[0], "errorloc303")) { /* error location */
2674 int errnum, errlen;
2675 char *err;
2676
Willy Tarreau977b8e42006-12-29 14:19:17 +01002677 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2678 return 0;
2679
Willy Tarreaubaaee002006-06-26 02:48:02 +02002680 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002681 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682 return -1;
2683 }
2684
2685 errnum = atol(args[1]);
2686 if (!strcmp(args[0], "errorloc303")) {
2687 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2688 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2689 } else {
2690 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2691 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2692 }
2693
Willy Tarreau0f772532006-12-23 20:51:41 +01002694 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2695 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002696 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002697 curproxy->errmsg[rc].str = err;
2698 curproxy->errmsg[rc].len = errlen;
2699 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002701 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002702
2703 if (rc >= HTTP_ERR_SIZE) {
2704 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2705 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002706 free(err);
2707 }
2708 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002709 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2710 int errnum, errlen, fd;
2711 char *err;
2712 struct stat stat;
2713
2714 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2715 return 0;
2716
2717 if (*(args[2]) == 0) {
2718 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2719 return -1;
2720 }
2721
2722 fd = open(args[2], O_RDONLY);
2723 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2724 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2725 file, linenum, args[2], args[1]);
2726 if (fd >= 0)
2727 close(fd);
2728 return -1;
2729 }
2730
2731 if (stat.st_size <= BUFSIZE) {
2732 errlen = stat.st_size;
2733 } else {
2734 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2735 file, linenum, args[2], BUFSIZE);
2736 errlen = BUFSIZE;
2737 }
2738
2739 err = malloc(errlen); /* malloc() must succeed during parsing */
2740 errnum = read(fd, err, errlen);
2741 if (errnum != errlen) {
2742 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2743 file, linenum, args[2], args[1]);
2744 close(fd);
2745 free(err);
2746 return -1;
2747 }
2748 close(fd);
2749
2750 errnum = atol(args[1]);
2751 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2752 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002753 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002754 curproxy->errmsg[rc].str = err;
2755 curproxy->errmsg[rc].len = errlen;
2756 break;
2757 }
2758 }
2759
2760 if (rc >= HTTP_ERR_SIZE) {
2761 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2762 file, linenum, errnum);
2763 free(err);
2764 }
2765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002766 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002767 struct cfg_kw_list *kwl;
2768 int index;
2769
2770 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2771 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2772 if (kwl->kw[index].section != CFG_LISTEN)
2773 continue;
2774 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2775 /* prepare error message just in case */
2776 snprintf(trash, sizeof(trash),
2777 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002778 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2779 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002780 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2781 return -1;
2782 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002783 else if (rc > 0) {
2784 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2785 return 0;
2786 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002787 return 0;
2788 }
2789 }
2790 }
2791
Willy Tarreau6daf3432008-01-22 16:44:08 +01002792 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002793 return -1;
2794 }
2795 return 0;
2796}
2797
2798
2799/*
2800 * This function reads and parses the configuration file given in the argument.
2801 * returns 0 if OK, -1 if error.
2802 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002803int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002805 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002806 FILE *f;
2807 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002809 int confsect = CFG_NONE;
2810
2811 struct proxy *curproxy = NULL;
2812 struct server *newsrv = NULL;
2813
2814 if ((f=fopen(file,"r")) == NULL)
2815 return -1;
2816
2817 init_default_instance();
2818
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002819 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002820 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002821 char *end;
2822 char *args[MAX_LINE_ARGS + 1];
2823 char *line = thisline;
2824
Willy Tarreaubaaee002006-06-26 02:48:02 +02002825 linenum++;
2826
2827 end = line + strlen(line);
2828
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002829 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2830 /* Check if we reached the limit and the last char is not \n.
2831 * Watch out for the last line without the terminating '\n'!
2832 */
2833 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2834 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002835 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002836 }
2837
Willy Tarreaubaaee002006-06-26 02:48:02 +02002838 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002839 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 line++;
2841
2842 arg = 0;
2843 args[arg] = line;
2844
2845 while (*line && arg < MAX_LINE_ARGS) {
2846 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2847 * C equivalent value. Other combinations left unchanged (eg: \1).
2848 */
2849 if (*line == '\\') {
2850 int skip = 0;
2851 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2852 *line = line[1];
2853 skip = 1;
2854 }
2855 else if (line[1] == 'r') {
2856 *line = '\r';
2857 skip = 1;
2858 }
2859 else if (line[1] == 'n') {
2860 *line = '\n';
2861 skip = 1;
2862 }
2863 else if (line[1] == 't') {
2864 *line = '\t';
2865 skip = 1;
2866 }
2867 else if (line[1] == 'x') {
2868 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2869 unsigned char hex1, hex2;
2870 hex1 = toupper(line[2]) - '0';
2871 hex2 = toupper(line[3]) - '0';
2872 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2873 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2874 *line = (hex1<<4) + hex2;
2875 skip = 3;
2876 }
2877 else {
2878 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002879 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002880 }
2881 }
2882 if (skip) {
2883 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2884 end -= skip;
2885 }
2886 line++;
2887 }
2888 else if (*line == '#' || *line == '\n' || *line == '\r') {
2889 /* end of string, end of loop */
2890 *line = 0;
2891 break;
2892 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002893 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002894 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002895 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002896 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 line++;
2898 args[++arg] = line;
2899 }
2900 else {
2901 line++;
2902 }
2903 }
2904
2905 /* empty line */
2906 if (!**args)
2907 continue;
2908
Willy Tarreau540abe42007-05-02 20:50:16 +02002909 /* zero out remaining args and ensure that at least one entry
2910 * is zeroed out.
2911 */
2912 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002913 args[arg] = line;
2914 }
2915
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002916 if (!strcmp(args[0], "no")) {
2917 inv = 1;
2918 for (arg=0; *args[arg+1]; arg++)
2919 args[arg] = args[arg+1]; // shift args after inversion
2920 }
2921
2922 if (inv && strcmp(args[0], "option")) {
2923 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002924 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002925 }
2926
Willy Tarreau977b8e42006-12-29 14:19:17 +01002927 if (!strcmp(args[0], "listen") ||
2928 !strcmp(args[0], "frontend") ||
2929 !strcmp(args[0], "backend") ||
2930 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002931 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002932 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002933 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002934 cursection = strdup(args[0]);
2935 }
2936 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002937 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002938 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002939 cursection = strdup(args[0]);
2940 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002941 /* else it's a section keyword */
2942
2943 switch (confsect) {
2944 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002945 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002946 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947 break;
2948 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002949 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002950 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002951 break;
2952 default:
2953 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002954 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002956 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002957 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002958 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002959 fclose(f);
2960
2961 /*
2962 * Now, check for the integrity of all that we have collected.
2963 */
2964
2965 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002966 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967
2968 if ((curproxy = proxy) == NULL) {
2969 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2970 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002971 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002972 }
2973
2974 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002975 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002976 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002977
Willy Tarreaubaaee002006-06-26 02:48:02 +02002978 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02002979 /* ensure we don't keep listeners uselessly bound */
2980 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002981 curproxy = curproxy->next;
2982 continue;
2983 }
2984
Willy Tarreau977b8e42006-12-29 14:19:17 +01002985 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2986 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 +01002987 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002988 cfgerr++;
2989 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002990 else if (curproxy->cap & PR_CAP_BE &&
2991 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002992 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002993 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002994 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2995 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 +01002996 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997 cfgerr++;
2998 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002999
Willy Tarreau31682232007-11-29 15:38:04 +01003000 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003001 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003002 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003003 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 cfgerr++;
3005 }
3006#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
3007 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003008 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003009 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 cfgerr++;
3011 }
3012#endif
3013 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003014 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003015 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016 }
3017 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003018
3019 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003020 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003021 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003022 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003024 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003025 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003026 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003027 }
3028 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003029 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003030 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003031 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003032 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003033 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003034 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003035 }
Willy Tarreaudf366142007-11-30 16:23:20 +01003036 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01003037 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3038 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003039
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01003040 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003041 file, proxy_type_str(curproxy), curproxy->id);
3042 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003044
3045 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
3046 if ((newsrv = curproxy->srv) != NULL) {
3047 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
3048 file, proxy_type_str(curproxy), curproxy->id);
3049 }
3050 }
3051
3052 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003053 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
3054 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
3055 file, curproxy->id);
3056 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003057 }
3058 }
3059
Willy Tarreau82936582007-11-30 15:20:09 +01003060 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3061 curproxy->options &= ~PR_O_DISABLE404;
3062 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3063 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
3064 }
3065
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003066 /* if a default backend was specified, let's find it */
3067 if (curproxy->defbe.name) {
3068 struct proxy *target;
3069
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003070 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3071 if (!target) {
3072 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3073 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003074 cfgerr++;
3075 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003076 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3077 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003078 } else {
3079 free(curproxy->defbe.name);
3080 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 }
3082 }
3083
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003084 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003085 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3086 /* map jump target for ACT_SETBE in req_rep chain */
3087 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003088 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003089 struct proxy *target;
3090
Willy Tarreaua496b602006-12-17 23:15:24 +01003091 if (exp->action != ACT_SETBE)
3092 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003093
3094 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3095 if (!target) {
3096 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3097 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003098 cfgerr++;
3099 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003100 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3101 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003102 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003103 } else {
3104 free((void *)exp->replace);
3105 exp->replace = (const char *)target;
3106 }
3107 }
3108 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003109
3110 /* find the target proxy for 'use_backend' rules */
3111 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003112 struct proxy *target;
3113
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003114 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003115
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003116 if (!target) {
3117 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3118 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003119 cfgerr++;
3120 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003121 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3122 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003123 cfgerr++;
3124 } else {
3125 free((void *)rule->be.name);
3126 rule->be.backend = target;
3127 }
3128 }
3129
Willy Tarreau2738a142006-07-08 17:28:09 +02003130 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003131 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003132 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003133 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003134 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003135 " | While not properly invalid, you will certainly encounter various problems\n"
3136 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003137 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003138 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003139 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003140
Willy Tarreau1fa31262007-12-03 00:36:16 +01003141 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3142 * We must still support older configurations, so let's find out whether those
3143 * parameters have been set or must be copied from contimeouts.
3144 */
3145 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003146 if (!curproxy->timeout.tarpit ||
3147 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003148 /* tarpit timeout not set. We search in the following order:
3149 * default.tarpit, curr.connect, default.connect.
3150 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003151 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003152 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003153 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003154 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003155 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003156 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003157 }
3158 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003159 (!curproxy->timeout.queue ||
3160 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003161 /* queue timeout not set. We search in the following order:
3162 * default.queue, curr.connect, default.connect.
3163 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003164 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003165 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003166 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003167 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003168 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003169 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003170 }
3171 }
3172
Willy Tarreauf3c69202006-07-09 16:42:34 +02003173 if (curproxy->options & PR_O_SSL3_CHK) {
3174 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3175 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3176 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3177 }
3178
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003179 /* The small pools required for the capture lists */
3180 if (curproxy->nb_req_cap)
3181 curproxy->req_cap_pool = create_pool("ptrcap",
3182 curproxy->nb_req_cap * sizeof(char *),
3183 MEM_F_SHARED);
3184 if (curproxy->nb_rsp_cap)
3185 curproxy->rsp_cap_pool = create_pool("ptrcap",
3186 curproxy->nb_rsp_cap * sizeof(char *),
3187 MEM_F_SHARED);
3188
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003189 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3190 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3191 MEM_F_SHARED);
3192
Willy Tarreau86034312006-12-29 00:10:33 +01003193 /* for backwards compatibility with "listen" instances, if
3194 * fullconn is not set but maxconn is set, then maxconn
3195 * is used.
3196 */
3197 if (!curproxy->fullconn)
3198 curproxy->fullconn = curproxy->maxconn;
3199
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 /* first, we will invert the servers list order */
3201 newsrv = NULL;
3202 while (curproxy->srv) {
3203 struct server *next;
3204
3205 next = curproxy->srv->next;
3206 curproxy->srv->next = newsrv;
3207 newsrv = curproxy->srv;
3208 if (!next)
3209 break;
3210 curproxy->srv = next;
3211 }
3212
Willy Tarreau20697042007-11-15 23:26:18 +01003213 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003214 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215
Willy Tarreaub625a082007-11-26 01:15:43 +01003216 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003217 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003218 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003219 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3220 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003221 else
3222 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003223
3224 if (curproxy->options & PR_O_LOGASAP)
3225 curproxy->to_log &= ~LW_BYTES;
3226
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003228 * ensure that we're not cross-dressing a TCP server into HTTP.
3229 */
3230 newsrv = curproxy->srv;
3231 while (newsrv != NULL) {
3232 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3233 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3234 file, proxy_type_str(curproxy), curproxy->id, linenum);
3235 goto err;
3236 }
3237 newsrv = newsrv->next;
3238 }
3239
3240 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 * If this server supports a maxconn parameter, it needs a dedicated
3242 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003243 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 */
3245 newsrv = curproxy->srv;
3246 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003247 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003248 /* Only 'minconn' was specified, or it was higher than or equal
3249 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3250 * this will avoid further useless expensive computations.
3251 */
3252 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003253 } else if (newsrv->maxconn && !newsrv->minconn) {
3254 /* minconn was not specified, so we set it to maxconn */
3255 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003256 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3257 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003258 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003259 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 }
3261
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003262 if (newsrv->trackit) {
3263 struct proxy *px;
3264 struct server *srv;
3265 char *pname, *sname;
3266
3267 pname = newsrv->trackit;
3268 sname = strrchr(pname, '/');
3269
3270 if (sname)
3271 *sname++ = '\0';
3272 else {
3273 sname = pname;
3274 pname = NULL;
3275 }
3276
3277 if (pname) {
3278 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3279 if (!px) {
3280 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3281 file, proxy_type_str(curproxy), curproxy->id,
3282 newsrv->id, pname);
3283 return -1;
3284 }
3285 } else
3286 px = curproxy;
3287
3288 srv = findserver(px, sname);
3289 if (!srv) {
3290 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3291 file, proxy_type_str(curproxy), curproxy->id,
3292 newsrv->id, sname);
3293 return -1;
3294 }
3295
3296 if (!(srv->state & SRV_CHECKED)) {
3297 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3298 "tracing as it does not have checks enabled.\n",
3299 file, proxy_type_str(curproxy), curproxy->id,
3300 newsrv->id, px->id, srv->id);
3301 return -1;
3302 }
3303
3304 if (curproxy != px &&
3305 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3306 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3307 "tracing: disable-on-404 option inconsistency.\n",
3308 file, proxy_type_str(curproxy), curproxy->id,
3309 newsrv->id, px->id, srv->id);
3310 return -1;
3311 }
3312
3313 newsrv->tracked = srv;
3314 newsrv->tracknext = srv->tracknext;
3315 srv->tracknext = newsrv;
3316
3317 free(newsrv->trackit);
3318 }
3319
Willy Tarreaubaaee002006-06-26 02:48:02 +02003320 newsrv = newsrv->next;
3321 }
3322
Willy Tarreaue6b98942007-10-29 01:09:36 +01003323 /* adjust this proxy's listeners */
3324 listener = curproxy->listen;
3325 while (listener) {
3326 if (curproxy->options & PR_O_TCP_NOLING)
3327 listener->options |= LI_O_NOLINGER;
3328 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003329 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003330 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003331 listener->accept = event_accept;
3332 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003333 listener->handler = process_session;
3334
3335 if (curproxy->mode == PR_MODE_HTTP)
3336 listener->analysers |= AN_REQ_HTTP_HDR;
3337
3338 if (curproxy->tcp_req.inspect_delay)
3339 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003340
3341 listener = listener->next;
3342 }
3343
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 curproxy = curproxy->next;
3345 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003346
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 if (cfgerr > 0) {
3348 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003349 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003351
3352 /*
3353 * Recount currently required checks.
3354 */
3355
3356 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3357 int optnum;
3358
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003359 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3360 if (curproxy->options & cfg_opts[optnum].val)
3361 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003362
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003363 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3364 if (curproxy->options2 & cfg_opts2[optnum].val)
3365 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003366 }
3367
Willy Tarreaua534fea2008-08-03 12:19:50 +02003368 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003369 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003370 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003371
3372 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003373 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003374 cursection = NULL;
3375 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003376}
3377
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003378/*
3379 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3380 * parsing sessions.
3381 */
3382void cfg_register_keywords(struct cfg_kw_list *kwl)
3383{
3384 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3385}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003387/*
3388 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3389 */
3390void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3391{
3392 LIST_DEL(&kwl->list);
3393 LIST_INIT(&kwl->list);
3394}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395
3396/*
3397 * Local variables:
3398 * c-indent-level: 8
3399 * c-basic-offset: 8
3400 * End:
3401 */