blob: 13b0e36931a46720ae8e6dfee6347e218eb5f6e9 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau0b4ed902007-03-26 00:18:40 +02004 * Copyright 2000-2007 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 Tarreau0f772532006-12-23 20:51:41 +010035#include <types/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <types/polling.h>
37#include <types/proxy.h>
38#include <types/queue.h>
39
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010045#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020046#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010047#include <proto/protocols.h>
48#include <proto/proto_tcp.h>
49#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010050#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/server.h>
52#include <proto/task.h>
53
54
Willy Tarreauf3c69202006-07-09 16:42:34 +020055/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
56 * ssl-hello-chk option to ensure that the remote server speaks SSL.
57 *
58 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
59 */
60const char sslv3_client_hello_pkt[] = {
61 "\x16" /* ContentType : 0x16 = Hanshake */
62 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
63 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
64 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
65 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
66 "\x03\x00" /* Hello Version : 0x0300 = v3 */
67 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
68 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
69 "\x00" /* Session ID length : empty (no session ID) */
70 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
71 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
72 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
73 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
74 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
75 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
76 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
77 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
78 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
79 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
80 "\x00\x38" "\x00\x39" "\x00\x3A"
81 "\x01" /* Compression Length : 0x01 = 1 byte for types */
82 "\x00" /* Compression Type : 0x00 = NULL compression */
83};
84
Willy Tarreau13943ab2006-12-31 00:24:10 +010085/* some of the most common options which are also the easiest to handle */
86static const struct {
87 const char *name;
88 unsigned int val;
89 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010090 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010091} cfg_opts[] =
92{
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
112 { "transparent", PR_O_TRANSP, PR_CAP_FE, 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 Tarreaubaaee002006-06-26 02:48:02 +0200118
Willy Tarreau6daf3432008-01-22 16:44:08 +0100119static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200120static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
121int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
122int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
123
124/*
125 * converts <str> to a list of listeners which are dynamically allocated.
126 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
127 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
128 * - <port> is a numerical port from 1 to 65535 ;
129 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
130 * This can be repeated as many times as necessary, separated by a coma.
131 * The <tail> argument is a pointer to a current list which should be appended
132 * to the tail of the new list. The pointer to the new list is returned.
133 */
134static struct listener *str2listener(char *str, struct listener *tail)
135{
136 struct listener *l;
137 char *c, *next, *range, *dupstr;
138 int port, end;
139
140 next = dupstr = strdup(str);
141
142 while (next && *next) {
143 struct sockaddr_storage ss;
144
145 str = next;
146 /* 1) look for the end of the first address */
147 if ((next = strrchr(str, ',')) != NULL) {
148 *next++ = 0;
149 }
150
151 /* 2) look for the addr/port delimiter, it's the last colon. */
152 if ((range = strrchr(str, ':')) == NULL) {
153 Alert("Missing port number: '%s'\n", str);
154 goto fail;
155 }
156
157 *range++ = 0;
158
159 if (strrchr(str, ':') != NULL) {
160 /* IPv6 address contains ':' */
161 memset(&ss, 0, sizeof(ss));
162 ss.ss_family = AF_INET6;
163
164 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
165 Alert("Invalid server address: '%s'\n", str);
166 goto fail;
167 }
168 }
169 else {
170 memset(&ss, 0, sizeof(ss));
171 ss.ss_family = AF_INET;
172
173 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
174 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
175 }
176 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
177 struct hostent *he;
178
179 if ((he = gethostbyname(str)) == NULL) {
180 Alert("Invalid server name: '%s'\n", str);
181 goto fail;
182 }
183 else
184 ((struct sockaddr_in *)&ss)->sin_addr =
185 *(struct in_addr *) *(he->h_addr_list);
186 }
187 }
188
189 /* 3) look for the port-end delimiter */
190 if ((c = strchr(range, '-')) != NULL) {
191 *c++ = 0;
192 end = atol(c);
193 }
194 else {
195 end = atol(range);
196 }
197
198 port = atol(range);
199
200 if (port < 1 || port > 65535) {
201 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
202 goto fail;
203 }
204
205 if (end < 1 || end > 65535) {
206 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
207 goto fail;
208 }
209
210 for (; port <= end; port++) {
211 l = (struct listener *)calloc(1, sizeof(struct listener));
212 l->next = tail;
213 tail = l;
214
215 l->fd = -1;
216 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100217 l->state = LI_INIT;
218
219 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100221 tcpv6_add_listener(l);
222 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100224 tcpv4_add_listener(l);
225 }
226 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 } /* end for(port) */
228 } /* end while(next) */
229 free(dupstr);
230 return tail;
231 fail:
232 free(dupstr);
233 return NULL;
234}
235
Willy Tarreau977b8e42006-12-29 14:19:17 +0100236/*
237 * Sends a warning if proxy <proxy> does not have at least one of the
238 * capabilities in <cap>. An optionnal <hint> may be added at the end
239 * of the warning to help the user. Returns 1 if a warning was emitted
240 * or 0 if the condition is valid.
241 */
242int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
243{
244 char *msg;
245
246 switch (cap) {
247 case PR_CAP_BE: msg = "no backend"; break;
248 case PR_CAP_FE: msg = "no frontend"; break;
249 case PR_CAP_RS: msg = "no ruleset"; break;
250 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
251 default: msg = "not enough"; break;
252 }
253
254 if (!(proxy->cap & cap)) {
255 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100256 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100257 return 1;
258 }
259 return 0;
260}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261
262/*
263 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
264 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100265int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266{
267
268 if (!strcmp(args[0], "global")) { /* new section */
269 /* no option, nothing special to do */
270 return 0;
271 }
272 else if (!strcmp(args[0], "daemon")) {
273 global.mode |= MODE_DAEMON;
274 }
275 else if (!strcmp(args[0], "debug")) {
276 global.mode |= MODE_DEBUG;
277 }
278 else if (!strcmp(args[0], "noepoll")) {
279 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
280 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200281 else if (!strcmp(args[0], "nosepoll")) {
282 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
283 }
284 else if (!strcmp(args[0], "nokqueue")) {
285 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
286 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200287 else if (!strcmp(args[0], "nopoll")) {
288 cfg_polling_mechanism &= ~POLL_USE_POLL;
289 }
290 else if (!strcmp(args[0], "quiet")) {
291 global.mode |= MODE_QUIET;
292 }
293 else if (!strcmp(args[0], "stats")) {
Willy Tarreaufbee7132007-10-18 13:53:22 +0200294 memcpy(trash, "error near 'stats'", 19);
295 if (stats_parse_global((const char **)args + 1, trash, sizeof(trash)) < 0) {
296 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
297 return -1;
298 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200300 else if (!strcmp(args[0], "tune.maxpollevents")) {
301 if (global.tune.maxpollevents != 0) {
302 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
303 return 0;
304 }
305 if (*(args[1]) == 0) {
306 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
307 return -1;
308 }
309 global.tune.maxpollevents = atol(args[1]);
310 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100311 else if (!strcmp(args[0], "tune.maxaccept")) {
312 if (global.tune.maxaccept != 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.maxaccept = atol(args[1]);
321 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200322 else if (!strcmp(args[0], "uid")) {
323 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200324 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200325 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.uid = atol(args[1]);
332 }
333 else if (!strcmp(args[0], "gid")) {
334 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200335 Alert("parsing [%s:%d] : group/gid 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.gid = atol(args[1]);
343 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200344 /* user/group name handling */
345 else if (!strcmp(args[0], "user")) {
346 struct passwd *ha_user;
347 if (global.uid != 0) {
348 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
349 return 0;
350 }
351 errno = 0;
352 ha_user = getpwnam(args[1]);
353 if (ha_user != NULL) {
354 global.uid = (int)ha_user->pw_uid;
355 }
356 else {
357 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
358 exit(1);
359 }
360 }
361 else if (!strcmp(args[0], "group")) {
362 struct group *ha_group;
363 if (global.gid != 0) {
364 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
365 return 0;
366 }
367 errno = 0;
368 ha_group = getgrnam(args[1]);
369 if (ha_group != NULL) {
370 global.gid = (int)ha_group->gr_gid;
371 }
372 else {
373 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
374 exit(1);
375 }
376 }
377 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200378 else if (!strcmp(args[0], "nbproc")) {
379 if (global.nbproc != 0) {
380 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
381 return 0;
382 }
383 if (*(args[1]) == 0) {
384 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
385 return -1;
386 }
387 global.nbproc = atol(args[1]);
388 }
389 else if (!strcmp(args[0], "maxconn")) {
390 if (global.maxconn != 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.maxconn = atol(args[1]);
399#ifdef SYSTEM_MAXCONN
400 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
401 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);
402 global.maxconn = DEFAULT_MAXCONN;
403 }
404#endif /* SYSTEM_MAXCONN */
405 }
406 else if (!strcmp(args[0], "ulimit-n")) {
407 if (global.rlimit_nofile != 0) {
408 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
409 return 0;
410 }
411 if (*(args[1]) == 0) {
412 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
413 return -1;
414 }
415 global.rlimit_nofile = atol(args[1]);
416 }
417 else if (!strcmp(args[0], "chroot")) {
418 if (global.chroot != NULL) {
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 a directory as an argument.\n", file, linenum, args[0]);
424 return -1;
425 }
426 global.chroot = strdup(args[1]);
427 }
428 else if (!strcmp(args[0], "pidfile")) {
429 if (global.pidfile != NULL) {
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 a file name as an argument.\n", file, linenum, args[0]);
435 return -1;
436 }
437 global.pidfile = strdup(args[1]);
438 }
439 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100440 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200441 int facility, level;
442
443 if (*(args[1]) == 0 || *(args[2]) == 0) {
444 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
445 return -1;
446 }
447
448 facility = get_log_facility(args[2]);
449 if (facility < 0) {
450 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
451 exit(1);
452 }
453
454 level = 7; /* max syslog level = debug */
455 if (*(args[3])) {
456 level = get_log_level(args[3]);
457 if (level < 0) {
458 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
459 exit(1);
460 }
461 }
462
Robert Tsai81ae1952007-12-05 10:47:29 +0100463 if (args[1][0] == '/') {
464 logsrv.u.addr.sa_family = AF_UNIX;
465 logsrv.u.un = *str2sun(args[1]);
466 } else {
467 logsrv.u.addr.sa_family = AF_INET;
468 logsrv.u.in = *str2sa(args[1]);
469 if (!logsrv.u.in.sin_port)
470 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200472
473 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100474 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 global.logfac1 = facility;
476 global.loglev1 = level;
477 }
478 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100479 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200480 global.logfac2 = facility;
481 global.loglev2 = level;
482 }
483 else {
484 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
485 return -1;
486 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200487 }
488 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
489 if (global.spread_checks != 0) {
490 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
491 return 0;
492 }
493 if (*(args[1]) == 0) {
494 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
495 return -1;
496 }
497 global.spread_checks = atol(args[1]);
498 if (global.spread_checks < 0 || global.spread_checks > 50) {
499 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
500 return -1;
501 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200502 }
503 else {
504 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
505 return -1;
506 }
507 return 0;
508}
509
510
511static void init_default_instance()
512{
513 memset(&defproxy, 0, sizeof(defproxy));
514 defproxy.mode = PR_MODE_TCP;
515 defproxy.state = PR_STNEW;
516 defproxy.maxconn = cfg_maxpconn;
517 defproxy.conn_retries = CONN_RETRIES;
518 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100519 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520}
521
522/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100523 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
524 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200525 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100526int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527{
528 static struct proxy *curproxy = NULL;
529 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200530 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100531 int rc;
532 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200533
Willy Tarreau977b8e42006-12-29 14:19:17 +0100534 if (!strcmp(args[0], "listen"))
535 rc = PR_CAP_LISTEN;
536 else if (!strcmp(args[0], "frontend"))
537 rc = PR_CAP_FE | PR_CAP_RS;
538 else if (!strcmp(args[0], "backend"))
539 rc = PR_CAP_BE | PR_CAP_RS;
540 else if (!strcmp(args[0], "ruleset"))
541 rc = PR_CAP_RS;
542 else
543 rc = PR_CAP_NONE;
544
545 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 if (!*args[1]) {
547 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
548 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
549 file, linenum, args[0]);
550 return -1;
551 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200552
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100553 err = invalid_char(args[1]);
554 if (err) {
555 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
556 file, linenum, *err, args[0], args[1]);
557 return -1;
558 }
559
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200560 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
561 /*
562 * If there are two proxies with the same name only following
563 * combinations are allowed:
564 *
565 * listen backend frontend ruleset
566 * listen - - - -
567 * backend - - OK -
568 * frontend - OK - -
569 * ruleset - - - -
570 */
571
572 if (!strcmp(curproxy->id, args[1]) &&
573 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
574 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100575 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
576 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200577 }
578 }
579
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
581 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
582 return -1;
583 }
584
585 curproxy->next = proxy;
586 proxy = curproxy;
587 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200588 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200589 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100590 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200591 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200592
Willy Tarreauee991362007-05-14 14:37:50 +0200593 /* Timeouts are defined as -1, so we cannot use the zeroed area
594 * as a default value.
595 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100596 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200597
598 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100600 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601
602 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100603 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604 curproxy->listen = str2listener(args[2], curproxy->listen);
605 if (!curproxy->listen)
606 return -1;
607 global.maxsock++;
608 }
609
610 /* set default values */
611 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 curproxy->options = defproxy.options;
Willy Tarreau31682232007-11-29 15:38:04 +0100613 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200614 curproxy->except_net = defproxy.except_net;
615 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616
Willy Tarreau977b8e42006-12-29 14:19:17 +0100617 if (curproxy->cap & PR_CAP_FE) {
618 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100619 curproxy->backlog = defproxy.backlog;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100620
621 /* initialize error relocations */
622 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
623 if (defproxy.errmsg[rc].str)
624 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
625 }
626
627 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629
Willy Tarreau977b8e42006-12-29 14:19:17 +0100630 if (curproxy->cap & PR_CAP_BE) {
631 curproxy->fullconn = defproxy.fullconn;
632 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633
Willy Tarreau977b8e42006-12-29 14:19:17 +0100634 if (defproxy.check_req)
635 curproxy->check_req = strdup(defproxy.check_req);
636 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200637
Willy Tarreau977b8e42006-12-29 14:19:17 +0100638 if (defproxy.cookie_name)
639 curproxy->cookie_name = strdup(defproxy.cookie_name);
640 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100641
642 if (defproxy.url_param_name)
643 curproxy->url_param_name = strdup(defproxy.url_param_name);
644 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100645 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646
Willy Tarreau977b8e42006-12-29 14:19:17 +0100647 if (curproxy->cap & PR_CAP_RS) {
648 if (defproxy.capture_name)
649 curproxy->capture_name = strdup(defproxy.capture_name);
650 curproxy->capture_namelen = defproxy.capture_namelen;
651 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200653
Willy Tarreau977b8e42006-12-29 14:19:17 +0100654 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100655 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100656 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100657 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100658 curproxy->uri_auth = defproxy.uri_auth;
659 curproxy->mon_net = defproxy.mon_net;
660 curproxy->mon_mask = defproxy.mon_mask;
661 if (defproxy.monitor_uri)
662 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
663 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100664 if (defproxy.defbe.name)
665 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100666 }
667
668 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100669 curproxy->timeout.connect = defproxy.timeout.connect;
670 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100671 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100672 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100673 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100674 curproxy->source_addr = defproxy.source_addr;
675 }
676
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 curproxy->mode = defproxy.mode;
678 curproxy->logfac1 = defproxy.logfac1;
679 curproxy->logsrv1 = defproxy.logsrv1;
680 curproxy->loglev1 = defproxy.loglev1;
681 curproxy->logfac2 = defproxy.logfac2;
682 curproxy->logsrv2 = defproxy.logsrv2;
683 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200684 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100685 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
686 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200687
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 return 0;
689 }
690 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
691 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100692 /* FIXME-20070101: we should do this too at the end of the
693 * config parsing to free all default values.
694 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200695 if (defproxy.check_req) free(defproxy.check_req);
696 if (defproxy.cookie_name) free(defproxy.cookie_name);
Willy Tarreau01732802007-11-01 22:48:15 +0100697 if (defproxy.url_param_name) free(defproxy.url_param_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200699 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100700 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100701
702 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
703 if (defproxy.errmsg[rc].len)
704 free(defproxy.errmsg[rc].str);
705 }
706
Willy Tarreaubaaee002006-06-26 02:48:02 +0200707 /* we cannot free uri_auth because it might already be used */
708 init_default_instance();
709 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100710 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 return 0;
712 }
713 else if (curproxy == NULL) {
714 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
715 return -1;
716 }
717
Willy Tarreau977b8e42006-12-29 14:19:17 +0100718
719 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200720 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100721 struct listener *last_listen;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200722 if (curproxy == &defproxy) {
723 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
724 return -1;
725 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100726 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
727 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200728
729 if (strchr(args[1], ':') == NULL) {
730 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
731 file, linenum, args[0]);
732 return -1;
733 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100734
735 last_listen = curproxy->listen;
736 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200737 if (!curproxy->listen)
738 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100739 if (*args[2]) {
740#ifdef CONFIG_HAP_LINUX_TPROXY
741 if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */
742 struct listener *l;
743
744 for (l = curproxy->listen; l != last_listen; l = l->next)
745 l->options |= LI_O_FOREIGN;
746 }
747 else {
748 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n",
749 file, linenum, args[0]);
750 return -1;
751 }
752#else
753 Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n",
754 file, linenum, args[0]);
755 return -1;
756#endif
757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200758 global.maxsock++;
759 return 0;
760 }
761 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
762 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
763 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
764 file, linenum, args[0]);
765 return -1;
766 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100767 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
768 return 0;
769
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 /* flush useless bits */
771 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
772 return 0;
773 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200774 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100775 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
776 return 0;
777
Willy Tarreau1c47f852006-07-09 08:22:27 +0200778 if (!*args[1]) {
779 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
780 file, linenum, args[0]);
781 return -1;
782 }
783
784 if (curproxy->monitor_uri != NULL)
785 free(curproxy->monitor_uri);
786
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100787 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200788 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100789 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200790 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
791
792 return 0;
793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200794 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
795 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
796 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
797 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
798 else {
799 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
800 return -1;
801 }
802 }
803 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
804 curproxy->state = PR_STSTOPPED;
805 }
806 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
807 curproxy->state = PR_STNEW;
808 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200809 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100810 err = invalid_char(args[1]);
811 if (err) {
812 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
813 file, linenum, *err, args[1]);
814 return -1;
815 }
816
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200817 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
818 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
819 file, linenum, args[1]);
820 return -1;
821 }
822 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823 else if (!strcmp(args[0], "cookie")) { /* cookie name */
824 int cur_arg;
825 // if (curproxy == &defproxy) {
826 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
827 // return -1;
828 // }
829
Willy Tarreau977b8e42006-12-29 14:19:17 +0100830 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
831 return 0;
832
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 if (curproxy->cookie_name != NULL) {
834 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
835 // file, linenum);
836 // return 0;
837 free(curproxy->cookie_name);
838 }
839
840 if (*(args[1]) == 0) {
841 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
842 file, linenum, args[0]);
843 return -1;
844 }
845 curproxy->cookie_name = strdup(args[1]);
846 curproxy->cookie_len = strlen(curproxy->cookie_name);
847
848 cur_arg = 2;
849 while (*(args[cur_arg])) {
850 if (!strcmp(args[cur_arg], "rewrite")) {
851 curproxy->options |= PR_O_COOK_RW;
852 }
853 else if (!strcmp(args[cur_arg], "indirect")) {
854 curproxy->options |= PR_O_COOK_IND;
855 }
856 else if (!strcmp(args[cur_arg], "insert")) {
857 curproxy->options |= PR_O_COOK_INS;
858 }
859 else if (!strcmp(args[cur_arg], "nocache")) {
860 curproxy->options |= PR_O_COOK_NOC;
861 }
862 else if (!strcmp(args[cur_arg], "postonly")) {
863 curproxy->options |= PR_O_COOK_POST;
864 }
865 else if (!strcmp(args[cur_arg], "prefix")) {
866 curproxy->options |= PR_O_COOK_PFX;
867 }
868 else {
869 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
870 file, linenum, args[0]);
871 return -1;
872 }
873 cur_arg++;
874 }
875 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
876 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
877 file, linenum);
878 return -1;
879 }
880
881 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
882 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
883 file, linenum);
884 return -1;
885 }
886 }/* end else if (!strcmp(args[0], "cookie")) */
887 else if (!strcmp(args[0], "appsession")) { /* cookie name */
888 // if (curproxy == &defproxy) {
889 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
890 // return -1;
891 // }
892
Willy Tarreau977b8e42006-12-29 14:19:17 +0100893 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
894 return 0;
895
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896 if (curproxy->appsession_name != NULL) {
897 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
898 // file, linenum);
899 // return 0;
900 free(curproxy->appsession_name);
901 }
902
903 if (*(args[5]) == 0) {
904 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
905 file, linenum, args[0]);
906 return -1;
907 }
908 have_appsession = 1;
909 curproxy->appsession_name = strdup(args[1]);
910 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
911 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100912 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
913 if (err) {
914 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
915 file, linenum, *err, args[0]);
916 return -1;
917 }
Willy Tarreauee991362007-05-14 14:37:50 +0200918 if (val > 0)
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100919 __tv_from_ms(&curproxy->timeout.appsession, val);
Willy Tarreauee991362007-05-14 14:37:50 +0200920 else
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100921 tv_eternity(&curproxy->timeout.appsession);
Willy Tarreauee991362007-05-14 14:37:50 +0200922
Willy Tarreau51041c72007-09-09 21:56:53 +0200923 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
924 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200925 return -1;
926 }
927 } /* Url App Session */
928 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100929 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
930 return 0;
931
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
933 // if (curproxy == &defproxy) {
934 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
935 // return -1;
936 // }
937
938 if (curproxy->capture_name != NULL) {
939 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
940 // file, linenum, args[0]);
941 // return 0;
942 free(curproxy->capture_name);
943 }
944
945 if (*(args[4]) == 0) {
946 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
947 file, linenum, args[0]);
948 return -1;
949 }
950 curproxy->capture_name = strdup(args[2]);
951 curproxy->capture_namelen = strlen(curproxy->capture_name);
952 curproxy->capture_len = atol(args[4]);
953 if (curproxy->capture_len >= CAPTURE_LEN) {
954 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
955 file, linenum, CAPTURE_LEN - 1);
956 curproxy->capture_len = CAPTURE_LEN - 1;
957 }
958 curproxy->to_log |= LW_COOKIE;
959 }
960 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
961 struct cap_hdr *hdr;
962
963 if (curproxy == &defproxy) {
964 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
965 return -1;
966 }
967
968 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
969 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
970 file, linenum, args[0], args[1]);
971 return -1;
972 }
973
974 hdr = calloc(sizeof(struct cap_hdr), 1);
975 hdr->next = curproxy->req_cap;
976 hdr->name = strdup(args[3]);
977 hdr->namelen = strlen(args[3]);
978 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200979 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 hdr->index = curproxy->nb_req_cap++;
981 curproxy->req_cap = hdr;
982 curproxy->to_log |= LW_REQHDR;
983 }
984 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
985 struct cap_hdr *hdr;
986
987 if (curproxy == &defproxy) {
988 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
989 return -1;
990 }
991
992 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
993 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
994 file, linenum, args[0], args[1]);
995 return -1;
996 }
997 hdr = calloc(sizeof(struct cap_hdr), 1);
998 hdr->next = curproxy->rsp_cap;
999 hdr->name = strdup(args[3]);
1000 hdr->namelen = strlen(args[3]);
1001 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001002 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001003 hdr->index = curproxy->nb_rsp_cap++;
1004 curproxy->rsp_cap = hdr;
1005 curproxy->to_log |= LW_RSPHDR;
1006 }
1007 else {
1008 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1009 file, linenum, args[0]);
1010 return -1;
1011 }
1012 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001013 else if (!strcmp(args[0], "contimeout") || !strcmp(args[0], "clitimeout") ||
1014 !strcmp(args[0], "srvtimeout") || !strcmp(args[0], "timeout")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001015
Willy Tarreaue219db72007-12-03 01:30:13 +01001016 /* either we have {con|srv|cli}timeout <value> or we have the
1017 * new form: timeout <type> <value>. The parser needs the word
1018 * preceeding the value.
1019 */
1020 const char **start_arg = (const char **)args;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001021
Willy Tarreaue219db72007-12-03 01:30:13 +01001022 if (strcmp(args[0], "timeout") == 0)
1023 start_arg++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001024
Willy Tarreaue219db72007-12-03 01:30:13 +01001025 snprintf(trash, sizeof(trash), "error near '%s'", args[0]);
1026 rc = proxy_parse_timeout(start_arg, curproxy, &defproxy, trash, sizeof(trash));
1027 if (rc < 0) {
1028 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001029 return -1;
1030 }
Willy Tarreaue219db72007-12-03 01:30:13 +01001031 if (rc > 0)
1032 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001033 }
1034 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001035 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1036 return 0;
1037
Willy Tarreaubaaee002006-06-26 02:48:02 +02001038 if (*(args[1]) == 0) {
1039 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1040 file, linenum, args[0]);
1041 return -1;
1042 }
1043 curproxy->conn_retries = atol(args[1]);
1044 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001045 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1046 int pol = ACL_COND_NONE;
1047 struct acl_cond *cond;
1048
1049 if (!strcmp(args[1], "if"))
1050 pol = ACL_COND_IF;
1051 else if (!strcmp(args[1], "unless"))
1052 pol = ACL_COND_UNLESS;
1053
1054 if (pol == ACL_COND_NONE) {
1055 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1056 file, linenum, args[0]);
1057 return -1;
1058 }
1059
1060 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1061 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1062 file, linenum);
1063 return -1;
1064 }
1065 LIST_ADDQ(&curproxy->block_cond, &cond->list);
1066 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02001067 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1068 int pol = ACL_COND_NONE;
1069 struct acl_cond *cond;
1070 struct switching_rule *rule;
1071
1072 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1073 return 0;
1074
1075 if (*(args[1]) == 0) {
1076 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1077 return -1;
1078 }
1079
1080 if (!strcmp(args[2], "if"))
1081 pol = ACL_COND_IF;
1082 else if (!strcmp(args[2], "unless"))
1083 pol = ACL_COND_UNLESS;
1084
1085 if (pol == ACL_COND_NONE) {
1086 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1087 file, linenum, args[0]);
1088 return -1;
1089 }
1090
1091 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1092 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1093 file, linenum);
1094 return -1;
1095 }
1096
1097 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1098 rule->cond = cond;
1099 rule->be.name = strdup(args[1]);
1100 LIST_INIT(&rule->list);
1101 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1102 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001104 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1105 return 0;
1106
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1108 curproxy->uri_auth = NULL; /* we must detach from the default config */
1109
1110 if (*(args[1]) == 0) {
1111 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1112 return -1;
1113 } else if (!strcmp(args[1], "uri")) {
1114 if (*(args[2]) == 0) {
1115 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1116 return -1;
1117 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1118 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1119 return -1;
1120 }
1121 } else if (!strcmp(args[1], "realm")) {
1122 if (*(args[2]) == 0) {
1123 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1124 return -1;
1125 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1126 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1127 return -1;
1128 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001129 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001130 unsigned interval;
1131
1132 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1133 if (err) {
1134 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1135 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001136 return -1;
1137 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1138 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1139 return -1;
1140 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 } else if (!strcmp(args[1], "auth")) {
1142 if (*(args[2]) == 0) {
1143 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1144 return -1;
1145 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1146 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1147 return -1;
1148 }
1149 } else if (!strcmp(args[1], "scope")) {
1150 if (*(args[2]) == 0) {
1151 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1152 return -1;
1153 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1154 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1155 return -1;
1156 }
1157 } else if (!strcmp(args[1], "enable")) {
1158 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1159 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1160 return -1;
1161 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001162 } else if (!strcmp(args[1], "hide-version")) {
1163 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1164 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1165 return -1;
1166 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001168 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169 file, linenum, args[0]);
1170 return -1;
1171 }
1172 }
1173 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001174 int optnum;
1175
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001176 if (*(args[1]) == '\0') {
1177 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1178 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001179 return -1;
1180 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001181
1182 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1183 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1184 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1185 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001186
1187 if (!inv)
1188 curproxy->options |= cfg_opts[optnum].val;
1189 else
1190 curproxy->options &= ~cfg_opts[optnum].val;
1191
Willy Tarreau13943ab2006-12-31 00:24:10 +01001192 return 0;
1193 }
1194 }
1195
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001196 if (inv) {
1197 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1198 file, linenum, args[1]);
1199 return -1;
1200 }
1201
Willy Tarreau13943ab2006-12-31 00:24:10 +01001202 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 /* generate a complete HTTP log */
1204 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1205 else if (!strcmp(args[1], "tcplog"))
1206 /* generate a detailed TCP log */
1207 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001208 else if (!strcmp(args[1], "tcpka")) {
1209 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001210 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1211 return 0;
1212
1213 if (curproxy->cap & PR_CAP_FE)
1214 curproxy->options |= PR_O_TCP_CLI_KA;
1215 if (curproxy->cap & PR_CAP_BE)
1216 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 }
1218 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001219 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1220 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001221 /* use HTTP request to check servers' health */
1222 if (curproxy->check_req != NULL) {
1223 free(curproxy->check_req);
1224 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001225 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001226 curproxy->options &= ~PR_O_SMTP_CHK;
1227 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 if (!*args[2]) { /* no argument */
1229 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1230 curproxy->check_len = strlen(DEF_CHECK_REQ);
1231 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001232 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001233 curproxy->check_req = (char *)malloc(reqlen);
1234 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1235 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1236 } else { /* more arguments : METHOD URI [HTTP_VER] */
1237 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1238 if (*args[4])
1239 reqlen += strlen(args[4]);
1240 else
1241 reqlen += strlen("HTTP/1.0");
1242
1243 curproxy->check_req = (char *)malloc(reqlen);
1244 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1245 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1246 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001247 }
1248 else if (!strcmp(args[1], "ssl-hello-chk")) {
1249 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001250 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1251 return 0;
1252
Willy Tarreauf3c69202006-07-09 16:42:34 +02001253 if (curproxy->check_req != NULL) {
1254 free(curproxy->check_req);
1255 }
1256 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001257 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001258 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001259 }
Willy Tarreau23677902007-05-08 23:50:35 +02001260 else if (!strcmp(args[1], "smtpchk")) {
1261 /* use SMTP request to check servers' health */
1262 if (curproxy->check_req != NULL) {
1263 free(curproxy->check_req);
1264 }
1265 curproxy->options &= ~PR_O_HTTP_CHK;
1266 curproxy->options &= ~PR_O_SSL3_CHK;
1267 curproxy->options |= PR_O_SMTP_CHK;
1268
1269 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1270 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1271 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1272 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1273 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1274 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1275 curproxy->check_req = (char *)malloc(reqlen);
1276 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1277 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1278 } else {
1279 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1280 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1281 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1282 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1283 }
1284 }
1285 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001286 else if (!strcmp(args[1], "forwardfor")) {
1287 /* insert x-forwarded-for field, but not for the
1288 * IP address listed as an except.
1289 */
1290 if (*(args[2])) {
1291 if (!strcmp(args[2], "except")) {
1292 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1293 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1294 file, linenum, args[0]);
1295 return -1;
1296 }
1297 /* flush useless bits */
1298 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1299 } else {
1300 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1301 file, linenum, args[0]);
1302 return -1;
1303 }
1304 }
1305 curproxy->options |= PR_O_FWDFOR;
1306 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001307 else {
1308 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1309 return -1;
1310 }
1311 return 0;
1312 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001313 else if (!strcmp(args[0], "default_backend")) {
1314 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 if (curproxy->defbe.name)
1322 free(curproxy->defbe.name);
1323 curproxy->defbe.name = strdup(args[1]);
1324 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001325 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001326 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1327 return 0;
1328
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001329 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1330 file, linenum, args[0]);
1331
Willy Tarreaubaaee002006-06-26 02:48:02 +02001332 /* enable reconnections to dispatch */
1333 curproxy->options |= PR_O_REDISP;
1334 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001335 else if (!strcmp(args[0], "http-check")) {
1336 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1337 return 0;
1338
1339 if (strcmp(args[1], "disable-on-404") == 0) {
1340 /* enable a graceful server shutdown on an HTTP 404 response */
1341 curproxy->options |= PR_O_DISABLE404;
1342 }
1343 else {
1344 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1345 return -1;
1346 }
1347 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001348 else if (!strcmp(args[0], "monitor")) {
1349 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1350 return 0;
1351
1352 if (strcmp(args[1], "fail") == 0) {
1353 /* add a condition to fail monitor requests */
1354 int pol = ACL_COND_NONE;
1355 struct acl_cond *cond;
1356
1357 if (!strcmp(args[2], "if"))
1358 pol = ACL_COND_IF;
1359 else if (!strcmp(args[2], "unless"))
1360 pol = ACL_COND_UNLESS;
1361
1362 if (pol == ACL_COND_NONE) {
1363 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1364 file, linenum, args[0], args[1]);
1365 return -1;
1366 }
1367
1368 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1369 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1370 file, linenum, args[0], args[1]);
1371 return -1;
1372 }
1373 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1374 }
1375 else {
1376 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1377 return -1;
1378 }
1379 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380#ifdef TPROXY
1381 else if (!strcmp(args[0], "transparent")) {
1382 /* enable transparent proxy connections */
1383 curproxy->options |= PR_O_TRANSP;
1384 }
1385#endif
1386 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001387 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1388 return 0;
1389
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390 if (*(args[1]) == 0) {
1391 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1392 return -1;
1393 }
1394 curproxy->maxconn = atol(args[1]);
1395 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001396 else if (!strcmp(args[0], "backlog")) { /* backlog */
1397 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1398 return 0;
1399
1400 if (*(args[1]) == 0) {
1401 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1402 return -1;
1403 }
1404 curproxy->backlog = atol(args[1]);
1405 }
Willy Tarreau86034312006-12-29 00:10:33 +01001406 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001407 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1408 return 0;
1409
Willy Tarreau86034312006-12-29 00:10:33 +01001410 if (*(args[1]) == 0) {
1411 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1412 return -1;
1413 }
1414 curproxy->fullconn = atol(args[1]);
1415 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001416 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1417 if (*(args[1]) == 0) {
1418 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1419 return -1;
1420 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001421 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1422 if (err) {
1423 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1424 file, linenum, *err);
1425 return -1;
1426 }
1427 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001428 }
1429 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1430 if (curproxy == &defproxy) {
1431 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1432 return -1;
1433 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001434 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1435 return 0;
1436
Willy Tarreaubaaee002006-06-26 02:48:02 +02001437 if (strchr(args[1], ':') == NULL) {
1438 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1439 return -1;
1440 }
1441 curproxy->dispatch_addr = *str2sa(args[1]);
1442 }
1443 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001444 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1445 return 0;
1446
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001447 memcpy(trash, "error near 'balance'", 19);
1448 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1449 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1450 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001451 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001452 }
1453 else if (!strcmp(args[0], "server")) { /* server address */
1454 int cur_arg;
1455 char *rport;
1456 char *raddr;
1457 short realport;
1458 int do_check;
1459
1460 if (curproxy == &defproxy) {
1461 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1462 return -1;
1463 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001464 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1465 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001466
1467 if (!*args[2]) {
1468 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1469 file, linenum, args[0]);
1470 return -1;
1471 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001472
1473 err = invalid_char(args[1]);
1474 if (err) {
1475 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1476 file, linenum, *err, args[1]);
1477 return -1;
1478 }
1479
Willy Tarreaubaaee002006-06-26 02:48:02 +02001480 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1481 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1482 return -1;
1483 }
1484
1485 /* the servers are linked backwards first */
1486 newsrv->next = curproxy->srv;
1487 curproxy->srv = newsrv;
1488 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001489 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490
1491 LIST_INIT(&newsrv->pendconns);
1492 do_check = 0;
1493 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001494 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001495 newsrv->id = strdup(args[1]);
1496
1497 /* several ways to check the port component :
1498 * - IP => port=+0, relative
1499 * - IP: => port=+0, relative
1500 * - IP:N => port=N, absolute
1501 * - IP:+N => port=+N, relative
1502 * - IP:-N => port=-N, relative
1503 */
1504 raddr = strdup(args[2]);
1505 rport = strchr(raddr, ':');
1506 if (rport) {
1507 *rport++ = 0;
1508 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001509 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001510 newsrv->state |= SRV_MAPPORTS;
1511 } else {
1512 realport = 0;
1513 newsrv->state |= SRV_MAPPORTS;
1514 }
1515
1516 newsrv->addr = *str2sa(raddr);
1517 newsrv->addr.sin_port = htons(realport);
1518 free(raddr);
1519
1520 newsrv->curfd = -1; /* no health-check in progress */
1521 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001522 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1523 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001524 newsrv->rise = DEF_RISETIME;
1525 newsrv->fall = DEF_FALLTIME;
1526 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001527 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001528 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001529 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001530
Willy Tarreaubaaee002006-06-26 02:48:02 +02001531 cur_arg = 3;
1532 while (*args[cur_arg]) {
1533 if (!strcmp(args[cur_arg], "cookie")) {
1534 newsrv->cookie = strdup(args[cur_arg + 1]);
1535 newsrv->cklen = strlen(args[cur_arg + 1]);
1536 cur_arg += 2;
1537 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001538 else if (!strcmp(args[cur_arg], "redir")) {
1539 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1540 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1541 cur_arg += 2;
1542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001543 else if (!strcmp(args[cur_arg], "rise")) {
1544 newsrv->rise = atol(args[cur_arg + 1]);
1545 newsrv->health = newsrv->rise;
1546 cur_arg += 2;
1547 }
1548 else if (!strcmp(args[cur_arg], "fall")) {
1549 newsrv->fall = atol(args[cur_arg + 1]);
1550 cur_arg += 2;
1551 }
1552 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001553 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1554 if (err) {
1555 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
1556 file, linenum, *err, newsrv->id);
1557 return -1;
1558 }
1559 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560 cur_arg += 2;
1561 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001562 else if (!strcmp(args[cur_arg], "fastinter")) {
1563 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1564 if (err) {
1565 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
1566 file, linenum, *err, newsrv->id);
1567 return -1;
1568 }
1569 newsrv->fastinter = val;
1570 cur_arg += 2;
1571 }
1572 else if (!strcmp(args[cur_arg], "downinter")) {
1573 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
1574 if (err) {
1575 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
1576 file, linenum, *err, newsrv->id);
1577 return -1;
1578 }
1579 newsrv->downinter = val;
1580 cur_arg += 2;
1581 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001582 else if (!strcmp(args[cur_arg], "addr")) {
1583 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001584 cur_arg += 2;
1585 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 else if (!strcmp(args[cur_arg], "port")) {
1587 newsrv->check_port = atol(args[cur_arg + 1]);
1588 cur_arg += 2;
1589 }
1590 else if (!strcmp(args[cur_arg], "backup")) {
1591 newsrv->state |= SRV_BACKUP;
1592 cur_arg ++;
1593 }
1594 else if (!strcmp(args[cur_arg], "weight")) {
1595 int w;
1596 w = atol(args[cur_arg + 1]);
1597 if (w < 1 || w > 256) {
1598 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1599 file, linenum, newsrv->id, w);
1600 return -1;
1601 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001602 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 cur_arg += 2;
1604 }
1605 else if (!strcmp(args[cur_arg], "minconn")) {
1606 newsrv->minconn = atol(args[cur_arg + 1]);
1607 cur_arg += 2;
1608 }
1609 else if (!strcmp(args[cur_arg], "maxconn")) {
1610 newsrv->maxconn = atol(args[cur_arg + 1]);
1611 cur_arg += 2;
1612 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001613 else if (!strcmp(args[cur_arg], "maxqueue")) {
1614 newsrv->maxqueue = atol(args[cur_arg + 1]);
1615 cur_arg += 2;
1616 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01001617 else if (!strcmp(args[cur_arg], "slowstart")) {
1618 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01001619 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001620 if (err) {
1621 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
1622 file, linenum, *err, newsrv->id);
1623 return -1;
1624 }
Willy Tarreau3259e332007-12-03 01:51:45 +01001625 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001626 cur_arg += 2;
1627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628 else if (!strcmp(args[cur_arg], "check")) {
1629 global.maxsock++;
1630 do_check = 1;
1631 cur_arg += 1;
1632 }
1633 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1634 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001635#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001636 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1637 file, linenum, "source", "usesrc");
1638#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1640 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001641#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642 return -1;
1643 }
1644 newsrv->state |= SRV_BIND_SRC;
1645 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1646 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001647 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001648#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1649#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001650 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001651 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1652 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001653 return -1;
1654 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001655#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001656 if (!*args[cur_arg + 1]) {
1657 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1658 file, linenum, "usesrc");
1659 return -1;
1660 }
1661 if (!strcmp(args[cur_arg + 1], "client")) {
1662 newsrv->state |= SRV_TPROXY_CLI;
1663 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1664 newsrv->state |= SRV_TPROXY_CIP;
1665 } else {
1666 newsrv->state |= SRV_TPROXY_ADDR;
1667 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1668 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001669 global.last_checks |= LSTCHK_NETADM;
1670#if !defined(CONFIG_HAP_LINUX_TPROXY)
1671 global.last_checks |= LSTCHK_CTTPROXY;
1672#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001673 cur_arg += 2;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001674#else /* no TPROXY support */
1675 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001676 file, linenum, "usesrc");
1677 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001678#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001679 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001680 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001681 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1682 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1683 file, linenum, "usesrc", "source");
1684 return -1;
1685 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 else {
Willy Tarreau21d2af32008-02-14 20:25:24 +01001687 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'check', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688 file, linenum, newsrv->id);
1689 return -1;
1690 }
1691 }
1692
1693 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001694 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1695 newsrv->check_port = newsrv->check_addr.sin_port;
1696
Willy Tarreaubaaee002006-06-26 02:48:02 +02001697 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1698 newsrv->check_port = realport; /* by default */
1699 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001700 /* not yet valid, because no port was set on
1701 * the server either. We'll check if we have
1702 * a known port on the first listener.
1703 */
1704 struct listener *l;
1705 l = curproxy->listen;
1706 if (l) {
1707 int port;
1708 port = (l->addr.ss_family == AF_INET6)
1709 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1710 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1711 newsrv->check_port = port;
1712 }
1713 }
1714 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001715 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1716 file, linenum, newsrv->id);
1717 return -1;
1718 }
1719 newsrv->state |= SRV_CHECKED;
1720 }
1721
1722 if (newsrv->state & SRV_BACKUP)
1723 curproxy->srv_bck++;
1724 else
1725 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01001726
1727 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 }
1729 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01001730 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001731 int facility;
1732
1733 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1734 curproxy->logfac1 = global.logfac1;
1735 curproxy->logsrv1 = global.logsrv1;
1736 curproxy->loglev1 = global.loglev1;
1737 curproxy->logfac2 = global.logfac2;
1738 curproxy->logsrv2 = global.logsrv2;
1739 curproxy->loglev2 = global.loglev2;
1740 }
1741 else if (*(args[1]) && *(args[2])) {
1742 int level;
1743
1744 facility = get_log_facility(args[2]);
1745 if (facility < 0) {
1746 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1747 exit(1);
1748 }
1749
1750 level = 7; /* max syslog level = debug */
1751 if (*(args[3])) {
1752 level = get_log_level(args[3]);
1753 if (level < 0) {
1754 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1755 exit(1);
1756 }
1757 }
1758
Robert Tsai81ae1952007-12-05 10:47:29 +01001759 if (args[1][0] == '/') {
1760 logsrv.u.addr.sa_family = AF_UNIX;
1761 logsrv.u.un = *str2sun(args[1]);
1762 } else {
1763 logsrv.u.addr.sa_family = AF_INET;
1764 logsrv.u.in = *str2sa(args[1]);
1765 if (!logsrv.u.in.sin_port) {
1766 logsrv.u.in.sin_port =
1767 htons(SYSLOG_PORT);
1768 }
1769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770
1771 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001772 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773 curproxy->logfac1 = facility;
1774 curproxy->loglev1 = level;
1775 }
1776 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01001777 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 curproxy->logfac2 = facility;
1779 curproxy->loglev2 = level;
1780 }
1781 else {
1782 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1783 return -1;
1784 }
1785 }
1786 else {
1787 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1788 file, linenum);
1789 return -1;
1790 }
1791 }
1792 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001793 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1794 return 0;
1795
Willy Tarreaubaaee002006-06-26 02:48:02 +02001796 if (!*args[1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001797#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001798 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1799 file, linenum, "source", "usesrc");
1800#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1802 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001803#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001804 return -1;
1805 }
1806
1807 curproxy->source_addr = *str2sa(args[1]);
1808 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001809 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001810#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
1811#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau77074d52006-11-12 23:57:19 +01001812 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1813 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1814 file, linenum, "usesrc");
1815 return -1;
1816 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001817#endif
Willy Tarreau77074d52006-11-12 23:57:19 +01001818 if (!*args[3]) {
1819 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1820 file, linenum, "usesrc");
1821 return -1;
1822 }
1823
1824 if (!strcmp(args[3], "client")) {
1825 curproxy->options |= PR_O_TPXY_CLI;
1826 } else if (!strcmp(args[3], "clientip")) {
1827 curproxy->options |= PR_O_TPXY_CIP;
1828 } else {
1829 curproxy->options |= PR_O_TPXY_ADDR;
1830 curproxy->tproxy_addr = *str2sa(args[3]);
1831 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01001832 global.last_checks |= LSTCHK_NETADM;
1833#if !defined(CONFIG_HAP_LINUX_TPROXY)
1834 global.last_checks |= LSTCHK_CTTPROXY;
1835#endif
1836#else /* no TPROXY support */
1837 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001838 file, linenum, "usesrc");
1839 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001840#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001841 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001842 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001843 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1844 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1845 file, linenum, "usesrc", "source");
1846 return -1;
1847 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001848 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1849 regex_t *preg;
1850 if (curproxy == &defproxy) {
1851 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1852 return -1;
1853 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001854 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1855 return 0;
1856
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857 if (*(args[1]) == 0 || *(args[2]) == 0) {
1858 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1859 file, linenum, args[0]);
1860 return -1;
1861 }
1862
1863 preg = calloc(1, sizeof(regex_t));
1864 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1865 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1866 return -1;
1867 }
1868
1869 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1870 if (err) {
1871 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1872 file, linenum, *err);
1873 return -1;
1874 }
1875 }
1876 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1877 regex_t *preg;
1878 if (curproxy == &defproxy) {
1879 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1880 return -1;
1881 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001882 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1883 return 0;
1884
Willy Tarreaubaaee002006-06-26 02:48:02 +02001885 if (*(args[1]) == 0) {
1886 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1887 return -1;
1888 }
1889
1890 preg = calloc(1, sizeof(regex_t));
1891 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1892 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1893 return -1;
1894 }
1895
1896 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1897 }
1898 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1899 regex_t *preg;
1900 if (curproxy == &defproxy) {
1901 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1902 return -1;
1903 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001904 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1905 return 0;
1906
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907 if (*(args[1]) == 0) {
1908 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1909 return -1;
1910 }
1911
1912 preg = calloc(1, sizeof(regex_t));
1913 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1914 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1915 return -1;
1916 }
1917
1918 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1919 }
1920 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1921 regex_t *preg;
1922 if (curproxy == &defproxy) {
1923 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1924 return -1;
1925 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001926 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1927 return 0;
1928
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929 if (*(args[1]) == 0) {
1930 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1931 return -1;
1932 }
1933
1934 preg = calloc(1, sizeof(regex_t));
1935 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1936 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1937 return -1;
1938 }
1939
1940 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1941 }
1942 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1943 regex_t *preg;
1944 if (curproxy == &defproxy) {
1945 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1946 return -1;
1947 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001948 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1949 return 0;
1950
Willy Tarreaubaaee002006-06-26 02:48:02 +02001951 if (*(args[1]) == 0) {
1952 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1953 return -1;
1954 }
1955
1956 preg = calloc(1, sizeof(regex_t));
1957 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1958 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1959 return -1;
1960 }
1961
1962 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1963 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001964 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1965 regex_t *preg;
1966 if (curproxy == &defproxy) {
1967 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1968 return -1;
1969 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001970 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1971 return 0;
1972
Willy Tarreaub8750a82006-09-03 09:56:00 +02001973 if (*(args[1]) == 0) {
1974 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1975 return -1;
1976 }
1977
1978 preg = calloc(1, sizeof(regex_t));
1979 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1980 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1981 return -1;
1982 }
1983
1984 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1985 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001986 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1987 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001988 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001989 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1990 return -1;
1991 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001992 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1993 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001994
Willy Tarreau977b8e42006-12-29 14:19:17 +01001995 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001996 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1997 file, linenum, args[0]);
1998 return -1;
1999 }
2000
2001 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002002 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002003 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2004 }
2005
2006 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2007 }
2008 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2009 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002010 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002011 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2012 return -1;
2013 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002014 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2015 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002016
Willy Tarreau977b8e42006-12-29 14:19:17 +01002017 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002018 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2019 file, linenum, args[0]);
2020 return -1;
2021 }
2022
2023 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002024 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002025 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2026 }
2027
2028 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
2029 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002030 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2031 regex_t *preg;
2032 if (curproxy == &defproxy) {
2033 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2034 return -1;
2035 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002036 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2037 return 0;
2038
Willy Tarreaubaaee002006-06-26 02:48:02 +02002039 if (*(args[1]) == 0 || *(args[2]) == 0) {
2040 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2041 file, linenum, args[0]);
2042 return -1;
2043 }
2044
2045 preg = calloc(1, sizeof(regex_t));
2046 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2047 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2048 return -1;
2049 }
2050
2051 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2052 if (err) {
2053 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2054 file, linenum, *err);
2055 return -1;
2056 }
2057 }
2058 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2059 regex_t *preg;
2060 if (curproxy == &defproxy) {
2061 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2062 return -1;
2063 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002064 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2065 return 0;
2066
Willy Tarreaubaaee002006-06-26 02:48:02 +02002067 if (*(args[1]) == 0) {
2068 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2069 return -1;
2070 }
2071
2072 preg = calloc(1, sizeof(regex_t));
2073 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2074 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2075 return -1;
2076 }
2077
2078 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
2079 }
2080 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2081 regex_t *preg;
2082 if (curproxy == &defproxy) {
2083 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2084 return -1;
2085 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002086 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2087 return 0;
2088
Willy Tarreaubaaee002006-06-26 02:48:02 +02002089 if (*(args[1]) == 0) {
2090 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2091 return -1;
2092 }
2093
2094 preg = calloc(1, sizeof(regex_t));
2095 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2096 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2097 return -1;
2098 }
2099
2100 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
2101 }
2102 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2103 regex_t *preg;
2104 if (curproxy == &defproxy) {
2105 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2106 return -1;
2107 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002108 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2109 return 0;
2110
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 if (*(args[1]) == 0) {
2112 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2113 return -1;
2114 }
2115
2116 preg = calloc(1, sizeof(regex_t));
2117 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2118 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2119 return -1;
2120 }
2121
2122 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
2123 }
2124 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2125 regex_t *preg;
2126 if (curproxy == &defproxy) {
2127 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2128 return -1;
2129 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002130 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2131 return 0;
2132
Willy Tarreaubaaee002006-06-26 02:48:02 +02002133 if (*(args[1]) == 0) {
2134 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2135 return -1;
2136 }
2137
2138 preg = calloc(1, sizeof(regex_t));
2139 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2140 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2141 return -1;
2142 }
2143
2144 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
2145 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002146 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2147 regex_t *preg;
2148 if (curproxy == &defproxy) {
2149 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2150 return -1;
2151 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002152 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2153 return 0;
2154
Willy Tarreaub8750a82006-09-03 09:56:00 +02002155 if (*(args[1]) == 0) {
2156 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2157 return -1;
2158 }
2159
2160 preg = calloc(1, sizeof(regex_t));
2161 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2162 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2163 return -1;
2164 }
2165
2166 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
2167 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002168 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2169 if (curproxy == &defproxy) {
2170 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2171 return -1;
2172 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002173 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2174 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002175
2176 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2177 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2178 return 0;
2179 }
2180
2181 if (*(args[1]) == 0) {
2182 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2183 return -1;
2184 }
2185
2186 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
2187 }
2188 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2189 regex_t *preg;
2190
2191 if (*(args[1]) == 0 || *(args[2]) == 0) {
2192 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2193 file, linenum, args[0]);
2194 return -1;
2195 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002196 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2197 return 0;
2198
Willy Tarreaubaaee002006-06-26 02:48:02 +02002199 preg = calloc(1, sizeof(regex_t));
2200 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2201 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2202 return -1;
2203 }
2204
2205 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2206 if (err) {
2207 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2208 file, linenum, *err);
2209 return -1;
2210 }
2211 }
2212 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2213 regex_t *preg;
2214 if (curproxy == &defproxy) {
2215 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2216 return -1;
2217 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002218 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2219 return 0;
2220
Willy Tarreaubaaee002006-06-26 02:48:02 +02002221 if (*(args[1]) == 0) {
2222 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2223 return -1;
2224 }
2225
2226 preg = calloc(1, sizeof(regex_t));
2227 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2228 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2229 return -1;
2230 }
2231
2232 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2233 if (err) {
2234 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2235 file, linenum, *err);
2236 return -1;
2237 }
2238 }
2239 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2240 regex_t *preg;
2241 if (curproxy == &defproxy) {
2242 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2243 return -1;
2244 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002245 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2246 return 0;
2247
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 if (*(args[1]) == 0) {
2249 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2250 return -1;
2251 }
2252
2253 preg = calloc(1, sizeof(regex_t));
2254 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2255 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2256 return -1;
2257 }
2258
2259 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2260 if (err) {
2261 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2262 file, linenum, *err);
2263 return -1;
2264 }
2265 }
2266 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2267 regex_t *preg;
2268 if (curproxy == &defproxy) {
2269 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2270 return -1;
2271 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002272 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2273 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274
2275 if (*(args[1]) == 0 || *(args[2]) == 0) {
2276 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2277 file, linenum, args[0]);
2278 return -1;
2279 }
2280
2281 preg = calloc(1, sizeof(regex_t));
2282 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2283 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2284 return -1;
2285 }
2286
2287 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2288 if (err) {
2289 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2290 file, linenum, *err);
2291 return -1;
2292 }
2293 }
2294 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2295 regex_t *preg;
2296 if (curproxy == &defproxy) {
2297 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2298 return -1;
2299 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002300 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2301 return 0;
2302
Willy Tarreaubaaee002006-06-26 02:48:02 +02002303 if (*(args[1]) == 0) {
2304 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2305 return -1;
2306 }
2307
2308 preg = calloc(1, sizeof(regex_t));
2309 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2310 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2311 return -1;
2312 }
2313
2314 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2315 if (err) {
2316 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2317 file, linenum, *err);
2318 return -1;
2319 }
2320 }
2321 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2322 regex_t *preg;
2323 if (curproxy == &defproxy) {
2324 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2325 return -1;
2326 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002327 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2328 return 0;
2329
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 if (*(args[1]) == 0) {
2331 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2332 return -1;
2333 }
2334
2335 preg = calloc(1, sizeof(regex_t));
2336 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2337 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2338 return -1;
2339 }
2340
2341 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2342 if (err) {
2343 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2344 file, linenum, *err);
2345 return -1;
2346 }
2347 }
2348 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2349 if (curproxy == &defproxy) {
2350 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2351 return -1;
2352 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002353 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2354 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002355
2356 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2357 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2358 return 0;
2359 }
2360
2361 if (*(args[1]) == 0) {
2362 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2363 return -1;
2364 }
2365
2366 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2367 }
2368 else if (!strcmp(args[0], "errorloc") ||
2369 !strcmp(args[0], "errorloc302") ||
2370 !strcmp(args[0], "errorloc303")) { /* error location */
2371 int errnum, errlen;
2372 char *err;
2373
Willy Tarreau977b8e42006-12-29 14:19:17 +01002374 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2375 return 0;
2376
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002378 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 return -1;
2380 }
2381
2382 errnum = atol(args[1]);
2383 if (!strcmp(args[0], "errorloc303")) {
2384 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2385 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2386 } else {
2387 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2388 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2389 }
2390
Willy Tarreau0f772532006-12-23 20:51:41 +01002391 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2392 if (http_err_codes[rc] == errnum) {
2393 if (curproxy->errmsg[rc].str)
2394 free(curproxy->errmsg[rc].str);
2395 curproxy->errmsg[rc].str = err;
2396 curproxy->errmsg[rc].len = errlen;
2397 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002400
2401 if (rc >= HTTP_ERR_SIZE) {
2402 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2403 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 free(err);
2405 }
2406 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002407 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2408 int errnum, errlen, fd;
2409 char *err;
2410 struct stat stat;
2411
2412 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2413 return 0;
2414
2415 if (*(args[2]) == 0) {
2416 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2417 return -1;
2418 }
2419
2420 fd = open(args[2], O_RDONLY);
2421 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2422 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2423 file, linenum, args[2], args[1]);
2424 if (fd >= 0)
2425 close(fd);
2426 return -1;
2427 }
2428
2429 if (stat.st_size <= BUFSIZE) {
2430 errlen = stat.st_size;
2431 } else {
2432 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2433 file, linenum, args[2], BUFSIZE);
2434 errlen = BUFSIZE;
2435 }
2436
2437 err = malloc(errlen); /* malloc() must succeed during parsing */
2438 errnum = read(fd, err, errlen);
2439 if (errnum != errlen) {
2440 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2441 file, linenum, args[2], args[1]);
2442 close(fd);
2443 free(err);
2444 return -1;
2445 }
2446 close(fd);
2447
2448 errnum = atol(args[1]);
2449 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2450 if (http_err_codes[rc] == errnum) {
2451 if (curproxy->errmsg[rc].str)
2452 free(curproxy->errmsg[rc].str);
2453 curproxy->errmsg[rc].str = err;
2454 curproxy->errmsg[rc].len = errlen;
2455 break;
2456 }
2457 }
2458
2459 if (rc >= HTTP_ERR_SIZE) {
2460 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2461 file, linenum, errnum);
2462 free(err);
2463 }
2464 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002465 else {
Willy Tarreau6daf3432008-01-22 16:44:08 +01002466 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 return -1;
2468 }
2469 return 0;
2470}
2471
2472
2473/*
2474 * This function reads and parses the configuration file given in the argument.
2475 * returns 0 if OK, -1 if error.
2476 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002477int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002479 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480 FILE *f;
2481 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002482 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483 int confsect = CFG_NONE;
2484
2485 struct proxy *curproxy = NULL;
2486 struct server *newsrv = NULL;
2487
2488 if ((f=fopen(file,"r")) == NULL)
2489 return -1;
2490
2491 init_default_instance();
2492
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002493 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002494 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002495 char *end;
2496 char *args[MAX_LINE_ARGS + 1];
2497 char *line = thisline;
2498
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499 linenum++;
2500
2501 end = line + strlen(line);
2502
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002503 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
2504 /* Check if we reached the limit and the last char is not \n.
2505 * Watch out for the last line without the terminating '\n'!
2506 */
2507 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
2508 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002509 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002510 }
2511
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002513 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 line++;
2515
2516 arg = 0;
2517 args[arg] = line;
2518
2519 while (*line && arg < MAX_LINE_ARGS) {
2520 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2521 * C equivalent value. Other combinations left unchanged (eg: \1).
2522 */
2523 if (*line == '\\') {
2524 int skip = 0;
2525 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2526 *line = line[1];
2527 skip = 1;
2528 }
2529 else if (line[1] == 'r') {
2530 *line = '\r';
2531 skip = 1;
2532 }
2533 else if (line[1] == 'n') {
2534 *line = '\n';
2535 skip = 1;
2536 }
2537 else if (line[1] == 't') {
2538 *line = '\t';
2539 skip = 1;
2540 }
2541 else if (line[1] == 'x') {
2542 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2543 unsigned char hex1, hex2;
2544 hex1 = toupper(line[2]) - '0';
2545 hex2 = toupper(line[3]) - '0';
2546 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2547 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2548 *line = (hex1<<4) + hex2;
2549 skip = 3;
2550 }
2551 else {
2552 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002553 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554 }
2555 }
2556 if (skip) {
2557 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2558 end -= skip;
2559 }
2560 line++;
2561 }
2562 else if (*line == '#' || *line == '\n' || *line == '\r') {
2563 /* end of string, end of loop */
2564 *line = 0;
2565 break;
2566 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002567 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01002569 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002570 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 line++;
2572 args[++arg] = line;
2573 }
2574 else {
2575 line++;
2576 }
2577 }
2578
2579 /* empty line */
2580 if (!**args)
2581 continue;
2582
Willy Tarreau540abe42007-05-02 20:50:16 +02002583 /* zero out remaining args and ensure that at least one entry
2584 * is zeroed out.
2585 */
2586 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 args[arg] = line;
2588 }
2589
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002590 if (!strcmp(args[0], "no")) {
2591 inv = 1;
2592 for (arg=0; *args[arg+1]; arg++)
2593 args[arg] = args[arg+1]; // shift args after inversion
2594 }
2595
2596 if (inv && strcmp(args[0], "option")) {
2597 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002598 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002599 }
2600
Willy Tarreau977b8e42006-12-29 14:19:17 +01002601 if (!strcmp(args[0], "listen") ||
2602 !strcmp(args[0], "frontend") ||
2603 !strcmp(args[0], "backend") ||
2604 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01002605 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 confsect = CFG_LISTEN;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002607 if (cursection)
2608 free(cursection);
2609 cursection = strdup(args[0]);
2610 }
2611 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612 confsect = CFG_GLOBAL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002613 if (cursection)
2614 free(cursection);
2615 cursection = strdup(args[0]);
2616 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 /* else it's a section keyword */
2618
2619 switch (confsect) {
2620 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002621 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002622 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623 break;
2624 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002625 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01002626 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002627 break;
2628 default:
2629 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002630 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01002633 if (cursection)
2634 free(cursection);
2635 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636 fclose(f);
2637
2638 /*
2639 * Now, check for the integrity of all that we have collected.
2640 */
2641
2642 /* will be needed further to delay some tasks */
2643 tv_now(&now);
2644
2645 if ((curproxy = proxy) == NULL) {
2646 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2647 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002648 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 }
2650
2651 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002652 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002653 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002654
Willy Tarreaubaaee002006-06-26 02:48:02 +02002655 if (curproxy->state == PR_STSTOPPED) {
2656 curproxy = curproxy->next;
2657 continue;
2658 }
2659
Willy Tarreau977b8e42006-12-29 14:19:17 +01002660 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2661 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 +01002662 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002663 cfgerr++;
2664 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002665 else if (curproxy->cap & PR_CAP_BE &&
2666 ((curproxy->mode != PR_MODE_HEALTH) &&
Alexandre Cassen5eb1a902007-11-29 15:43:32 +01002667 !(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreau31682232007-11-29 15:38:04 +01002668 !(curproxy->lbprm.algo & BE_LB_ALGO) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002669 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2670 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 +01002671 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 cfgerr++;
2673 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002674
Willy Tarreau31682232007-11-29 15:38:04 +01002675 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->lbprm.algo & BE_LB_ALGO)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002677 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002678 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 cfgerr++;
2680 }
2681#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2682 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002683 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002684 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002685 cfgerr++;
2686 }
2687#endif
2688 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002689 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002690 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 }
2692 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002693
2694 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002696 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002697 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002700 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002701 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702 }
2703 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002704 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002705 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002706 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002707 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002708 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002709 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002710 }
Willy Tarreaudf366142007-11-30 16:23:20 +01002711 if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
Willy Tarreau31682232007-11-29 15:38:04 +01002712 curproxy->lbprm.algo &= ~BE_LB_ALGO;
2713 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002714
Willy Tarreau1a20a5d2007-11-01 21:08:19 +01002715 Warning("parsing %s : Layer 7 hash not possible for %s '%s'. Falling back to round robin.\n",
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002716 file, proxy_type_str(curproxy), curproxy->id);
2717 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002718 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002719
2720 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2721 if ((newsrv = curproxy->srv) != NULL) {
2722 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2723 file, proxy_type_str(curproxy), curproxy->id);
2724 }
2725 }
2726
2727 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2729 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2730 file, curproxy->id);
2731 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002732 }
2733 }
2734
Willy Tarreau82936582007-11-30 15:20:09 +01002735 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
2736 curproxy->options &= ~PR_O_DISABLE404;
2737 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
2738 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
2739 }
2740
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002741 /* if a default backend was specified, let's find it */
2742 if (curproxy->defbe.name) {
2743 struct proxy *target;
2744
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002745 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
2746 if (!target) {
2747 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
2748 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002749 cfgerr++;
2750 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002751 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
2752 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002753 } else {
2754 free(curproxy->defbe.name);
2755 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 }
2757 }
2758
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002759 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002760 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2761 /* map jump target for ACT_SETBE in req_rep chain */
2762 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01002763 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002764 struct proxy *target;
2765
Willy Tarreaua496b602006-12-17 23:15:24 +01002766 if (exp->action != ACT_SETBE)
2767 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002768
2769 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
2770 if (!target) {
2771 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
2772 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01002773 cfgerr++;
2774 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002775 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
2776 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002777 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002778 } else {
2779 free((void *)exp->replace);
2780 exp->replace = (const char *)target;
2781 }
2782 }
2783 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002784
2785 /* find the target proxy for 'use_backend' rules */
2786 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002787 struct proxy *target;
2788
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002789 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002790
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002791 if (!target) {
2792 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
2793 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002794 cfgerr++;
2795 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01002796 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
2797 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002798 cfgerr++;
2799 } else {
2800 free((void *)rule->be.name);
2801 rule->be.backend = target;
2802 }
2803 }
2804
Willy Tarreau2738a142006-07-08 17:28:09 +02002805 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002806 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->timeout.client)) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02002807 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002808 (!tv_isset(&curproxy->timeout.connect) || !tv_isset(&curproxy->timeout.server))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002809 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002810 " | While not properly invalid, you will certainly encounter various problems\n"
2811 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01002812 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002813 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002814 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002815
Willy Tarreau1fa31262007-12-03 00:36:16 +01002816 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
2817 * We must still support older configurations, so let's find out whether those
2818 * parameters have been set or must be copied from contimeouts.
2819 */
2820 if (curproxy != &defproxy) {
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002821 if (!tv_isset(&curproxy->timeout.tarpit) ||
2822 __tv_iseq(&curproxy->timeout.tarpit, &defproxy.timeout.tarpit)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01002823 /* tarpit timeout not set. We search in the following order:
2824 * default.tarpit, curr.connect, default.connect.
2825 */
2826 if (tv_isset(&defproxy.timeout.tarpit))
2827 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002828 else if (tv_isset(&curproxy->timeout.connect))
2829 curproxy->timeout.tarpit = curproxy->timeout.connect;
2830 else if (tv_isset(&defproxy.timeout.connect))
2831 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002832 }
2833 if ((curproxy->cap & PR_CAP_BE) &&
2834 (!tv_isset(&curproxy->timeout.queue) ||
2835 __tv_iseq(&curproxy->timeout.queue, &defproxy.timeout.queue))) {
2836 /* queue timeout not set. We search in the following order:
2837 * default.queue, curr.connect, default.connect.
2838 */
2839 if (tv_isset(&defproxy.timeout.queue))
2840 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002841 else if (tv_isset(&curproxy->timeout.connect))
2842 curproxy->timeout.queue = curproxy->timeout.connect;
2843 else if (tv_isset(&defproxy.timeout.connect))
2844 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002845 }
2846 }
2847
Willy Tarreauf3c69202006-07-09 16:42:34 +02002848 if (curproxy->options & PR_O_SSL3_CHK) {
2849 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2850 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2851 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2852 }
2853
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002854 /* The small pools required for the capture lists */
2855 if (curproxy->nb_req_cap)
2856 curproxy->req_cap_pool = create_pool("ptrcap",
2857 curproxy->nb_req_cap * sizeof(char *),
2858 MEM_F_SHARED);
2859 if (curproxy->nb_rsp_cap)
2860 curproxy->rsp_cap_pool = create_pool("ptrcap",
2861 curproxy->nb_rsp_cap * sizeof(char *),
2862 MEM_F_SHARED);
2863
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002864 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2865 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2866 MEM_F_SHARED);
2867
Willy Tarreau86034312006-12-29 00:10:33 +01002868 /* for backwards compatibility with "listen" instances, if
2869 * fullconn is not set but maxconn is set, then maxconn
2870 * is used.
2871 */
2872 if (!curproxy->fullconn)
2873 curproxy->fullconn = curproxy->maxconn;
2874
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875 /* first, we will invert the servers list order */
2876 newsrv = NULL;
2877 while (curproxy->srv) {
2878 struct server *next;
2879
2880 next = curproxy->srv->next;
2881 curproxy->srv->next = newsrv;
2882 newsrv = curproxy->srv;
2883 if (!next)
2884 break;
2885 curproxy->srv = next;
2886 }
2887
Willy Tarreau20697042007-11-15 23:26:18 +01002888 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01002889 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890
Willy Tarreaub625a082007-11-26 01:15:43 +01002891 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01002892 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01002893 fwrr_init_server_groups(curproxy);
2894 else
2895 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896
2897 if (curproxy->options & PR_O_LOGASAP)
2898 curproxy->to_log &= ~LW_BYTES;
2899
Willy Tarreaubaaee002006-06-26 02:48:02 +02002900 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01002901 * ensure that we're not cross-dressing a TCP server into HTTP.
2902 */
2903 newsrv = curproxy->srv;
2904 while (newsrv != NULL) {
2905 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
2906 Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
2907 file, proxy_type_str(curproxy), curproxy->id, linenum);
2908 goto err;
2909 }
2910 newsrv = newsrv->next;
2911 }
2912
2913 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914 * If this server supports a maxconn parameter, it needs a dedicated
2915 * tasks to fill the emptied slots when a connection leaves.
2916 */
2917 newsrv = curproxy->srv;
2918 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002919 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002920 /* Only 'minconn' was specified, or it was higher than or equal
2921 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2922 * this will avoid further useless expensive computations.
2923 */
2924 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002925 } else if (newsrv->maxconn && !newsrv->minconn) {
2926 /* minconn was not specified, so we set it to maxconn */
2927 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002928 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2929 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002930 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002931 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002932 }
2933
2934 if (newsrv->maxconn > 0) {
2935 struct task *t;
2936
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002937 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002938 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01002939 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940 }
2941
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002942 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002943 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002944 t->state = TASK_IDLE;
2945 t->process = process_srv_queue;
2946 t->context = newsrv;
2947 newsrv->queue_mgt = t;
2948
2949 /* never run it unless specifically woken up */
2950 tv_eternity(&t->expire);
2951 task_queue(t);
2952 }
2953 newsrv = newsrv->next;
2954 }
2955
Willy Tarreaue6b98942007-10-29 01:09:36 +01002956 /* adjust this proxy's listeners */
2957 listener = curproxy->listen;
2958 while (listener) {
2959 if (curproxy->options & PR_O_TCP_NOLING)
2960 listener->options |= LI_O_NOLINGER;
2961 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002962 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002963 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01002964 listener->accept = event_accept;
2965 listener->private = curproxy;
2966
2967 listener = listener->next;
2968 }
2969
Willy Tarreaubaaee002006-06-26 02:48:02 +02002970 curproxy = curproxy->next;
2971 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002972
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973 if (cfgerr > 0) {
2974 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01002975 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002976 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002977
2978 /*
2979 * Recount currently required checks.
2980 */
2981
2982 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
2983 int optnum;
2984
2985 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2986 if (!(curproxy->options & cfg_opts[optnum].val))
2987 continue;
2988
2989 global.last_checks |= cfg_opts[optnum].checks;
2990 }
2991 }
2992
Willy Tarreau6daf3432008-01-22 16:44:08 +01002993 if (cursection)
2994 free(cursection);
2995 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002996 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01002997
2998 err:
2999 if (cursection)
3000 free(cursection);
3001 cursection = NULL;
3002 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003}
3004
3005
3006
3007/*
3008 * Local variables:
3009 * c-indent-level: 8
3010 * c-basic-offset: 8
3011 * End:
3012 */