blob: 10f7b2accf3d9e60b9fd3dfb69e9649df68e5305 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau7c669d72008-06-20 15:04:11 +02004 * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
27#include <common/config.h>
28#include <common/memory.h>
29#include <common/standard.h>
30#include <common/time.h>
31#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020032
33#include <types/capture.h>
34#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreaueb0c6142007-05-07 00:53:22 +020036#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010038#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020040#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010041#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010043#include <proto/protocols.h>
44#include <proto/proto_tcp.h>
45#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010046#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010048#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <proto/task.h>
50
51
Willy Tarreauf3c69202006-07-09 16:42:34 +020052/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
53 * ssl-hello-chk option to ensure that the remote server speaks SSL.
54 *
55 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
56 */
57const char sslv3_client_hello_pkt[] = {
58 "\x16" /* ContentType : 0x16 = Hanshake */
59 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
60 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
61 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
62 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
63 "\x03\x00" /* Hello Version : 0x0300 = v3 */
64 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
65 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
66 "\x00" /* Session ID length : empty (no session ID) */
67 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
68 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
69 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
70 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
71 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
72 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
73 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
74 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
75 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
76 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
77 "\x00\x38" "\x00\x39" "\x00\x3A"
78 "\x01" /* Compression Length : 0x01 = 1 byte for types */
79 "\x00" /* Compression Type : 0x00 = NULL compression */
80};
81
Willy Tarreau13943ab2006-12-31 00:24:10 +010082/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010083struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010084 const char *name;
85 unsigned int val;
86 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010087 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +010088};
89
90/* proxy->options */
91static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +010092{
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010094 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010095 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010096 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010097 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
98 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
99 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
100 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
101 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
102 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
103 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
104 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100106 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
107 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100108#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100109 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
110#endif
111#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100112 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100113#endif
114
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116};
117
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100118/* proxy->options2 */
119static const struct cfg_opt cfg_opts2[] =
120{
121#ifdef CONFIG_HAP_LINUX_SPLICE
122 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
123 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
124 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
125#endif
126 { NULL, 0, 0, 0 }
127};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200128
Willy Tarreau6daf3432008-01-22 16:44:08 +0100129static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200130static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
131int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
132int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
133
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200134/* List head of all known configuration keywords */
135static struct cfg_kw_list cfg_keywords = {
136 .list = LIST_HEAD_INIT(cfg_keywords.list)
137};
138
Willy Tarreaubaaee002006-06-26 02:48:02 +0200139/*
140 * converts <str> to a list of listeners which are dynamically allocated.
141 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
142 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
143 * - <port> is a numerical port from 1 to 65535 ;
144 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
145 * This can be repeated as many times as necessary, separated by a coma.
146 * The <tail> argument is a pointer to a current list which should be appended
147 * to the tail of the new list. The pointer to the new list is returned.
148 */
149static struct listener *str2listener(char *str, struct listener *tail)
150{
151 struct listener *l;
152 char *c, *next, *range, *dupstr;
153 int port, end;
154
155 next = dupstr = strdup(str);
156
157 while (next && *next) {
158 struct sockaddr_storage ss;
159
160 str = next;
161 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100162 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200163 *next++ = 0;
164 }
165
166 /* 2) look for the addr/port delimiter, it's the last colon. */
167 if ((range = strrchr(str, ':')) == NULL) {
168 Alert("Missing port number: '%s'\n", str);
169 goto fail;
170 }
171
172 *range++ = 0;
173
174 if (strrchr(str, ':') != NULL) {
175 /* IPv6 address contains ':' */
176 memset(&ss, 0, sizeof(ss));
177 ss.ss_family = AF_INET6;
178
179 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
180 Alert("Invalid server address: '%s'\n", str);
181 goto fail;
182 }
183 }
184 else {
185 memset(&ss, 0, sizeof(ss));
186 ss.ss_family = AF_INET;
187
188 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
189 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
190 }
191 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
192 struct hostent *he;
193
194 if ((he = gethostbyname(str)) == NULL) {
195 Alert("Invalid server name: '%s'\n", str);
196 goto fail;
197 }
198 else
199 ((struct sockaddr_in *)&ss)->sin_addr =
200 *(struct in_addr *) *(he->h_addr_list);
201 }
202 }
203
204 /* 3) look for the port-end delimiter */
205 if ((c = strchr(range, '-')) != NULL) {
206 *c++ = 0;
207 end = atol(c);
208 }
209 else {
210 end = atol(range);
211 }
212
213 port = atol(range);
214
215 if (port < 1 || port > 65535) {
216 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
217 goto fail;
218 }
219
220 if (end < 1 || end > 65535) {
221 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
222 goto fail;
223 }
224
225 for (; port <= end; port++) {
226 l = (struct listener *)calloc(1, sizeof(struct listener));
227 l->next = tail;
228 tail = l;
229
230 l->fd = -1;
231 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100232 l->state = LI_INIT;
233
234 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100236 tcpv6_add_listener(l);
237 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100239 tcpv4_add_listener(l);
240 }
241 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242 } /* end for(port) */
243 } /* end while(next) */
244 free(dupstr);
245 return tail;
246 fail:
247 free(dupstr);
248 return NULL;
249}
250
Willy Tarreau977b8e42006-12-29 14:19:17 +0100251/*
252 * Sends a warning if proxy <proxy> does not have at least one of the
253 * capabilities in <cap>. An optionnal <hint> may be added at the end
254 * of the warning to help the user. Returns 1 if a warning was emitted
255 * or 0 if the condition is valid.
256 */
257int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
258{
259 char *msg;
260
261 switch (cap) {
262 case PR_CAP_BE: msg = "no backend"; break;
263 case PR_CAP_FE: msg = "no frontend"; break;
264 case PR_CAP_RS: msg = "no ruleset"; break;
265 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
266 default: msg = "not enough"; break;
267 }
268
269 if (!(proxy->cap & cap)) {
270 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100271 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100272 return 1;
273 }
274 return 0;
275}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200276
277/*
278 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
279 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100280int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281{
282
283 if (!strcmp(args[0], "global")) { /* new section */
284 /* no option, nothing special to do */
285 return 0;
286 }
287 else if (!strcmp(args[0], "daemon")) {
288 global.mode |= MODE_DAEMON;
289 }
290 else if (!strcmp(args[0], "debug")) {
291 global.mode |= MODE_DEBUG;
292 }
293 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100294 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200296 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100297 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200298 }
299 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100300 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100303 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100305 else if (!strcmp(args[0], "nosplice")) {
306 global.tune.options &= ~GTUNE_USE_SPLICE;
307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308 else if (!strcmp(args[0], "quiet")) {
309 global.mode |= MODE_QUIET;
310 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200311 else if (!strcmp(args[0], "tune.maxpollevents")) {
312 if (global.tune.maxpollevents != 0) {
313 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
314 return 0;
315 }
316 if (*(args[1]) == 0) {
317 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
318 return -1;
319 }
320 global.tune.maxpollevents = atol(args[1]);
321 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100322 else if (!strcmp(args[0], "tune.maxaccept")) {
323 if (global.tune.maxaccept != 0) {
324 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
325 return 0;
326 }
327 if (*(args[1]) == 0) {
328 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
329 return -1;
330 }
331 global.tune.maxaccept = atol(args[1]);
332 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200333 else if (!strcmp(args[0], "uid")) {
334 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200335 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200336 return 0;
337 }
338 if (*(args[1]) == 0) {
339 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
340 return -1;
341 }
342 global.uid = atol(args[1]);
343 }
344 else if (!strcmp(args[0], "gid")) {
345 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200346 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200347 return 0;
348 }
349 if (*(args[1]) == 0) {
350 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
351 return -1;
352 }
353 global.gid = atol(args[1]);
354 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200355 /* user/group name handling */
356 else if (!strcmp(args[0], "user")) {
357 struct passwd *ha_user;
358 if (global.uid != 0) {
359 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
360 return 0;
361 }
362 errno = 0;
363 ha_user = getpwnam(args[1]);
364 if (ha_user != NULL) {
365 global.uid = (int)ha_user->pw_uid;
366 }
367 else {
368 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
369 exit(1);
370 }
371 }
372 else if (!strcmp(args[0], "group")) {
373 struct group *ha_group;
374 if (global.gid != 0) {
375 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
376 return 0;
377 }
378 errno = 0;
379 ha_group = getgrnam(args[1]);
380 if (ha_group != NULL) {
381 global.gid = (int)ha_group->gr_gid;
382 }
383 else {
384 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
385 exit(1);
386 }
387 }
388 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200389 else if (!strcmp(args[0], "nbproc")) {
390 if (global.nbproc != 0) {
391 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
392 return 0;
393 }
394 if (*(args[1]) == 0) {
395 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
396 return -1;
397 }
398 global.nbproc = atol(args[1]);
399 }
400 else if (!strcmp(args[0], "maxconn")) {
401 if (global.maxconn != 0) {
402 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
403 return 0;
404 }
405 if (*(args[1]) == 0) {
406 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
407 return -1;
408 }
409 global.maxconn = atol(args[1]);
410#ifdef SYSTEM_MAXCONN
411 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
412 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
413 global.maxconn = DEFAULT_MAXCONN;
414 }
415#endif /* SYSTEM_MAXCONN */
416 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100417 else if (!strcmp(args[0], "maxpipes")) {
418 if (global.maxpipes != 0) {
419 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
420 return 0;
421 }
422 if (*(args[1]) == 0) {
423 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
424 return -1;
425 }
426 global.maxpipes = atol(args[1]);
427 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200428 else if (!strcmp(args[0], "ulimit-n")) {
429 if (global.rlimit_nofile != 0) {
430 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
431 return 0;
432 }
433 if (*(args[1]) == 0) {
434 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
435 return -1;
436 }
437 global.rlimit_nofile = atol(args[1]);
438 }
439 else if (!strcmp(args[0], "chroot")) {
440 if (global.chroot != NULL) {
441 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
442 return 0;
443 }
444 if (*(args[1]) == 0) {
445 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
446 return -1;
447 }
448 global.chroot = strdup(args[1]);
449 }
450 else if (!strcmp(args[0], "pidfile")) {
451 if (global.pidfile != NULL) {
452 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
453 return 0;
454 }
455 if (*(args[1]) == 0) {
456 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
457 return -1;
458 }
459 global.pidfile = strdup(args[1]);
460 }
461 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100462 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463 int facility, level;
464
465 if (*(args[1]) == 0 || *(args[2]) == 0) {
466 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
467 return -1;
468 }
469
470 facility = get_log_facility(args[2]);
471 if (facility < 0) {
472 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
473 exit(1);
474 }
475
476 level = 7; /* max syslog level = debug */
477 if (*(args[3])) {
478 level = get_log_level(args[3]);
479 if (level < 0) {
480 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
481 exit(1);
482 }
483 }
484
Robert Tsai81ae1952007-12-05 10:47:29 +0100485 if (args[1][0] == '/') {
486 logsrv.u.addr.sa_family = AF_UNIX;
487 logsrv.u.un = *str2sun(args[1]);
488 } else {
489 logsrv.u.addr.sa_family = AF_INET;
490 logsrv.u.in = *str2sa(args[1]);
491 if (!logsrv.u.in.sin_port)
492 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
493 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200494
495 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100496 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200497 global.logfac1 = facility;
498 global.loglev1 = level;
499 }
500 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100501 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200502 global.logfac2 = facility;
503 global.loglev2 = level;
504 }
505 else {
506 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
507 return -1;
508 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200509 }
510 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
511 if (global.spread_checks != 0) {
512 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
513 return 0;
514 }
515 if (*(args[1]) == 0) {
516 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
517 return -1;
518 }
519 global.spread_checks = atol(args[1]);
520 if (global.spread_checks < 0 || global.spread_checks > 50) {
521 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
522 return -1;
523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200524 }
525 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200526 struct cfg_kw_list *kwl;
527 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200528 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200529
530 list_for_each_entry(kwl, &cfg_keywords.list, list) {
531 for (index = 0; kwl->kw[index].kw != NULL; index++) {
532 if (kwl->kw[index].section != CFG_GLOBAL)
533 continue;
534 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
535 /* prepare error message just in case */
536 snprintf(trash, sizeof(trash),
537 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200538 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
539 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200540 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
541 return -1;
542 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200543 else if (rc > 0) {
544 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
545 return 0;
546 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200547 return 0;
548 }
549 }
550 }
551
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
553 return -1;
554 }
555 return 0;
556}
557
558
559static void init_default_instance()
560{
561 memset(&defproxy, 0, sizeof(defproxy));
562 defproxy.mode = PR_MODE_TCP;
563 defproxy.state = PR_STNEW;
564 defproxy.maxconn = cfg_maxpconn;
565 defproxy.conn_retries = CONN_RETRIES;
566 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200567
568 LIST_INIT(&defproxy.pendconns);
569 LIST_INIT(&defproxy.acl);
570 LIST_INIT(&defproxy.block_cond);
571 LIST_INIT(&defproxy.mon_fail_cond);
572 LIST_INIT(&defproxy.switching_rules);
573
Willy Tarreau3a70f942008-02-15 11:15:34 +0100574 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575}
576
577/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100578 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
579 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100581int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582{
583 static struct proxy *curproxy = NULL;
584 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200585 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100586 int rc;
587 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200588
Willy Tarreau977b8e42006-12-29 14:19:17 +0100589 if (!strcmp(args[0], "listen"))
590 rc = PR_CAP_LISTEN;
591 else if (!strcmp(args[0], "frontend"))
592 rc = PR_CAP_FE | PR_CAP_RS;
593 else if (!strcmp(args[0], "backend"))
594 rc = PR_CAP_BE | PR_CAP_RS;
595 else if (!strcmp(args[0], "ruleset"))
596 rc = PR_CAP_RS;
597 else
598 rc = PR_CAP_NONE;
599
600 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 if (!*args[1]) {
602 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
603 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
604 file, linenum, args[0]);
605 return -1;
606 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200607
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100608 err = invalid_char(args[1]);
609 if (err) {
610 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
611 file, linenum, *err, args[0], args[1]);
612 return -1;
613 }
614
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200615 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
616 /*
617 * If there are two proxies with the same name only following
618 * combinations are allowed:
619 *
620 * listen backend frontend ruleset
621 * listen - - - -
622 * backend - - OK -
623 * frontend - OK - -
624 * ruleset - - - -
625 */
626
627 if (!strcmp(curproxy->id, args[1]) &&
628 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
629 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100630 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
631 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200632 }
633 }
634
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
636 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
637 return -1;
638 }
639
640 curproxy->next = proxy;
641 proxy = curproxy;
642 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200643 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200644 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200645 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100646 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200647 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200648 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200649
Willy Tarreauee991362007-05-14 14:37:50 +0200650 /* Timeouts are defined as -1, so we cannot use the zeroed area
651 * as a default value.
652 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100653 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200654
655 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100657 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658
659 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100660 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 curproxy->listen = str2listener(args[2], curproxy->listen);
662 if (!curproxy->listen)
663 return -1;
664 global.maxsock++;
665 }
666
667 /* set default values */
668 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100670 curproxy->options2 = defproxy.options2;
Willy Tarreau31682232007-11-29 15:38:04 +0100671 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200672 curproxy->except_net = defproxy.except_net;
673 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200675 if (defproxy.fwdfor_hdr_len) {
676 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
677 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
678 }
679
Willy Tarreau977b8e42006-12-29 14:19:17 +0100680 if (curproxy->cap & PR_CAP_FE) {
681 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100682 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100683
684 /* initialize error relocations */
685 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
686 if (defproxy.errmsg[rc].str)
687 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
688 }
689
690 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
691 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692
Willy Tarreau977b8e42006-12-29 14:19:17 +0100693 if (curproxy->cap & PR_CAP_BE) {
694 curproxy->fullconn = defproxy.fullconn;
695 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696
Willy Tarreau977b8e42006-12-29 14:19:17 +0100697 if (defproxy.check_req)
698 curproxy->check_req = strdup(defproxy.check_req);
699 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700
Willy Tarreau977b8e42006-12-29 14:19:17 +0100701 if (defproxy.cookie_name)
702 curproxy->cookie_name = strdup(defproxy.cookie_name);
703 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100704
705 if (defproxy.url_param_name)
706 curproxy->url_param_name = strdup(defproxy.url_param_name);
707 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709
Willy Tarreau977b8e42006-12-29 14:19:17 +0100710 if (curproxy->cap & PR_CAP_RS) {
711 if (defproxy.capture_name)
712 curproxy->capture_name = strdup(defproxy.capture_name);
713 curproxy->capture_namelen = defproxy.capture_namelen;
714 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100715 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716
Willy Tarreau977b8e42006-12-29 14:19:17 +0100717 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100718 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100719 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100720 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100721 curproxy->uri_auth = defproxy.uri_auth;
722 curproxy->mon_net = defproxy.mon_net;
723 curproxy->mon_mask = defproxy.mon_mask;
724 if (defproxy.monitor_uri)
725 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
726 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100727 if (defproxy.defbe.name)
728 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100729 }
730
731 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100732 curproxy->timeout.connect = defproxy.timeout.connect;
733 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100734 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100735 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100736 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100737 curproxy->source_addr = defproxy.source_addr;
738 }
739
Willy Tarreaubaaee002006-06-26 02:48:02 +0200740 curproxy->mode = defproxy.mode;
741 curproxy->logfac1 = defproxy.logfac1;
742 curproxy->logsrv1 = defproxy.logsrv1;
743 curproxy->loglev1 = defproxy.loglev1;
744 curproxy->logfac2 = defproxy.logfac2;
745 curproxy->logsrv2 = defproxy.logsrv2;
746 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100748 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
749 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200750
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751 return 0;
752 }
753 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
754 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100755 /* FIXME-20070101: we should do this too at the end of the
756 * config parsing to free all default values.
757 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200758 free(defproxy.check_req);
759 free(defproxy.cookie_name);
760 free(defproxy.url_param_name);
761 free(defproxy.capture_name);
762 free(defproxy.monitor_uri);
763 free(defproxy.defbe.name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200764 free(defproxy.fwdfor_hdr_name);
765 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100766
Willy Tarreaua534fea2008-08-03 12:19:50 +0200767 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
768 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100769
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 /* we cannot free uri_auth because it might already be used */
771 init_default_instance();
772 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100773 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200774 return 0;
775 }
776 else if (curproxy == NULL) {
777 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
778 return -1;
779 }
780
Willy Tarreau977b8e42006-12-29 14:19:17 +0100781
782 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200783 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100784 struct listener *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100785 int cur_arg;
786
Willy Tarreaubaaee002006-06-26 02:48:02 +0200787 if (curproxy == &defproxy) {
788 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
789 return -1;
790 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100791 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
792 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200793
794 if (strchr(args[1], ':') == NULL) {
795 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
796 file, linenum, args[0]);
797 return -1;
798 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100799
800 last_listen = curproxy->listen;
801 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200802 if (!curproxy->listen)
803 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100804
805 cur_arg = 2;
806 while (*(args[cur_arg])) {
807 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
808#ifdef SO_BINDTODEVICE
809 struct listener *l;
810
811 if (!*args[cur_arg + 1]) {
812 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
813 file, linenum, args[0]);
814 return -1;
815 }
816
817 for (l = curproxy->listen; l != last_listen; l = l->next)
818 l->interface = strdup(args[cur_arg + 1]);
819
820 global.last_checks |= LSTCHK_NETADM;
821
822 cur_arg += 2;
823 continue;
824#else
825 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
826 file, linenum, args[0], args[cur_arg]);
827 return -1;
828#endif
829 }
830 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100831#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100832 struct listener *l;
833
834 for (l = curproxy->listen; l != last_listen; l = l->next)
835 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100836
837 cur_arg ++;
838 continue;
839#else
840 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
841 file, linenum, args[0], args[cur_arg]);
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100842 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100843#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100844 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100845 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100846 file, linenum, args[0]);
847 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100848 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200849 global.maxsock++;
850 return 0;
851 }
852 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
853 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
854 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
855 file, linenum, args[0]);
856 return -1;
857 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100858 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
859 return 0;
860
Willy Tarreaubaaee002006-06-26 02:48:02 +0200861 /* flush useless bits */
862 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
863 return 0;
864 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200865 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100866 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
867 return 0;
868
Willy Tarreau1c47f852006-07-09 08:22:27 +0200869 if (!*args[1]) {
870 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
871 file, linenum, args[0]);
872 return -1;
873 }
874
Willy Tarreaua534fea2008-08-03 12:19:50 +0200875 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100876 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200877 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100878 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200879 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
880
881 return 0;
882 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200883 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
884 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
885 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
886 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
887 else {
888 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
889 return -1;
890 }
891 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100892 else if (!strcmp(args[0], "id")) {
893 struct proxy *target;
894
895 if (curproxy == &defproxy) {
896 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
897 file, linenum, args[0]);
898 return -1;
899 }
900
901 if (!*args[1]) {
902 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
903 file, linenum, args[0]);
904 return -1;
905 }
906
907 curproxy->uuid = atol(args[1]);
908
909 if (curproxy->uuid < 1001) {
910 Alert("parsing [%s:%d]: custom id has to be > 1000",
911 file, linenum);
912 return -1;
913 }
914
915 for (target = proxy; target; target = target->next)
916 if (curproxy != target && curproxy->uuid == target->uuid) {
917 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
918 file, linenum, curproxy->id, target->id);
919 return -1;
920 }
921 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
923 curproxy->state = PR_STSTOPPED;
924 }
925 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
926 curproxy->state = PR_STNEW;
927 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200928 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200929 if (curproxy == &defproxy) {
930 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
931 return -1;
932 }
933
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100934 err = invalid_char(args[1]);
935 if (err) {
936 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
937 file, linenum, *err, args[1]);
938 return -1;
939 }
940
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200941 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
942 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
943 file, linenum, args[1]);
944 return -1;
945 }
946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947 else if (!strcmp(args[0], "cookie")) { /* cookie name */
948 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949
Willy Tarreau977b8e42006-12-29 14:19:17 +0100950 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
951 return 0;
952
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953 if (*(args[1]) == 0) {
954 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
955 file, linenum, args[0]);
956 return -1;
957 }
Willy Tarreaua534fea2008-08-03 12:19:50 +0200958
959 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960 curproxy->cookie_name = strdup(args[1]);
961 curproxy->cookie_len = strlen(curproxy->cookie_name);
962
963 cur_arg = 2;
964 while (*(args[cur_arg])) {
965 if (!strcmp(args[cur_arg], "rewrite")) {
966 curproxy->options |= PR_O_COOK_RW;
967 }
968 else if (!strcmp(args[cur_arg], "indirect")) {
969 curproxy->options |= PR_O_COOK_IND;
970 }
971 else if (!strcmp(args[cur_arg], "insert")) {
972 curproxy->options |= PR_O_COOK_INS;
973 }
974 else if (!strcmp(args[cur_arg], "nocache")) {
975 curproxy->options |= PR_O_COOK_NOC;
976 }
977 else if (!strcmp(args[cur_arg], "postonly")) {
978 curproxy->options |= PR_O_COOK_POST;
979 }
980 else if (!strcmp(args[cur_arg], "prefix")) {
981 curproxy->options |= PR_O_COOK_PFX;
982 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +0200983 else if (!strcmp(args[cur_arg], "domain")) {
984 if (!*args[cur_arg + 1]) {
985 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
986 file, linenum, args[cur_arg]);
987 return -1;
988 }
989
990 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
991 /* rfc2109, 4.3.2 Rejecting Cookies */
992 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
993 " dots or does not start with a dot.\n",
994 file, linenum, args[cur_arg + 1]);
995 return -1;
996 }
997
998 err = invalid_domainchar(args[cur_arg + 1]);
999 if (err) {
1000 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1001 file, linenum, *err, args[cur_arg + 1]);
1002 return -1;
1003 }
1004
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001005 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001006 cur_arg++;
1007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001008 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001009 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001010 file, linenum, args[0]);
1011 return -1;
1012 }
1013 cur_arg++;
1014 }
1015 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1016 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1017 file, linenum);
1018 return -1;
1019 }
1020
1021 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1022 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1023 file, linenum);
1024 return -1;
1025 }
1026 }/* end else if (!strcmp(args[0], "cookie")) */
1027 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001028
Willy Tarreau977b8e42006-12-29 14:19:17 +01001029 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1030 return 0;
1031
Willy Tarreaubaaee002006-06-26 02:48:02 +02001032 if (*(args[5]) == 0) {
1033 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1034 file, linenum, args[0]);
1035 return -1;
1036 }
1037 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001038 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001039 curproxy->appsession_name = strdup(args[1]);
1040 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1041 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001042 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1043 if (err) {
1044 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1045 file, linenum, *err, args[0]);
1046 return -1;
1047 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001048 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001049
Willy Tarreau51041c72007-09-09 21:56:53 +02001050 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1051 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 return -1;
1053 }
1054 } /* Url App Session */
1055 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001056 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1057 return 0;
1058
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 if (*(args[4]) == 0) {
1061 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1062 file, linenum, args[0]);
1063 return -1;
1064 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001065 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066 curproxy->capture_name = strdup(args[2]);
1067 curproxy->capture_namelen = strlen(curproxy->capture_name);
1068 curproxy->capture_len = atol(args[4]);
1069 if (curproxy->capture_len >= CAPTURE_LEN) {
1070 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1071 file, linenum, CAPTURE_LEN - 1);
1072 curproxy->capture_len = CAPTURE_LEN - 1;
1073 }
1074 curproxy->to_log |= LW_COOKIE;
1075 }
1076 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1077 struct cap_hdr *hdr;
1078
1079 if (curproxy == &defproxy) {
1080 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1081 return -1;
1082 }
1083
1084 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1085 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1086 file, linenum, args[0], args[1]);
1087 return -1;
1088 }
1089
1090 hdr = calloc(sizeof(struct cap_hdr), 1);
1091 hdr->next = curproxy->req_cap;
1092 hdr->name = strdup(args[3]);
1093 hdr->namelen = strlen(args[3]);
1094 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001095 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001096 hdr->index = curproxy->nb_req_cap++;
1097 curproxy->req_cap = hdr;
1098 curproxy->to_log |= LW_REQHDR;
1099 }
1100 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1101 struct cap_hdr *hdr;
1102
1103 if (curproxy == &defproxy) {
1104 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1105 return -1;
1106 }
1107
1108 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1109 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1110 file, linenum, args[0], args[1]);
1111 return -1;
1112 }
1113 hdr = calloc(sizeof(struct cap_hdr), 1);
1114 hdr->next = curproxy->rsp_cap;
1115 hdr->name = strdup(args[3]);
1116 hdr->namelen = strlen(args[3]);
1117 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001118 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 hdr->index = curproxy->nb_rsp_cap++;
1120 curproxy->rsp_cap = hdr;
1121 curproxy->to_log |= LW_RSPHDR;
1122 }
1123 else {
1124 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1125 file, linenum, args[0]);
1126 return -1;
1127 }
1128 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001129 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001130 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1131 return 0;
1132
Willy Tarreaubaaee002006-06-26 02:48:02 +02001133 if (*(args[1]) == 0) {
1134 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1135 file, linenum, args[0]);
1136 return -1;
1137 }
1138 curproxy->conn_retries = atol(args[1]);
1139 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001140 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1141 int pol = ACL_COND_NONE;
1142 struct acl_cond *cond;
1143
Willy Tarreaub099aca2008-10-12 17:26:37 +02001144 if (curproxy == &defproxy) {
1145 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1146 return -1;
1147 }
1148
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001149 if (!strcmp(args[1], "if"))
1150 pol = ACL_COND_IF;
1151 else if (!strcmp(args[1], "unless"))
1152 pol = ACL_COND_UNLESS;
1153
1154 if (pol == ACL_COND_NONE) {
1155 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1156 file, linenum, args[0]);
1157 return -1;
1158 }
1159
1160 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1161 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1162 file, linenum);
1163 return -1;
1164 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001165 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001166 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1167 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001168 else if (!strcmp(args[0], "redirect")) {
1169 int pol = ACL_COND_NONE;
1170 struct acl_cond *cond;
1171 struct redirect_rule *rule;
1172 int cur_arg;
1173 int type = REDIRECT_TYPE_NONE;
1174 int code = 302;
1175 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001176 char *cookie = NULL;
1177 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001178 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001179
1180 cur_arg = 1;
1181 while (*(args[cur_arg])) {
1182 if (!strcmp(args[cur_arg], "location")) {
1183 if (!*args[cur_arg + 1]) {
1184 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1185 file, linenum, args[0], args[cur_arg]);
1186 return -1;
1187 }
1188
1189 type = REDIRECT_TYPE_LOCATION;
1190 cur_arg++;
1191 destination = args[cur_arg];
1192 }
1193 else if (!strcmp(args[cur_arg], "prefix")) {
1194 if (!*args[cur_arg + 1]) {
1195 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1196 file, linenum, args[0], args[cur_arg]);
1197 return -1;
1198 }
1199
1200 type = REDIRECT_TYPE_PREFIX;
1201 cur_arg++;
1202 destination = args[cur_arg];
1203 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001204 else if (!strcmp(args[cur_arg], "set-cookie")) {
1205 if (!*args[cur_arg + 1]) {
1206 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1207 file, linenum, args[0], args[cur_arg]);
1208 return -1;
1209 }
1210
1211 cur_arg++;
1212 cookie = args[cur_arg];
1213 cookie_set = 1;
1214 }
1215 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1216 if (!*args[cur_arg + 1]) {
1217 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1218 file, linenum, args[0], args[cur_arg]);
1219 return -1;
1220 }
1221
1222 cur_arg++;
1223 cookie = args[cur_arg];
1224 cookie_set = 0;
1225 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001226 else if (!strcmp(args[cur_arg],"code")) {
1227 if (!*args[cur_arg + 1]) {
1228 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1229 file, linenum, args[0]);
1230 return -1;
1231 }
1232 cur_arg++;
1233 code = atol(args[cur_arg]);
1234 if (code < 301 || code > 303) {
1235 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1236 file, linenum, args[0], code);
1237 return -1;
1238 }
1239 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001240 else if (!strcmp(args[cur_arg],"drop-query")) {
1241 flags |= REDIRECT_FLAG_DROP_QS;
1242 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001243 else if (!strcmp(args[cur_arg], "if")) {
1244 pol = ACL_COND_IF;
1245 cur_arg++;
1246 break;
1247 }
1248 else if (!strcmp(args[cur_arg], "unless")) {
1249 pol = ACL_COND_UNLESS;
1250 cur_arg++;
1251 break;
1252 }
1253 else {
1254 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1255 file, linenum, args[0], args[cur_arg]);
1256 return -1;
1257 }
1258 cur_arg++;
1259 }
1260
1261 if (type == REDIRECT_TYPE_NONE) {
1262 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1263 file, linenum, args[0]);
1264 return -1;
1265 }
1266
1267 if (pol == ACL_COND_NONE) {
1268 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1269 file, linenum, args[0]);
1270 return -1;
1271 }
1272
1273 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1274 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1275 file, linenum, args[0]);
1276 return -1;
1277 }
1278
Willy Tarreaua9802632008-07-25 19:13:19 +02001279 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001280 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1281 rule->cond = cond;
1282 rule->rdr_str = strdup(destination);
1283 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001284 if (cookie) {
1285 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1286 * a clear consists in appending "; Max-Age=0" at the end.
1287 */
1288 rule->cookie_len = strlen(cookie);
1289 if (cookie_set)
1290 rule->cookie_str = strdup(cookie);
1291 else {
1292 rule->cookie_str = malloc(rule->cookie_len + 12);
1293 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1294 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1295 rule->cookie_len += 11;
1296 }
1297 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001298 rule->type = type;
1299 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001300 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001301 LIST_INIT(&rule->list);
1302 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1303 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001304 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001305 int pol = ACL_COND_NONE;
1306 struct acl_cond *cond;
1307 struct switching_rule *rule;
1308
Willy Tarreaub099aca2008-10-12 17:26:37 +02001309 if (curproxy == &defproxy) {
1310 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1311 return -1;
1312 }
1313
Willy Tarreau55ea7572007-06-17 19:56:27 +02001314 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1315 return 0;
1316
1317 if (*(args[1]) == 0) {
1318 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1319 return -1;
1320 }
1321
1322 if (!strcmp(args[2], "if"))
1323 pol = ACL_COND_IF;
1324 else if (!strcmp(args[2], "unless"))
1325 pol = ACL_COND_UNLESS;
1326
1327 if (pol == ACL_COND_NONE) {
1328 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1329 file, linenum, args[0]);
1330 return -1;
1331 }
1332
1333 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001334 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001335 file, linenum);
1336 return -1;
1337 }
1338
Willy Tarreaua9802632008-07-25 19:13:19 +02001339 cond->line = linenum;
1340 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001341 struct acl *acl;
1342 const char *name;
1343
1344 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1345 name = acl ? acl->name : "(unknown)";
1346 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1347 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001348 }
1349
Willy Tarreau55ea7572007-06-17 19:56:27 +02001350 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1351 rule->cond = cond;
1352 rule->be.name = strdup(args[1]);
1353 LIST_INIT(&rule->list);
1354 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1355 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001356 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001357 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1358 return 0;
1359
Willy Tarreaubaaee002006-06-26 02:48:02 +02001360 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1361 curproxy->uri_auth = NULL; /* we must detach from the default config */
1362
1363 if (*(args[1]) == 0) {
1364 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1365 return -1;
1366 } else if (!strcmp(args[1], "uri")) {
1367 if (*(args[2]) == 0) {
1368 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1369 return -1;
1370 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1371 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1372 return -1;
1373 }
1374 } else if (!strcmp(args[1], "realm")) {
1375 if (*(args[2]) == 0) {
1376 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1377 return -1;
1378 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1379 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1380 return -1;
1381 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001382 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001383 unsigned interval;
1384
1385 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1386 if (err) {
1387 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1388 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001389 return -1;
1390 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1391 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1392 return -1;
1393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 } else if (!strcmp(args[1], "auth")) {
1395 if (*(args[2]) == 0) {
1396 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1397 return -1;
1398 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1399 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1400 return -1;
1401 }
1402 } else if (!strcmp(args[1], "scope")) {
1403 if (*(args[2]) == 0) {
1404 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1405 return -1;
1406 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1407 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1408 return -1;
1409 }
1410 } else if (!strcmp(args[1], "enable")) {
1411 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1412 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1413 return -1;
1414 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001415 } else if (!strcmp(args[1], "hide-version")) {
1416 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1417 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1418 return -1;
1419 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001420 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001421 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422 file, linenum, args[0]);
1423 return -1;
1424 }
1425 }
1426 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001427 int optnum;
1428
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001429 if (*(args[1]) == '\0') {
1430 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1431 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001432 return -1;
1433 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001434
1435 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1436 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1437 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1438 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001439
1440 if (!inv)
1441 curproxy->options |= cfg_opts[optnum].val;
1442 else
1443 curproxy->options &= ~cfg_opts[optnum].val;
1444
Willy Tarreau13943ab2006-12-31 00:24:10 +01001445 return 0;
1446 }
1447 }
1448
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001449 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1450 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
1451 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
1452 return 0;
1453
1454 if (!inv)
1455 curproxy->options2 |= cfg_opts2[optnum].val;
1456 else
1457 curproxy->options2 &= ~cfg_opts2[optnum].val;
1458
1459 return 0;
1460 }
1461 }
1462
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001463 if (inv) {
1464 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1465 file, linenum, args[1]);
1466 return -1;
1467 }
1468
Willy Tarreau13943ab2006-12-31 00:24:10 +01001469 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470 /* generate a complete HTTP log */
1471 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1472 else if (!strcmp(args[1], "tcplog"))
1473 /* generate a detailed TCP log */
1474 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001475 else if (!strcmp(args[1], "tcpka")) {
1476 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001477 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1478 return 0;
1479
1480 if (curproxy->cap & PR_CAP_FE)
1481 curproxy->options |= PR_O_TCP_CLI_KA;
1482 if (curproxy->cap & PR_CAP_BE)
1483 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001484 }
1485 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001486 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1487 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001488 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001489 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001490 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001491 curproxy->options &= ~PR_O_SMTP_CHK;
1492 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493 if (!*args[2]) { /* no argument */
1494 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1495 curproxy->check_len = strlen(DEF_CHECK_REQ);
1496 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001497 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001498 curproxy->check_req = (char *)malloc(reqlen);
1499 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1500 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1501 } else { /* more arguments : METHOD URI [HTTP_VER] */
1502 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1503 if (*args[4])
1504 reqlen += strlen(args[4]);
1505 else
1506 reqlen += strlen("HTTP/1.0");
1507
1508 curproxy->check_req = (char *)malloc(reqlen);
1509 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1510 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1511 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001512 }
1513 else if (!strcmp(args[1], "ssl-hello-chk")) {
1514 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001515 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1516 return 0;
1517
Willy Tarreaua534fea2008-08-03 12:19:50 +02001518 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001519 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001520 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001521 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001522 }
Willy Tarreau23677902007-05-08 23:50:35 +02001523 else if (!strcmp(args[1], "smtpchk")) {
1524 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001525 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001526 curproxy->options &= ~PR_O_HTTP_CHK;
1527 curproxy->options &= ~PR_O_SSL3_CHK;
1528 curproxy->options |= PR_O_SMTP_CHK;
1529
1530 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1531 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1532 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1533 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1534 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1535 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1536 curproxy->check_req = (char *)malloc(reqlen);
1537 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1538 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1539 } else {
1540 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1541 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1542 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1543 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1544 }
1545 }
1546 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001547 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001548 int cur_arg;
1549
1550 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1551 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001552 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001553
1554 curproxy->options |= PR_O_FWDFOR;
1555
1556 free(curproxy->fwdfor_hdr_name);
1557 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1558 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1559
1560 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1561 cur_arg = 2;
1562 while (*(args[cur_arg])) {
1563 if (!strcmp(args[cur_arg], "except")) {
1564 /* suboption except - needs additional argument for it */
1565 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1566 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1567 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001568 return -1;
1569 }
1570 /* flush useless bits */
1571 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001572 cur_arg += 2;
1573 } else if (!strcmp(args[cur_arg], "header")) {
1574 /* suboption header - needs additional argument for it */
1575 if (*(args[cur_arg+1]) == 0) {
1576 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1577 file, linenum, args[0], args[1], args[cur_arg]);
1578 return -1;
1579 }
1580 free(curproxy->fwdfor_hdr_name);
1581 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1582 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1583 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001584 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001585 /* unknown suboption - catchall */
1586 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1587 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001588 return -1;
1589 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001590 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001591 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592 else {
1593 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1594 return -1;
1595 }
1596 return 0;
1597 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001598 else if (!strcmp(args[0], "default_backend")) {
1599 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1600 return 0;
1601
1602 if (*(args[1]) == 0) {
1603 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1604 return -1;
1605 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001606 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001607 curproxy->defbe.name = strdup(args[1]);
1608 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001610 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1611 return 0;
1612
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001613 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1614 file, linenum, args[0]);
1615
Willy Tarreaubaaee002006-06-26 02:48:02 +02001616 /* enable reconnections to dispatch */
1617 curproxy->options |= PR_O_REDISP;
1618 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001619 else if (!strcmp(args[0], "http-check")) {
1620 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1621 return 0;
1622
1623 if (strcmp(args[1], "disable-on-404") == 0) {
1624 /* enable a graceful server shutdown on an HTTP 404 response */
1625 curproxy->options |= PR_O_DISABLE404;
1626 }
1627 else {
1628 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1629 return -1;
1630 }
1631 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001632 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001633 if (curproxy == &defproxy) {
1634 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1635 return -1;
1636 }
1637
Willy Tarreaub80c2302007-11-30 20:51:32 +01001638 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1639 return 0;
1640
1641 if (strcmp(args[1], "fail") == 0) {
1642 /* add a condition to fail monitor requests */
1643 int pol = ACL_COND_NONE;
1644 struct acl_cond *cond;
1645
1646 if (!strcmp(args[2], "if"))
1647 pol = ACL_COND_IF;
1648 else if (!strcmp(args[2], "unless"))
1649 pol = ACL_COND_UNLESS;
1650
1651 if (pol == ACL_COND_NONE) {
1652 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1653 file, linenum, args[0], args[1]);
1654 return -1;
1655 }
1656
1657 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1658 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1659 file, linenum, args[0], args[1]);
1660 return -1;
1661 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001662 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001663 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1664 }
1665 else {
1666 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1667 return -1;
1668 }
1669 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670#ifdef TPROXY
1671 else if (!strcmp(args[0], "transparent")) {
1672 /* enable transparent proxy connections */
1673 curproxy->options |= PR_O_TRANSP;
1674 }
1675#endif
1676 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001677 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1678 return 0;
1679
Willy Tarreaubaaee002006-06-26 02:48:02 +02001680 if (*(args[1]) == 0) {
1681 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1682 return -1;
1683 }
1684 curproxy->maxconn = atol(args[1]);
1685 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001686 else if (!strcmp(args[0], "backlog")) { /* backlog */
1687 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1688 return 0;
1689
1690 if (*(args[1]) == 0) {
1691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1692 return -1;
1693 }
1694 curproxy->backlog = atol(args[1]);
1695 }
Willy Tarreau86034312006-12-29 00:10:33 +01001696 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001697 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1698 return 0;
1699
Willy Tarreau86034312006-12-29 00:10:33 +01001700 if (*(args[1]) == 0) {
1701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1702 return -1;
1703 }
1704 curproxy->fullconn = atol(args[1]);
1705 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001706 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1707 if (*(args[1]) == 0) {
1708 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1709 return -1;
1710 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001711 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1712 if (err) {
1713 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1714 file, linenum, *err);
1715 return -1;
1716 }
1717 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001718 }
1719 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
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;
1726
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 if (strchr(args[1], ':') == NULL) {
1728 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1729 return -1;
1730 }
1731 curproxy->dispatch_addr = *str2sa(args[1]);
1732 }
1733 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001734 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1735 return 0;
1736
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02001737 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001738 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1739 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1740 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001741 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742 }
1743 else if (!strcmp(args[0], "server")) { /* server address */
1744 int cur_arg;
1745 char *rport;
1746 char *raddr;
1747 short realport;
1748 int do_check;
1749
1750 if (curproxy == &defproxy) {
1751 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1752 return -1;
1753 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001754 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1755 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001756
1757 if (!*args[2]) {
1758 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1759 file, linenum, args[0]);
1760 return -1;
1761 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001762
1763 err = invalid_char(args[1]);
1764 if (err) {
1765 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1766 file, linenum, *err, args[1]);
1767 return -1;
1768 }
1769
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1771 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1772 return -1;
1773 }
1774
1775 /* the servers are linked backwards first */
1776 newsrv->next = curproxy->srv;
1777 curproxy->srv = newsrv;
1778 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001779 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780
1781 LIST_INIT(&newsrv->pendconns);
1782 do_check = 0;
1783 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001784 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001785 newsrv->id = strdup(args[1]);
1786
1787 /* several ways to check the port component :
1788 * - IP => port=+0, relative
1789 * - IP: => port=+0, relative
1790 * - IP:N => port=N, absolute
1791 * - IP:+N => port=+N, relative
1792 * - IP:-N => port=-N, relative
1793 */
1794 raddr = strdup(args[2]);
1795 rport = strchr(raddr, ':');
1796 if (rport) {
1797 *rport++ = 0;
1798 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001799 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800 newsrv->state |= SRV_MAPPORTS;
1801 } else {
1802 realport = 0;
1803 newsrv->state |= SRV_MAPPORTS;
1804 }
1805
1806 newsrv->addr = *str2sa(raddr);
1807 newsrv->addr.sin_port = htons(realport);
1808 free(raddr);
1809
1810 newsrv->curfd = -1; /* no health-check in progress */
1811 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001812 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1813 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001814 newsrv->rise = DEF_RISETIME;
1815 newsrv->fall = DEF_FALLTIME;
1816 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001817 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001818 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001819 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001820
Willy Tarreaubaaee002006-06-26 02:48:02 +02001821 cur_arg = 3;
1822 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001823 if (!strcmp(args[cur_arg], "id")) {
1824 struct server *target;
1825
1826 if (!*args[cur_arg + 1]) {
1827 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1828 file, linenum, args[cur_arg]);
1829 return -1;
1830 }
1831
1832 newsrv->puid = atol(args[cur_arg + 1]);
1833
1834 if (newsrv->puid< 1001) {
1835 Alert("parsing [%s:%d]: custom id has to be > 1000",
1836 file, linenum);
1837 return -1;
1838 }
1839
1840 for (target = proxy->srv; target; target = target->next)
1841 if (newsrv != target && newsrv->puid == target->puid) {
1842 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1843 file, linenum, newsrv->id, target->id);
1844 return -1;
1845 }
1846 cur_arg += 2;
1847 }
1848 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001849 newsrv->cookie = strdup(args[cur_arg + 1]);
1850 newsrv->cklen = strlen(args[cur_arg + 1]);
1851 cur_arg += 2;
1852 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001853 else if (!strcmp(args[cur_arg], "redir")) {
1854 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1855 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1856 cur_arg += 2;
1857 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001858 else if (!strcmp(args[cur_arg], "rise")) {
1859 newsrv->rise = atol(args[cur_arg + 1]);
1860 newsrv->health = newsrv->rise;
1861 cur_arg += 2;
1862 }
1863 else if (!strcmp(args[cur_arg], "fall")) {
1864 newsrv->fall = atol(args[cur_arg + 1]);
1865 cur_arg += 2;
1866 }
1867 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001868 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1869 if (err) {
1870 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1871 file, linenum, *err, newsrv->id);
1872 return -1;
1873 }
1874 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001875 cur_arg += 2;
1876 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001877 else if (!strcmp(args[cur_arg], "fastinter")) {
1878 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1879 if (err) {
1880 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1881 file, linenum, *err, newsrv->id);
1882 return -1;
1883 }
1884 newsrv->fastinter = val;
1885 cur_arg += 2;
1886 }
1887 else if (!strcmp(args[cur_arg], "downinter")) {
1888 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1889 if (err) {
1890 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1891 file, linenum, *err, newsrv->id);
1892 return -1;
1893 }
1894 newsrv->downinter = val;
1895 cur_arg += 2;
1896 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001897 else if (!strcmp(args[cur_arg], "addr")) {
1898 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001899 cur_arg += 2;
1900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 else if (!strcmp(args[cur_arg], "port")) {
1902 newsrv->check_port = atol(args[cur_arg + 1]);
1903 cur_arg += 2;
1904 }
1905 else if (!strcmp(args[cur_arg], "backup")) {
1906 newsrv->state |= SRV_BACKUP;
1907 cur_arg ++;
1908 }
1909 else if (!strcmp(args[cur_arg], "weight")) {
1910 int w;
1911 w = atol(args[cur_arg + 1]);
1912 if (w < 1 || w > 256) {
1913 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1914 file, linenum, newsrv->id, w);
1915 return -1;
1916 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001917 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 cur_arg += 2;
1919 }
1920 else if (!strcmp(args[cur_arg], "minconn")) {
1921 newsrv->minconn = atol(args[cur_arg + 1]);
1922 cur_arg += 2;
1923 }
1924 else if (!strcmp(args[cur_arg], "maxconn")) {
1925 newsrv->maxconn = atol(args[cur_arg + 1]);
1926 cur_arg += 2;
1927 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001928 else if (!strcmp(args[cur_arg], "maxqueue")) {
1929 newsrv->maxqueue = atol(args[cur_arg + 1]);
1930 cur_arg += 2;
1931 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001932 else if (!strcmp(args[cur_arg], "slowstart")) {
1933 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001934 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001935 if (err) {
1936 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1937 file, linenum, *err, newsrv->id);
1938 return -1;
1939 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001940 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001941 cur_arg += 2;
1942 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01001943 else if (!strcmp(args[cur_arg], "track")) {
1944
1945 if (!*args[cur_arg + 1]) {
1946 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
1947 file, linenum);
1948 return -1;
1949 }
1950
1951 newsrv->trackit = strdup(args[cur_arg + 1]);
1952
1953 cur_arg += 2;
1954 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955 else if (!strcmp(args[cur_arg], "check")) {
1956 global.maxsock++;
1957 do_check = 1;
1958 cur_arg += 1;
1959 }
1960 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1961 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001962#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001963 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1964 file, linenum, "source", "usesrc");
1965#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1967 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001968#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001969 return -1;
1970 }
1971 newsrv->state |= SRV_BIND_SRC;
1972 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1973 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001974 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001975#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1976#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001977 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001978 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1979 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001980 return -1;
1981 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001982#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001983 if (!*args[cur_arg + 1]) {
1984 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1985 file, linenum, "usesrc");
1986 return -1;
1987 }
1988 if (!strcmp(args[cur_arg + 1], "client")) {
1989 newsrv->state |= SRV_TPROXY_CLI;
1990 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1991 newsrv->state |= SRV_TPROXY_CIP;
1992 } else {
1993 newsrv->state |= SRV_TPROXY_ADDR;
1994 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1995 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001996 global.last_checks |= LSTCHK_NETADM;
1997#if !defined(CONFIG_HAP_LINUX_TPROXY)
1998 global.last_checks |= LSTCHK_CTTPROXY;
1999#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002000 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002001#else /* no TPROXY support */
2002 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002003 file, linenum, "usesrc");
2004 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002005#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002006 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002007 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002008 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2009 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2010 file, linenum, "usesrc", "source");
2011 return -1;
2012 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002013 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002014 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 +02002015 file, linenum, newsrv->id);
2016 return -1;
2017 }
2018 }
2019
2020 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002021 if (newsrv->trackit) {
2022 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2023 file, linenum);
2024 return -1;
2025 }
2026
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002027 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2028 newsrv->check_port = newsrv->check_addr.sin_port;
2029
Willy Tarreaubaaee002006-06-26 02:48:02 +02002030 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2031 newsrv->check_port = realport; /* by default */
2032 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002033 /* not yet valid, because no port was set on
2034 * the server either. We'll check if we have
2035 * a known port on the first listener.
2036 */
2037 struct listener *l;
2038 l = curproxy->listen;
2039 if (l) {
2040 int port;
2041 port = (l->addr.ss_family == AF_INET6)
2042 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2043 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2044 newsrv->check_port = port;
2045 }
2046 }
2047 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002048 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2049 file, linenum, newsrv->id);
2050 return -1;
2051 }
2052 newsrv->state |= SRV_CHECKED;
2053 }
2054
2055 if (newsrv->state & SRV_BACKUP)
2056 curproxy->srv_bck++;
2057 else
2058 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002059
2060 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002061 }
2062 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002063 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002064 int facility;
2065
2066 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2067 curproxy->logfac1 = global.logfac1;
2068 curproxy->logsrv1 = global.logsrv1;
2069 curproxy->loglev1 = global.loglev1;
2070 curproxy->logfac2 = global.logfac2;
2071 curproxy->logsrv2 = global.logsrv2;
2072 curproxy->loglev2 = global.loglev2;
2073 }
2074 else if (*(args[1]) && *(args[2])) {
2075 int level;
2076
2077 facility = get_log_facility(args[2]);
2078 if (facility < 0) {
2079 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2080 exit(1);
2081 }
2082
2083 level = 7; /* max syslog level = debug */
2084 if (*(args[3])) {
2085 level = get_log_level(args[3]);
2086 if (level < 0) {
2087 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2088 exit(1);
2089 }
2090 }
2091
Robert Tsai81ae1952007-12-05 10:47:29 +01002092 if (args[1][0] == '/') {
2093 logsrv.u.addr.sa_family = AF_UNIX;
2094 logsrv.u.un = *str2sun(args[1]);
2095 } else {
2096 logsrv.u.addr.sa_family = AF_INET;
2097 logsrv.u.in = *str2sa(args[1]);
2098 if (!logsrv.u.in.sin_port) {
2099 logsrv.u.in.sin_port =
2100 htons(SYSLOG_PORT);
2101 }
2102 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103
2104 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002105 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 curproxy->logfac1 = facility;
2107 curproxy->loglev1 = level;
2108 }
2109 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002110 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 curproxy->logfac2 = facility;
2112 curproxy->loglev2 = level;
2113 }
2114 else {
2115 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2116 return -1;
2117 }
2118 }
2119 else {
2120 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2121 file, linenum);
2122 return -1;
2123 }
2124 }
2125 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002126 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2127 return 0;
2128
Willy Tarreaubaaee002006-06-26 02:48:02 +02002129 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002130#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002131 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2132 file, linenum, "source", "usesrc");
2133#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002134 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2135 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002136#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002137 return -1;
2138 }
2139
2140 curproxy->source_addr = *str2sa(args[1]);
2141 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01002142 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002143#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2144#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01002145 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2146 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2147 file, linenum, "usesrc");
2148 return -1;
2149 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002150#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01002151 if (!*args[3]) {
2152 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2153 file, linenum, "usesrc");
2154 return -1;
2155 }
2156
2157 if (!strcmp(args[3], "client")) {
2158 curproxy->options |= PR_O_TPXY_CLI;
2159 } else if (!strcmp(args[3], "clientip")) {
2160 curproxy->options |= PR_O_TPXY_CIP;
2161 } else {
2162 curproxy->options |= PR_O_TPXY_ADDR;
2163 curproxy->tproxy_addr = *str2sa(args[3]);
2164 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002165 global.last_checks |= LSTCHK_NETADM;
2166#if !defined(CONFIG_HAP_LINUX_TPROXY)
2167 global.last_checks |= LSTCHK_CTTPROXY;
2168#endif
2169#else /* no TPROXY support */
2170 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002171 file, linenum, "usesrc");
2172 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002173#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002174 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002175 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002176 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2177 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2178 file, linenum, "usesrc", "source");
2179 return -1;
2180 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002181 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2182 regex_t *preg;
2183 if (curproxy == &defproxy) {
2184 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2185 return -1;
2186 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002187 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2188 return 0;
2189
Willy Tarreaubaaee002006-06-26 02:48:02 +02002190 if (*(args[1]) == 0 || *(args[2]) == 0) {
2191 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2192 file, linenum, args[0]);
2193 return -1;
2194 }
2195
2196 preg = calloc(1, sizeof(regex_t));
2197 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2198 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2199 return -1;
2200 }
2201
2202 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2203 if (err) {
2204 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2205 file, linenum, *err);
2206 return -1;
2207 }
2208 }
2209 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2210 regex_t *preg;
2211 if (curproxy == &defproxy) {
2212 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2213 return -1;
2214 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002215 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2216 return 0;
2217
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 if (*(args[1]) == 0) {
2219 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2220 return -1;
2221 }
2222
2223 preg = calloc(1, sizeof(regex_t));
2224 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2225 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2226 return -1;
2227 }
2228
2229 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2230 }
2231 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2232 regex_t *preg;
2233 if (curproxy == &defproxy) {
2234 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2235 return -1;
2236 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002237 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2238 return 0;
2239
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240 if (*(args[1]) == 0) {
2241 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2242 return -1;
2243 }
2244
2245 preg = calloc(1, sizeof(regex_t));
2246 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2247 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2248 return -1;
2249 }
2250
2251 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2252 }
2253 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2254 regex_t *preg;
2255 if (curproxy == &defproxy) {
2256 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2257 return -1;
2258 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002259 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2260 return 0;
2261
Willy Tarreaubaaee002006-06-26 02:48:02 +02002262 if (*(args[1]) == 0) {
2263 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2264 return -1;
2265 }
2266
2267 preg = calloc(1, sizeof(regex_t));
2268 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2269 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2270 return -1;
2271 }
2272
2273 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2274 }
2275 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2276 regex_t *preg;
2277 if (curproxy == &defproxy) {
2278 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2279 return -1;
2280 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002281 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2282 return 0;
2283
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284 if (*(args[1]) == 0) {
2285 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2286 return -1;
2287 }
2288
2289 preg = calloc(1, sizeof(regex_t));
2290 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2291 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2292 return -1;
2293 }
2294
2295 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2296 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002297 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2298 regex_t *preg;
2299 if (curproxy == &defproxy) {
2300 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2301 return -1;
2302 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002303 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2304 return 0;
2305
Willy Tarreaub8750a82006-09-03 09:56:00 +02002306 if (*(args[1]) == 0) {
2307 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2308 return -1;
2309 }
2310
2311 preg = calloc(1, sizeof(regex_t));
2312 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2313 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2314 return -1;
2315 }
2316
2317 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2318 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002319 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2320 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002321 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002322 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2323 return -1;
2324 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002325 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2326 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002327
Willy Tarreau977b8e42006-12-29 14:19:17 +01002328 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002329 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2330 file, linenum, args[0]);
2331 return -1;
2332 }
2333
2334 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002335 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002336 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2337 }
2338
2339 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2340 }
2341 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2342 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002343 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002344 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2345 return -1;
2346 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002347 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2348 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002349
Willy Tarreau977b8e42006-12-29 14:19:17 +01002350 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002351 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2352 file, linenum, args[0]);
2353 return -1;
2354 }
2355
2356 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002357 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002358 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2359 }
2360
2361 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2362 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2364 regex_t *preg;
2365 if (curproxy == &defproxy) {
2366 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2367 return -1;
2368 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002369 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2370 return 0;
2371
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 if (*(args[1]) == 0 || *(args[2]) == 0) {
2373 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2374 file, linenum, args[0]);
2375 return -1;
2376 }
2377
2378 preg = calloc(1, sizeof(regex_t));
2379 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2380 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2381 return -1;
2382 }
2383
2384 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2385 if (err) {
2386 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2387 file, linenum, *err);
2388 return -1;
2389 }
2390 }
2391 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2392 regex_t *preg;
2393 if (curproxy == &defproxy) {
2394 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2395 return -1;
2396 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002397 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2398 return 0;
2399
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 if (*(args[1]) == 0) {
2401 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2402 return -1;
2403 }
2404
2405 preg = calloc(1, sizeof(regex_t));
2406 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2407 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2408 return -1;
2409 }
2410
2411 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2412 }
2413 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2414 regex_t *preg;
2415 if (curproxy == &defproxy) {
2416 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2417 return -1;
2418 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002419 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2420 return 0;
2421
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 if (*(args[1]) == 0) {
2423 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2424 return -1;
2425 }
2426
2427 preg = calloc(1, sizeof(regex_t));
2428 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2429 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2430 return -1;
2431 }
2432
2433 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2434 }
2435 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2436 regex_t *preg;
2437 if (curproxy == &defproxy) {
2438 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2439 return -1;
2440 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002441 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2442 return 0;
2443
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 if (*(args[1]) == 0) {
2445 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2446 return -1;
2447 }
2448
2449 preg = calloc(1, sizeof(regex_t));
2450 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2451 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2452 return -1;
2453 }
2454
2455 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2456 }
2457 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2458 regex_t *preg;
2459 if (curproxy == &defproxy) {
2460 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2461 return -1;
2462 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002463 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2464 return 0;
2465
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 if (*(args[1]) == 0) {
2467 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2468 return -1;
2469 }
2470
2471 preg = calloc(1, sizeof(regex_t));
2472 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2473 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2474 return -1;
2475 }
2476
2477 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2478 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002479 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2480 regex_t *preg;
2481 if (curproxy == &defproxy) {
2482 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2483 return -1;
2484 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002485 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2486 return 0;
2487
Willy Tarreaub8750a82006-09-03 09:56:00 +02002488 if (*(args[1]) == 0) {
2489 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2490 return -1;
2491 }
2492
2493 preg = calloc(1, sizeof(regex_t));
2494 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2495 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2496 return -1;
2497 }
2498
2499 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2502 if (curproxy == &defproxy) {
2503 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2504 return -1;
2505 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002506 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2507 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002508
2509 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2510 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2511 return 0;
2512 }
2513
2514 if (*(args[1]) == 0) {
2515 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2516 return -1;
2517 }
2518
2519 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2520 }
2521 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2522 regex_t *preg;
2523
2524 if (*(args[1]) == 0 || *(args[2]) == 0) {
2525 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2526 file, linenum, args[0]);
2527 return -1;
2528 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002529 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2530 return 0;
2531
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532 preg = calloc(1, sizeof(regex_t));
2533 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2534 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2535 return -1;
2536 }
2537
2538 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2539 if (err) {
2540 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2541 file, linenum, *err);
2542 return -1;
2543 }
2544 }
2545 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2546 regex_t *preg;
2547 if (curproxy == &defproxy) {
2548 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2549 return -1;
2550 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002551 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2552 return 0;
2553
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554 if (*(args[1]) == 0) {
2555 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2556 return -1;
2557 }
2558
2559 preg = calloc(1, sizeof(regex_t));
2560 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2561 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2562 return -1;
2563 }
2564
2565 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2566 if (err) {
2567 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2568 file, linenum, *err);
2569 return -1;
2570 }
2571 }
2572 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2573 regex_t *preg;
2574 if (curproxy == &defproxy) {
2575 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2576 return -1;
2577 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002578 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2579 return 0;
2580
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581 if (*(args[1]) == 0) {
2582 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2583 return -1;
2584 }
2585
2586 preg = calloc(1, sizeof(regex_t));
2587 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2588 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2589 return -1;
2590 }
2591
2592 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2593 if (err) {
2594 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2595 file, linenum, *err);
2596 return -1;
2597 }
2598 }
2599 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2600 regex_t *preg;
2601 if (curproxy == &defproxy) {
2602 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2603 return -1;
2604 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002605 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2606 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607
2608 if (*(args[1]) == 0 || *(args[2]) == 0) {
2609 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2610 file, linenum, args[0]);
2611 return -1;
2612 }
2613
2614 preg = calloc(1, sizeof(regex_t));
2615 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2616 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2617 return -1;
2618 }
2619
2620 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2621 if (err) {
2622 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2623 file, linenum, *err);
2624 return -1;
2625 }
2626 }
2627 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2628 regex_t *preg;
2629 if (curproxy == &defproxy) {
2630 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2631 return -1;
2632 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002633 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2634 return 0;
2635
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636 if (*(args[1]) == 0) {
2637 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2638 return -1;
2639 }
2640
2641 preg = calloc(1, sizeof(regex_t));
2642 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2643 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2644 return -1;
2645 }
2646
2647 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2648 if (err) {
2649 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2650 file, linenum, *err);
2651 return -1;
2652 }
2653 }
2654 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2655 regex_t *preg;
2656 if (curproxy == &defproxy) {
2657 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2658 return -1;
2659 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002660 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2661 return 0;
2662
Willy Tarreaubaaee002006-06-26 02:48:02 +02002663 if (*(args[1]) == 0) {
2664 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2665 return -1;
2666 }
2667
2668 preg = calloc(1, sizeof(regex_t));
2669 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2670 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2671 return -1;
2672 }
2673
2674 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2675 if (err) {
2676 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2677 file, linenum, *err);
2678 return -1;
2679 }
2680 }
2681 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2682 if (curproxy == &defproxy) {
2683 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2684 return -1;
2685 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002686 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2687 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002688
2689 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2690 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2691 return 0;
2692 }
2693
2694 if (*(args[1]) == 0) {
2695 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2696 return -1;
2697 }
2698
2699 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2700 }
2701 else if (!strcmp(args[0], "errorloc") ||
2702 !strcmp(args[0], "errorloc302") ||
2703 !strcmp(args[0], "errorloc303")) { /* error location */
2704 int errnum, errlen;
2705 char *err;
2706
Willy Tarreau977b8e42006-12-29 14:19:17 +01002707 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2708 return 0;
2709
Willy Tarreaubaaee002006-06-26 02:48:02 +02002710 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002711 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 return -1;
2713 }
2714
2715 errnum = atol(args[1]);
2716 if (!strcmp(args[0], "errorloc303")) {
2717 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2718 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2719 } else {
2720 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2721 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2722 }
2723
Willy Tarreau0f772532006-12-23 20:51:41 +01002724 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2725 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002726 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002727 curproxy->errmsg[rc].str = err;
2728 curproxy->errmsg[rc].len = errlen;
2729 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002730 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002732
2733 if (rc >= HTTP_ERR_SIZE) {
2734 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2735 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002736 free(err);
2737 }
2738 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002739 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2740 int errnum, errlen, fd;
2741 char *err;
2742 struct stat stat;
2743
2744 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2745 return 0;
2746
2747 if (*(args[2]) == 0) {
2748 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2749 return -1;
2750 }
2751
2752 fd = open(args[2], O_RDONLY);
2753 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2754 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2755 file, linenum, args[2], args[1]);
2756 if (fd >= 0)
2757 close(fd);
2758 return -1;
2759 }
2760
2761 if (stat.st_size <= BUFSIZE) {
2762 errlen = stat.st_size;
2763 } else {
2764 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2765 file, linenum, args[2], BUFSIZE);
2766 errlen = BUFSIZE;
2767 }
2768
2769 err = malloc(errlen); /* malloc() must succeed during parsing */
2770 errnum = read(fd, err, errlen);
2771 if (errnum != errlen) {
2772 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2773 file, linenum, args[2], args[1]);
2774 close(fd);
2775 free(err);
2776 return -1;
2777 }
2778 close(fd);
2779
2780 errnum = atol(args[1]);
2781 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2782 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002783 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002784 curproxy->errmsg[rc].str = err;
2785 curproxy->errmsg[rc].len = errlen;
2786 break;
2787 }
2788 }
2789
2790 if (rc >= HTTP_ERR_SIZE) {
2791 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2792 file, linenum, errnum);
2793 free(err);
2794 }
2795 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002796 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002797 struct cfg_kw_list *kwl;
2798 int index;
2799
2800 list_for_each_entry(kwl, &cfg_keywords.list, list) {
2801 for (index = 0; kwl->kw[index].kw != NULL; index++) {
2802 if (kwl->kw[index].section != CFG_LISTEN)
2803 continue;
2804 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
2805 /* prepare error message just in case */
2806 snprintf(trash, sizeof(trash),
2807 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02002808 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
2809 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002810 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2811 return -1;
2812 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02002813 else if (rc > 0) {
2814 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
2815 return 0;
2816 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02002817 return 0;
2818 }
2819 }
2820 }
2821
Willy Tarreau6daf3432008-01-22 16:44:08 +01002822 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823 return -1;
2824 }
2825 return 0;
2826}
2827
2828
2829/*
2830 * This function reads and parses the configuration file given in the argument.
2831 * returns 0 if OK, -1 if error.
2832 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002833int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002835 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002836 FILE *f;
2837 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002838 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 int confsect = CFG_NONE;
2840
2841 struct proxy *curproxy = NULL;
2842 struct server *newsrv = NULL;
2843
2844 if ((f=fopen(file,"r")) == NULL)
2845 return -1;
2846
2847 init_default_instance();
2848
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002849 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002850 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002851 char *end;
2852 char *args[MAX_LINE_ARGS + 1];
2853 char *line = thisline;
2854
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 linenum++;
2856
2857 end = line + strlen(line);
2858
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002859 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2860 /* Check if we reached the limit and the last char is not \n.
2861 * Watch out for the last line without the terminating '\n'!
2862 */
2863 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2864 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002865 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002866 }
2867
Willy Tarreaubaaee002006-06-26 02:48:02 +02002868 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002869 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 line++;
2871
2872 arg = 0;
2873 args[arg] = line;
2874
2875 while (*line && arg < MAX_LINE_ARGS) {
2876 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2877 * C equivalent value. Other combinations left unchanged (eg: \1).
2878 */
2879 if (*line == '\\') {
2880 int skip = 0;
2881 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2882 *line = line[1];
2883 skip = 1;
2884 }
2885 else if (line[1] == 'r') {
2886 *line = '\r';
2887 skip = 1;
2888 }
2889 else if (line[1] == 'n') {
2890 *line = '\n';
2891 skip = 1;
2892 }
2893 else if (line[1] == 't') {
2894 *line = '\t';
2895 skip = 1;
2896 }
2897 else if (line[1] == 'x') {
2898 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2899 unsigned char hex1, hex2;
2900 hex1 = toupper(line[2]) - '0';
2901 hex2 = toupper(line[3]) - '0';
2902 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2903 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2904 *line = (hex1<<4) + hex2;
2905 skip = 3;
2906 }
2907 else {
2908 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002909 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002910 }
2911 }
2912 if (skip) {
2913 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2914 end -= skip;
2915 }
2916 line++;
2917 }
2918 else if (*line == '#' || *line == '\n' || *line == '\r') {
2919 /* end of string, end of loop */
2920 *line = 0;
2921 break;
2922 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002923 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002924 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002925 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002926 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002927 line++;
2928 args[++arg] = line;
2929 }
2930 else {
2931 line++;
2932 }
2933 }
2934
2935 /* empty line */
2936 if (!**args)
2937 continue;
2938
Willy Tarreau540abe42007-05-02 20:50:16 +02002939 /* zero out remaining args and ensure that at least one entry
2940 * is zeroed out.
2941 */
2942 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002943 args[arg] = line;
2944 }
2945
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002946 if (!strcmp(args[0], "no")) {
2947 inv = 1;
2948 for (arg=0; *args[arg+1]; arg++)
2949 args[arg] = args[arg+1]; // shift args after inversion
2950 }
2951
2952 if (inv && strcmp(args[0], "option")) {
2953 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002954 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002955 }
2956
Willy Tarreau977b8e42006-12-29 14:19:17 +01002957 if (!strcmp(args[0], "listen") ||
2958 !strcmp(args[0], "frontend") ||
2959 !strcmp(args[0], "backend") ||
2960 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002961 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002962 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002963 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002964 cursection = strdup(args[0]);
2965 }
2966 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002968 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002969 cursection = strdup(args[0]);
2970 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 /* else it's a section keyword */
2972
2973 switch (confsect) {
2974 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002975 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002976 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002977 break;
2978 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002979 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002980 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002981 break;
2982 default:
2983 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002984 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002986 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002987 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002988 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 fclose(f);
2990
2991 /*
2992 * Now, check for the integrity of all that we have collected.
2993 */
2994
2995 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002996 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997
2998 if ((curproxy = proxy) == NULL) {
2999 Alert("parsing %s : no <listen> line. Nothing to do !\n",
3000 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003001 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003002 }
3003
3004 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003005 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003006 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003007
Willy Tarreaubaaee002006-06-26 02:48:02 +02003008 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003009 /* ensure we don't keep listeners uselessly bound */
3010 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003011 curproxy = curproxy->next;
3012 continue;
3013 }
3014
Willy Tarreau977b8e42006-12-29 14:19:17 +01003015 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
3016 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 +01003017 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018 cfgerr++;
3019 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003020 else if (curproxy->cap & PR_CAP_BE &&
3021 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01003022 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01003023 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01003024 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
3025 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 +01003026 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003027 cfgerr++;
3028 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003029
Willy Tarreau31682232007-11-29 15:38:04 +01003030 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003031 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003032 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003033 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003034 cfgerr++;
3035 }
3036#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
3037 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003038 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003039 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 cfgerr++;
3041 }
3042#endif
3043 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003044 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003045 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 }
3047 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003048
3049 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003051 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003052 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003053 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003055 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003056 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057 }
3058 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003059 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003060 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003062 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003063 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003064 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003065 }
Willy Tarreaudf366142007-11-30 16:23:20 +01003066 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01003067 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3068 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003069
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01003070 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003071 file, proxy_type_str(curproxy), curproxy->id);
3072 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003073 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003074
3075 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
3076 if ((newsrv = curproxy->srv) != NULL) {
3077 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
3078 file, proxy_type_str(curproxy), curproxy->id);
3079 }
3080 }
3081
3082 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
3084 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
3085 file, curproxy->id);
3086 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003087 }
3088 }
3089
Willy Tarreau82936582007-11-30 15:20:09 +01003090 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3091 curproxy->options &= ~PR_O_DISABLE404;
3092 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3093 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
3094 }
3095
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003096 /* if a default backend was specified, let's find it */
3097 if (curproxy->defbe.name) {
3098 struct proxy *target;
3099
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003100 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3101 if (!target) {
3102 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3103 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003104 cfgerr++;
3105 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003106 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3107 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003108 } else {
3109 free(curproxy->defbe.name);
3110 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003111 }
3112 }
3113
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003114 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003115 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3116 /* map jump target for ACT_SETBE in req_rep chain */
3117 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003118 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003119 struct proxy *target;
3120
Willy Tarreaua496b602006-12-17 23:15:24 +01003121 if (exp->action != ACT_SETBE)
3122 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003123
3124 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3125 if (!target) {
3126 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3127 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003128 cfgerr++;
3129 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003130 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3131 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003132 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003133 } else {
3134 free((void *)exp->replace);
3135 exp->replace = (const char *)target;
3136 }
3137 }
3138 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003139
3140 /* find the target proxy for 'use_backend' rules */
3141 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003142 struct proxy *target;
3143
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003144 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003145
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003146 if (!target) {
3147 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3148 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003149 cfgerr++;
3150 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003151 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3152 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003153 cfgerr++;
3154 } else {
3155 free((void *)rule->be.name);
3156 rule->be.backend = target;
3157 }
3158 }
3159
Willy Tarreau2738a142006-07-08 17:28:09 +02003160 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003161 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003162 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003163 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003164 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003165 " | While not properly invalid, you will certainly encounter various problems\n"
3166 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003167 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003168 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003169 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003170
Willy Tarreau1fa31262007-12-03 00:36:16 +01003171 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3172 * We must still support older configurations, so let's find out whether those
3173 * parameters have been set or must be copied from contimeouts.
3174 */
3175 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003176 if (!curproxy->timeout.tarpit ||
3177 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003178 /* tarpit timeout not set. We search in the following order:
3179 * default.tarpit, curr.connect, default.connect.
3180 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003181 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003182 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003183 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003184 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003185 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003186 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003187 }
3188 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003189 (!curproxy->timeout.queue ||
3190 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003191 /* queue timeout not set. We search in the following order:
3192 * default.queue, curr.connect, default.connect.
3193 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003194 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003195 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003196 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003197 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003198 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003199 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003200 }
3201 }
3202
Willy Tarreauf3c69202006-07-09 16:42:34 +02003203 if (curproxy->options & PR_O_SSL3_CHK) {
3204 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3205 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3206 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3207 }
3208
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003209 /* The small pools required for the capture lists */
3210 if (curproxy->nb_req_cap)
3211 curproxy->req_cap_pool = create_pool("ptrcap",
3212 curproxy->nb_req_cap * sizeof(char *),
3213 MEM_F_SHARED);
3214 if (curproxy->nb_rsp_cap)
3215 curproxy->rsp_cap_pool = create_pool("ptrcap",
3216 curproxy->nb_rsp_cap * sizeof(char *),
3217 MEM_F_SHARED);
3218
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003219 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3220 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3221 MEM_F_SHARED);
3222
Willy Tarreau86034312006-12-29 00:10:33 +01003223 /* for backwards compatibility with "listen" instances, if
3224 * fullconn is not set but maxconn is set, then maxconn
3225 * is used.
3226 */
3227 if (!curproxy->fullconn)
3228 curproxy->fullconn = curproxy->maxconn;
3229
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 /* first, we will invert the servers list order */
3231 newsrv = NULL;
3232 while (curproxy->srv) {
3233 struct server *next;
3234
3235 next = curproxy->srv->next;
3236 curproxy->srv->next = newsrv;
3237 newsrv = curproxy->srv;
3238 if (!next)
3239 break;
3240 curproxy->srv = next;
3241 }
3242
Willy Tarreau20697042007-11-15 23:26:18 +01003243 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003244 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245
Willy Tarreaub625a082007-11-26 01:15:43 +01003246 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003247 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003248 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003249 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3250 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003251 else
3252 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253
3254 if (curproxy->options & PR_O_LOGASAP)
3255 curproxy->to_log &= ~LW_BYTES;
3256
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003258 * ensure that we're not cross-dressing a TCP server into HTTP.
3259 */
3260 newsrv = curproxy->srv;
3261 while (newsrv != NULL) {
3262 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
3263 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3264 file, proxy_type_str(curproxy), curproxy->id, linenum);
3265 goto err;
3266 }
3267 newsrv = newsrv->next;
3268 }
3269
3270 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 * If this server supports a maxconn parameter, it needs a dedicated
3272 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003273 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274 */
3275 newsrv = curproxy->srv;
3276 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003277 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 /* Only 'minconn' was specified, or it was higher than or equal
3279 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3280 * this will avoid further useless expensive computations.
3281 */
3282 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003283 } else if (newsrv->maxconn && !newsrv->minconn) {
3284 /* minconn was not specified, so we set it to maxconn */
3285 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003286 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
3287 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003288 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003289 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 }
3291
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003292 if (newsrv->trackit) {
3293 struct proxy *px;
3294 struct server *srv;
3295 char *pname, *sname;
3296
3297 pname = newsrv->trackit;
3298 sname = strrchr(pname, '/');
3299
3300 if (sname)
3301 *sname++ = '\0';
3302 else {
3303 sname = pname;
3304 pname = NULL;
3305 }
3306
3307 if (pname) {
3308 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3309 if (!px) {
3310 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3311 file, proxy_type_str(curproxy), curproxy->id,
3312 newsrv->id, pname);
3313 return -1;
3314 }
3315 } else
3316 px = curproxy;
3317
3318 srv = findserver(px, sname);
3319 if (!srv) {
3320 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3321 file, proxy_type_str(curproxy), curproxy->id,
3322 newsrv->id, sname);
3323 return -1;
3324 }
3325
3326 if (!(srv->state & SRV_CHECKED)) {
3327 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3328 "tracing as it does not have checks enabled.\n",
3329 file, proxy_type_str(curproxy), curproxy->id,
3330 newsrv->id, px->id, srv->id);
3331 return -1;
3332 }
3333
3334 if (curproxy != px &&
3335 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3336 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3337 "tracing: disable-on-404 option inconsistency.\n",
3338 file, proxy_type_str(curproxy), curproxy->id,
3339 newsrv->id, px->id, srv->id);
3340 return -1;
3341 }
3342
3343 newsrv->tracked = srv;
3344 newsrv->tracknext = srv->tracknext;
3345 srv->tracknext = newsrv;
3346
3347 free(newsrv->trackit);
3348 }
3349
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 newsrv = newsrv->next;
3351 }
3352
Willy Tarreaue6b98942007-10-29 01:09:36 +01003353 /* adjust this proxy's listeners */
3354 listener = curproxy->listen;
3355 while (listener) {
3356 if (curproxy->options & PR_O_TCP_NOLING)
3357 listener->options |= LI_O_NOLINGER;
3358 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003359 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003360 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003361 listener->accept = event_accept;
3362 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003363 listener->handler = process_session;
3364
3365 if (curproxy->mode == PR_MODE_HTTP)
3366 listener->analysers |= AN_REQ_HTTP_HDR;
3367
3368 if (curproxy->tcp_req.inspect_delay)
3369 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003370
3371 listener = listener->next;
3372 }
3373
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 curproxy = curproxy->next;
3375 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003376
Willy Tarreaubaaee002006-06-26 02:48:02 +02003377 if (cfgerr > 0) {
3378 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003379 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003380 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003381
3382 /*
3383 * Recount currently required checks.
3384 */
3385
3386 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3387 int optnum;
3388
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003389 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3390 if (curproxy->options & cfg_opts[optnum].val)
3391 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003392
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003393 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3394 if (curproxy->options2 & cfg_opts2[optnum].val)
3395 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003396 }
3397
Willy Tarreaua534fea2008-08-03 12:19:50 +02003398 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003399 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003400 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003401
3402 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003403 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003404 cursection = NULL;
3405 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406}
3407
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003408/*
3409 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3410 * parsing sessions.
3411 */
3412void cfg_register_keywords(struct cfg_kw_list *kwl)
3413{
3414 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3415}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003417/*
3418 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3419 */
3420void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3421{
3422 LIST_DEL(&kwl->list);
3423 LIST_INIT(&kwl->list);
3424}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003425
3426/*
3427 * Local variables:
3428 * c-indent-level: 8
3429 * c-basic-offset: 8
3430 * End:
3431 */