blob: 77bd8277e904fe8c75967a2c33cf11fa02c33481 [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 Tarreau0f772532006-12-23 20:51:41 +010044#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/log.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010046#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <proto/server.h>
48#include <proto/task.h>
49
50
Willy Tarreauf3c69202006-07-09 16:42:34 +020051/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
52 * ssl-hello-chk option to ensure that the remote server speaks SSL.
53 *
54 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
55 */
56const char sslv3_client_hello_pkt[] = {
57 "\x16" /* ContentType : 0x16 = Hanshake */
58 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
59 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
60 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
61 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
62 "\x03\x00" /* Hello Version : 0x0300 = v3 */
63 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
64 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
65 "\x00" /* Session ID length : empty (no session ID) */
66 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
67 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
68 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
69 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
70 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
71 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
72 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
73 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
74 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
75 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
76 "\x00\x38" "\x00\x39" "\x00\x3A"
77 "\x01" /* Compression Length : 0x01 = 1 byte for types */
78 "\x00" /* Compression Type : 0x00 = NULL compression */
79};
80
Willy Tarreau13943ab2006-12-31 00:24:10 +010081/* some of the most common options which are also the easiest to handle */
82static const struct {
83 const char *name;
84 unsigned int val;
85 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010086 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010087} cfg_opts[] =
88{
89#ifdef TPROXY
90 { "transparent", PR_O_TRANSP, PR_CAP_FE },
91#endif
Willy Tarreau4fee4e92007-01-06 21:09:17 +010092 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
93 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010094 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
95 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
96 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
97 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
98 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
99 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
100 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
101 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
102 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
103 { "forceclose", PR_O_FORCE_CLO | PR_O_HTTP_CLOSE, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100104#ifdef CONFIG_HAP_TCPSPLICE
105 { "tcpsplice", PR_O_TCPSPLICE , PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
106#endif
107
Willy Tarreau13943ab2006-12-31 00:24:10 +0100108 { NULL, 0, 0 }
109};
110
Willy Tarreaubaaee002006-06-26 02:48:02 +0200111
112static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
113int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
114int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
115
116/*
117 * converts <str> to a list of listeners which are dynamically allocated.
118 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
119 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
120 * - <port> is a numerical port from 1 to 65535 ;
121 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
122 * This can be repeated as many times as necessary, separated by a coma.
123 * The <tail> argument is a pointer to a current list which should be appended
124 * to the tail of the new list. The pointer to the new list is returned.
125 */
126static struct listener *str2listener(char *str, struct listener *tail)
127{
128 struct listener *l;
129 char *c, *next, *range, *dupstr;
130 int port, end;
131
132 next = dupstr = strdup(str);
133
134 while (next && *next) {
135 struct sockaddr_storage ss;
136
137 str = next;
138 /* 1) look for the end of the first address */
139 if ((next = strrchr(str, ',')) != NULL) {
140 *next++ = 0;
141 }
142
143 /* 2) look for the addr/port delimiter, it's the last colon. */
144 if ((range = strrchr(str, ':')) == NULL) {
145 Alert("Missing port number: '%s'\n", str);
146 goto fail;
147 }
148
149 *range++ = 0;
150
151 if (strrchr(str, ':') != NULL) {
152 /* IPv6 address contains ':' */
153 memset(&ss, 0, sizeof(ss));
154 ss.ss_family = AF_INET6;
155
156 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
157 Alert("Invalid server address: '%s'\n", str);
158 goto fail;
159 }
160 }
161 else {
162 memset(&ss, 0, sizeof(ss));
163 ss.ss_family = AF_INET;
164
165 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
166 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
167 }
168 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
169 struct hostent *he;
170
171 if ((he = gethostbyname(str)) == NULL) {
172 Alert("Invalid server name: '%s'\n", str);
173 goto fail;
174 }
175 else
176 ((struct sockaddr_in *)&ss)->sin_addr =
177 *(struct in_addr *) *(he->h_addr_list);
178 }
179 }
180
181 /* 3) look for the port-end delimiter */
182 if ((c = strchr(range, '-')) != NULL) {
183 *c++ = 0;
184 end = atol(c);
185 }
186 else {
187 end = atol(range);
188 }
189
190 port = atol(range);
191
192 if (port < 1 || port > 65535) {
193 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
194 goto fail;
195 }
196
197 if (end < 1 || end > 65535) {
198 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
199 goto fail;
200 }
201
202 for (; port <= end; port++) {
203 l = (struct listener *)calloc(1, sizeof(struct listener));
204 l->next = tail;
205 tail = l;
206
207 l->fd = -1;
208 l->addr = ss;
209 if (ss.ss_family == AF_INET6)
210 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
211 else
212 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
213
214 } /* end for(port) */
215 } /* end while(next) */
216 free(dupstr);
217 return tail;
218 fail:
219 free(dupstr);
220 return NULL;
221}
222
Willy Tarreau977b8e42006-12-29 14:19:17 +0100223/*
224 * Sends a warning if proxy <proxy> does not have at least one of the
225 * capabilities in <cap>. An optionnal <hint> may be added at the end
226 * of the warning to help the user. Returns 1 if a warning was emitted
227 * or 0 if the condition is valid.
228 */
229int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
230{
231 char *msg;
232
233 switch (cap) {
234 case PR_CAP_BE: msg = "no backend"; break;
235 case PR_CAP_FE: msg = "no frontend"; break;
236 case PR_CAP_RS: msg = "no ruleset"; break;
237 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
238 default: msg = "not enough"; break;
239 }
240
241 if (!(proxy->cap & cap)) {
242 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100243 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100244 return 1;
245 }
246 return 0;
247}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200248
249/*
250 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
251 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200252int cfg_parse_global(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200253{
254
255 if (!strcmp(args[0], "global")) { /* new section */
256 /* no option, nothing special to do */
257 return 0;
258 }
259 else if (!strcmp(args[0], "daemon")) {
260 global.mode |= MODE_DAEMON;
261 }
262 else if (!strcmp(args[0], "debug")) {
263 global.mode |= MODE_DEBUG;
264 }
265 else if (!strcmp(args[0], "noepoll")) {
266 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
267 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200268 else if (!strcmp(args[0], "nosepoll")) {
269 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
270 }
271 else if (!strcmp(args[0], "nokqueue")) {
272 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274 else if (!strcmp(args[0], "nopoll")) {
275 cfg_polling_mechanism &= ~POLL_USE_POLL;
276 }
277 else if (!strcmp(args[0], "quiet")) {
278 global.mode |= MODE_QUIET;
279 }
280 else if (!strcmp(args[0], "stats")) {
281 global.mode |= MODE_STATS;
282 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200283 else if (!strcmp(args[0], "tune.maxpollevents")) {
284 if (global.tune.maxpollevents != 0) {
285 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
286 return 0;
287 }
288 if (*(args[1]) == 0) {
289 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
290 return -1;
291 }
292 global.tune.maxpollevents = atol(args[1]);
293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 else if (!strcmp(args[0], "uid")) {
295 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200296 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 return 0;
298 }
299 if (*(args[1]) == 0) {
300 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
301 return -1;
302 }
303 global.uid = atol(args[1]);
304 }
305 else if (!strcmp(args[0], "gid")) {
306 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200307 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308 return 0;
309 }
310 if (*(args[1]) == 0) {
311 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
312 return -1;
313 }
314 global.gid = atol(args[1]);
315 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200316 /* user/group name handling */
317 else if (!strcmp(args[0], "user")) {
318 struct passwd *ha_user;
319 if (global.uid != 0) {
320 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
321 return 0;
322 }
323 errno = 0;
324 ha_user = getpwnam(args[1]);
325 if (ha_user != NULL) {
326 global.uid = (int)ha_user->pw_uid;
327 }
328 else {
329 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
330 exit(1);
331 }
332 }
333 else if (!strcmp(args[0], "group")) {
334 struct group *ha_group;
335 if (global.gid != 0) {
336 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
337 return 0;
338 }
339 errno = 0;
340 ha_group = getgrnam(args[1]);
341 if (ha_group != NULL) {
342 global.gid = (int)ha_group->gr_gid;
343 }
344 else {
345 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
346 exit(1);
347 }
348 }
349 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200350 else if (!strcmp(args[0], "nbproc")) {
351 if (global.nbproc != 0) {
352 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
353 return 0;
354 }
355 if (*(args[1]) == 0) {
356 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
357 return -1;
358 }
359 global.nbproc = atol(args[1]);
360 }
361 else if (!strcmp(args[0], "maxconn")) {
362 if (global.maxconn != 0) {
363 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
364 return 0;
365 }
366 if (*(args[1]) == 0) {
367 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
368 return -1;
369 }
370 global.maxconn = atol(args[1]);
371#ifdef SYSTEM_MAXCONN
372 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
373 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);
374 global.maxconn = DEFAULT_MAXCONN;
375 }
376#endif /* SYSTEM_MAXCONN */
377 }
378 else if (!strcmp(args[0], "ulimit-n")) {
379 if (global.rlimit_nofile != 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.rlimit_nofile = atol(args[1]);
388 }
389 else if (!strcmp(args[0], "chroot")) {
390 if (global.chroot != NULL) {
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 a directory as an argument.\n", file, linenum, args[0]);
396 return -1;
397 }
398 global.chroot = strdup(args[1]);
399 }
400 else if (!strcmp(args[0], "pidfile")) {
401 if (global.pidfile != NULL) {
402 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
403 return 0;
404 }
405 if (*(args[1]) == 0) {
406 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
407 return -1;
408 }
409 global.pidfile = strdup(args[1]);
410 }
411 else if (!strcmp(args[0], "log")) { /* syslog server address */
412 struct sockaddr_in *sa;
413 int facility, level;
414
415 if (*(args[1]) == 0 || *(args[2]) == 0) {
416 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
417 return -1;
418 }
419
420 facility = get_log_facility(args[2]);
421 if (facility < 0) {
422 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
423 exit(1);
424 }
425
426 level = 7; /* max syslog level = debug */
427 if (*(args[3])) {
428 level = get_log_level(args[3]);
429 if (level < 0) {
430 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
431 exit(1);
432 }
433 }
434
435 sa = str2sa(args[1]);
436 if (!sa->sin_port)
437 sa->sin_port = htons(SYSLOG_PORT);
438
439 if (global.logfac1 == -1) {
440 global.logsrv1 = *sa;
441 global.logfac1 = facility;
442 global.loglev1 = level;
443 }
444 else if (global.logfac2 == -1) {
445 global.logsrv2 = *sa;
446 global.logfac2 = facility;
447 global.loglev2 = level;
448 }
449 else {
450 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
451 return -1;
452 }
453
454 }
455 else {
456 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
457 return -1;
458 }
459 return 0;
460}
461
462
463static void init_default_instance()
464{
465 memset(&defproxy, 0, sizeof(defproxy));
466 defproxy.mode = PR_MODE_TCP;
467 defproxy.state = PR_STNEW;
468 defproxy.maxconn = cfg_maxpconn;
469 defproxy.conn_retries = CONN_RETRIES;
470 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
471}
472
473/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100474 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
475 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200477int cfg_parse_listen(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200478{
479 static struct proxy *curproxy = NULL;
480 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200481 const char *err;
Willy Tarreauee991362007-05-14 14:37:50 +0200482 int rc, val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483
Willy Tarreau977b8e42006-12-29 14:19:17 +0100484 if (!strcmp(args[0], "listen"))
485 rc = PR_CAP_LISTEN;
486 else if (!strcmp(args[0], "frontend"))
487 rc = PR_CAP_FE | PR_CAP_RS;
488 else if (!strcmp(args[0], "backend"))
489 rc = PR_CAP_BE | PR_CAP_RS;
490 else if (!strcmp(args[0], "ruleset"))
491 rc = PR_CAP_RS;
492 else
493 rc = PR_CAP_NONE;
494
495 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200496 if (!*args[1]) {
497 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
498 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
499 file, linenum, args[0]);
500 return -1;
501 }
502
503 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
504 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
505 return -1;
506 }
507
508 curproxy->next = proxy;
509 proxy = curproxy;
510 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200511 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200512 LIST_INIT(&curproxy->block_cond);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200513
Willy Tarreauee991362007-05-14 14:37:50 +0200514 /* Timeouts are defined as -1, so we cannot use the zeroed area
515 * as a default value.
516 */
517 tv_eternity(&curproxy->clitimeout);
518 tv_eternity(&curproxy->srvtimeout);
519 tv_eternity(&curproxy->contimeout);
520 tv_eternity(&curproxy->appsession_timeout);
521
Willy Tarreaubaaee002006-06-26 02:48:02 +0200522 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100523 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200524
525 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100526 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527 curproxy->listen = str2listener(args[2], curproxy->listen);
528 if (!curproxy->listen)
529 return -1;
530 global.maxsock++;
531 }
532
533 /* set default values */
534 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200535 curproxy->options = defproxy.options;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200536 curproxy->except_net = defproxy.except_net;
537 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538
Willy Tarreau977b8e42006-12-29 14:19:17 +0100539 if (curproxy->cap & PR_CAP_FE) {
540 curproxy->maxconn = defproxy.maxconn;
541
542 /* initialize error relocations */
543 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
544 if (defproxy.errmsg[rc].str)
545 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
546 }
547
548 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200550
Willy Tarreau977b8e42006-12-29 14:19:17 +0100551 if (curproxy->cap & PR_CAP_BE) {
552 curproxy->fullconn = defproxy.fullconn;
553 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200554
Willy Tarreau977b8e42006-12-29 14:19:17 +0100555 if (defproxy.check_req)
556 curproxy->check_req = strdup(defproxy.check_req);
557 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200558
Willy Tarreau977b8e42006-12-29 14:19:17 +0100559 if (defproxy.cookie_name)
560 curproxy->cookie_name = strdup(defproxy.cookie_name);
561 curproxy->cookie_len = defproxy.cookie_len;
562 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200563
Willy Tarreau977b8e42006-12-29 14:19:17 +0100564 if (curproxy->cap & PR_CAP_RS) {
565 if (defproxy.capture_name)
566 curproxy->capture_name = strdup(defproxy.capture_name);
567 curproxy->capture_namelen = defproxy.capture_namelen;
568 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100569 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200570
Willy Tarreau977b8e42006-12-29 14:19:17 +0100571 if (curproxy->cap & PR_CAP_FE) {
572 curproxy->clitimeout = defproxy.clitimeout;
573 curproxy->uri_auth = defproxy.uri_auth;
574 curproxy->mon_net = defproxy.mon_net;
575 curproxy->mon_mask = defproxy.mon_mask;
576 if (defproxy.monitor_uri)
577 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
578 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100579 if (defproxy.defbe.name)
580 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100581 }
582
583 if (curproxy->cap & PR_CAP_BE) {
584 curproxy->contimeout = defproxy.contimeout;
585 curproxy->srvtimeout = defproxy.srvtimeout;
586 curproxy->source_addr = defproxy.source_addr;
587 }
588
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 curproxy->mode = defproxy.mode;
590 curproxy->logfac1 = defproxy.logfac1;
591 curproxy->logsrv1 = defproxy.logsrv1;
592 curproxy->loglev1 = defproxy.loglev1;
593 curproxy->logfac2 = defproxy.logfac2;
594 curproxy->logsrv2 = defproxy.logsrv2;
595 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200596 curproxy->grace = defproxy.grace;
Willy Tarreau1c47f852006-07-09 08:22:27 +0200597
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598 return 0;
599 }
600 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
601 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100602 /* FIXME-20070101: we should do this too at the end of the
603 * config parsing to free all default values.
604 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200605 if (defproxy.check_req) free(defproxy.check_req);
606 if (defproxy.cookie_name) free(defproxy.cookie_name);
607 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200608 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100609 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100610
611 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
612 if (defproxy.errmsg[rc].len)
613 free(defproxy.errmsg[rc].str);
614 }
615
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616 /* we cannot free uri_auth because it might already be used */
617 init_default_instance();
618 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100619 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200620 return 0;
621 }
622 else if (curproxy == NULL) {
623 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
624 return -1;
625 }
626
Willy Tarreau977b8e42006-12-29 14:19:17 +0100627
628 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 if (!strcmp(args[0], "bind")) { /* new listen addresses */
630 if (curproxy == &defproxy) {
631 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
632 return -1;
633 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100634 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
635 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636
637 if (strchr(args[1], ':') == NULL) {
638 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
639 file, linenum, args[0]);
640 return -1;
641 }
642 curproxy->listen = str2listener(args[1], curproxy->listen);
643 if (!curproxy->listen)
644 return -1;
645 global.maxsock++;
646 return 0;
647 }
648 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
649 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
650 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
651 file, linenum, args[0]);
652 return -1;
653 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100654 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
655 return 0;
656
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 /* flush useless bits */
658 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
659 return 0;
660 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200661 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100662 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
663 return 0;
664
Willy Tarreau1c47f852006-07-09 08:22:27 +0200665 if (!*args[1]) {
666 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
667 file, linenum, args[0]);
668 return -1;
669 }
670
671 if (curproxy->monitor_uri != NULL)
672 free(curproxy->monitor_uri);
673
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100674 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200675 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100676 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200677 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
678
679 return 0;
680 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200681 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
682 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
683 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
684 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
685 else {
686 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
687 return -1;
688 }
689 }
690 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
691 curproxy->state = PR_STSTOPPED;
692 }
693 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
694 curproxy->state = PR_STNEW;
695 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200696 else if (!strcmp(args[0], "acl")) { /* add an ACL */
697 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
698 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
699 file, linenum, args[1]);
700 return -1;
701 }
702 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 else if (!strcmp(args[0], "cookie")) { /* cookie name */
704 int cur_arg;
705 // if (curproxy == &defproxy) {
706 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
707 // return -1;
708 // }
709
Willy Tarreau977b8e42006-12-29 14:19:17 +0100710 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
711 return 0;
712
Willy Tarreaubaaee002006-06-26 02:48:02 +0200713 if (curproxy->cookie_name != NULL) {
714 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
715 // file, linenum);
716 // return 0;
717 free(curproxy->cookie_name);
718 }
719
720 if (*(args[1]) == 0) {
721 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
722 file, linenum, args[0]);
723 return -1;
724 }
725 curproxy->cookie_name = strdup(args[1]);
726 curproxy->cookie_len = strlen(curproxy->cookie_name);
727
728 cur_arg = 2;
729 while (*(args[cur_arg])) {
730 if (!strcmp(args[cur_arg], "rewrite")) {
731 curproxy->options |= PR_O_COOK_RW;
732 }
733 else if (!strcmp(args[cur_arg], "indirect")) {
734 curproxy->options |= PR_O_COOK_IND;
735 }
736 else if (!strcmp(args[cur_arg], "insert")) {
737 curproxy->options |= PR_O_COOK_INS;
738 }
739 else if (!strcmp(args[cur_arg], "nocache")) {
740 curproxy->options |= PR_O_COOK_NOC;
741 }
742 else if (!strcmp(args[cur_arg], "postonly")) {
743 curproxy->options |= PR_O_COOK_POST;
744 }
745 else if (!strcmp(args[cur_arg], "prefix")) {
746 curproxy->options |= PR_O_COOK_PFX;
747 }
748 else {
749 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
750 file, linenum, args[0]);
751 return -1;
752 }
753 cur_arg++;
754 }
755 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
756 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
757 file, linenum);
758 return -1;
759 }
760
761 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
762 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
763 file, linenum);
764 return -1;
765 }
766 }/* end else if (!strcmp(args[0], "cookie")) */
767 else if (!strcmp(args[0], "appsession")) { /* cookie name */
768 // if (curproxy == &defproxy) {
769 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
770 // return -1;
771 // }
772
Willy Tarreau977b8e42006-12-29 14:19:17 +0100773 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
774 return 0;
775
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 if (curproxy->appsession_name != NULL) {
777 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
778 // file, linenum);
779 // return 0;
780 free(curproxy->appsession_name);
781 }
782
783 if (*(args[5]) == 0) {
784 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
785 file, linenum, args[0]);
786 return -1;
787 }
788 have_appsession = 1;
789 curproxy->appsession_name = strdup(args[1]);
790 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
791 curproxy->appsession_len = atoi(args[3]);
Willy Tarreauee991362007-05-14 14:37:50 +0200792 val = atoi(args[5]);
793 if (val > 0)
794 __tv_from_ms(&curproxy->appsession_timeout, val);
795 else
796 tv_eternity(&curproxy->appsession_timeout);
797
Willy Tarreaubaaee002006-06-26 02:48:02 +0200798 rc = chtbl_init(&(curproxy->htbl_proxy), TBLSIZ, hashpjw, match_str, destroy);
799 if (rc) {
800 Alert("Error Init Appsession Hashtable.\n");
801 return -1;
802 }
803 } /* Url App Session */
804 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100805 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
806 return 0;
807
Willy Tarreaubaaee002006-06-26 02:48:02 +0200808 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
809 // if (curproxy == &defproxy) {
810 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
811 // return -1;
812 // }
813
814 if (curproxy->capture_name != NULL) {
815 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
816 // file, linenum, args[0]);
817 // return 0;
818 free(curproxy->capture_name);
819 }
820
821 if (*(args[4]) == 0) {
822 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
823 file, linenum, args[0]);
824 return -1;
825 }
826 curproxy->capture_name = strdup(args[2]);
827 curproxy->capture_namelen = strlen(curproxy->capture_name);
828 curproxy->capture_len = atol(args[4]);
829 if (curproxy->capture_len >= CAPTURE_LEN) {
830 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
831 file, linenum, CAPTURE_LEN - 1);
832 curproxy->capture_len = CAPTURE_LEN - 1;
833 }
834 curproxy->to_log |= LW_COOKIE;
835 }
836 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
837 struct cap_hdr *hdr;
838
839 if (curproxy == &defproxy) {
840 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
841 return -1;
842 }
843
844 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
845 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
846 file, linenum, args[0], args[1]);
847 return -1;
848 }
849
850 hdr = calloc(sizeof(struct cap_hdr), 1);
851 hdr->next = curproxy->req_cap;
852 hdr->name = strdup(args[3]);
853 hdr->namelen = strlen(args[3]);
854 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200855 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200856 hdr->index = curproxy->nb_req_cap++;
857 curproxy->req_cap = hdr;
858 curproxy->to_log |= LW_REQHDR;
859 }
860 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
861 struct cap_hdr *hdr;
862
863 if (curproxy == &defproxy) {
864 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
865 return -1;
866 }
867
868 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
869 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
870 file, linenum, args[0], args[1]);
871 return -1;
872 }
873 hdr = calloc(sizeof(struct cap_hdr), 1);
874 hdr->next = curproxy->rsp_cap;
875 hdr->name = strdup(args[3]);
876 hdr->namelen = strlen(args[3]);
877 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200878 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879 hdr->index = curproxy->nb_rsp_cap++;
880 curproxy->rsp_cap = hdr;
881 curproxy->to_log |= LW_RSPHDR;
882 }
883 else {
884 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
885 file, linenum, args[0]);
886 return -1;
887 }
888 }
889 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200890 if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
892 return 0;
893 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100894 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
895 return 0;
896
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897 if (*(args[1]) == 0) {
898 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
899 file, linenum, args[0]);
900 return -1;
901 }
Willy Tarreauee991362007-05-14 14:37:50 +0200902 val = atoi(args[1]);
903 if (val > 0)
904 __tv_from_ms(&curproxy->contimeout, val);
905 else
906 tv_eternity(&curproxy->contimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200907 }
908 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200909 if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
911 file, linenum, args[0]);
912 return 0;
913 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100914 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
915 return 0;
916
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 if (*(args[1]) == 0) {
918 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
919 file, linenum, args[0]);
920 return -1;
921 }
Willy Tarreauee991362007-05-14 14:37:50 +0200922 val = atoi(args[1]);
923 if (val > 0)
924 __tv_from_ms(&curproxy->clitimeout, val);
925 else
926 tv_eternity(&curproxy->clitimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200929 if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
931 return 0;
932 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100933 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
934 return 0;
935
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936 if (*(args[1]) == 0) {
937 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
938 file, linenum, args[0]);
939 return -1;
940 }
Willy Tarreauee991362007-05-14 14:37:50 +0200941 val = atoi(args[1]);
942 if (val > 0)
943 __tv_from_ms(&curproxy->srvtimeout, val);
944 else
945 tv_eternity(&curproxy->srvtimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 }
947 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100948 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
949 return 0;
950
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 if (*(args[1]) == 0) {
952 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
953 file, linenum, args[0]);
954 return -1;
955 }
956 curproxy->conn_retries = atol(args[1]);
957 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200958 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
959 int pol = ACL_COND_NONE;
960 struct acl_cond *cond;
961
962 if (!strcmp(args[1], "if"))
963 pol = ACL_COND_IF;
964 else if (!strcmp(args[1], "unless"))
965 pol = ACL_COND_UNLESS;
966
967 if (pol == ACL_COND_NONE) {
968 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
969 file, linenum, args[0]);
970 return -1;
971 }
972
973 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
974 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
975 file, linenum);
976 return -1;
977 }
978 LIST_ADDQ(&curproxy->block_cond, &cond->list);
979 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100981 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
982 return 0;
983
Willy Tarreaubaaee002006-06-26 02:48:02 +0200984 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
985 curproxy->uri_auth = NULL; /* we must detach from the default config */
986
987 if (*(args[1]) == 0) {
988 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
989 return -1;
990 } else if (!strcmp(args[1], "uri")) {
991 if (*(args[2]) == 0) {
992 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
993 return -1;
994 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
995 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
996 return -1;
997 }
998 } else if (!strcmp(args[1], "realm")) {
999 if (*(args[2]) == 0) {
1000 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1001 return -1;
1002 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1003 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1004 return -1;
1005 }
1006 } else if (!strcmp(args[1], "auth")) {
1007 if (*(args[2]) == 0) {
1008 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1009 return -1;
1010 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1011 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1012 return -1;
1013 }
1014 } else if (!strcmp(args[1], "scope")) {
1015 if (*(args[2]) == 0) {
1016 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1017 return -1;
1018 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1019 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1020 return -1;
1021 }
1022 } else if (!strcmp(args[1], "enable")) {
1023 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1024 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1025 return -1;
1026 }
1027 } else {
1028 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'uri', 'realm', 'auth' or 'enable').\n",
1029 file, linenum, args[0]);
1030 return -1;
1031 }
1032 }
1033 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001034 int optnum;
1035
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036 if (*(args[1]) == 0) {
1037 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
1038 return -1;
1039 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001040
1041 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1042 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1043 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1044 return 0;
1045 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001046 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001047 return 0;
1048 }
1049 }
1050
1051 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 /* generate a complete HTTP log */
1053 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1054 else if (!strcmp(args[1], "tcplog"))
1055 /* generate a detailed TCP log */
1056 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001057 else if (!strcmp(args[1], "tcpka")) {
1058 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001059 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1060 return 0;
1061
1062 if (curproxy->cap & PR_CAP_FE)
1063 curproxy->options |= PR_O_TCP_CLI_KA;
1064 if (curproxy->cap & PR_CAP_BE)
1065 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066 }
1067 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001068 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1069 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001070 /* use HTTP request to check servers' health */
1071 if (curproxy->check_req != NULL) {
1072 free(curproxy->check_req);
1073 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001074 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001075 curproxy->options &= ~PR_O_SMTP_CHK;
1076 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001077 if (!*args[2]) { /* no argument */
1078 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1079 curproxy->check_len = strlen(DEF_CHECK_REQ);
1080 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001081 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001082 curproxy->check_req = (char *)malloc(reqlen);
1083 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1084 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1085 } else { /* more arguments : METHOD URI [HTTP_VER] */
1086 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1087 if (*args[4])
1088 reqlen += strlen(args[4]);
1089 else
1090 reqlen += strlen("HTTP/1.0");
1091
1092 curproxy->check_req = (char *)malloc(reqlen);
1093 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1094 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1095 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001096 }
1097 else if (!strcmp(args[1], "ssl-hello-chk")) {
1098 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001099 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1100 return 0;
1101
Willy Tarreauf3c69202006-07-09 16:42:34 +02001102 if (curproxy->check_req != NULL) {
1103 free(curproxy->check_req);
1104 }
1105 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001106 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001107 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001108 }
Willy Tarreau23677902007-05-08 23:50:35 +02001109 else if (!strcmp(args[1], "smtpchk")) {
1110 /* use SMTP request to check servers' health */
1111 if (curproxy->check_req != NULL) {
1112 free(curproxy->check_req);
1113 }
1114 curproxy->options &= ~PR_O_HTTP_CHK;
1115 curproxy->options &= ~PR_O_SSL3_CHK;
1116 curproxy->options |= PR_O_SMTP_CHK;
1117
1118 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1119 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1120 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1121 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1122 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1123 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1124 curproxy->check_req = (char *)malloc(reqlen);
1125 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1126 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1127 } else {
1128 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1129 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1130 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1131 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1132 }
1133 }
1134 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001135 else if (!strcmp(args[1], "forwardfor")) {
1136 /* insert x-forwarded-for field, but not for the
1137 * IP address listed as an except.
1138 */
1139 if (*(args[2])) {
1140 if (!strcmp(args[2], "except")) {
1141 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1142 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1143 file, linenum, args[0]);
1144 return -1;
1145 }
1146 /* flush useless bits */
1147 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1148 } else {
1149 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1150 file, linenum, args[0]);
1151 return -1;
1152 }
1153 }
1154 curproxy->options |= PR_O_FWDFOR;
1155 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 else {
1157 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1158 return -1;
1159 }
1160 return 0;
1161 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001162 else if (!strcmp(args[0], "default_backend")) {
1163 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1164 return 0;
1165
1166 if (*(args[1]) == 0) {
1167 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1168 return -1;
1169 }
1170 if (curproxy->defbe.name)
1171 free(curproxy->defbe.name);
1172 curproxy->defbe.name = strdup(args[1]);
1173 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001174 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001175 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1176 return 0;
1177
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178 /* enable reconnections to dispatch */
1179 curproxy->options |= PR_O_REDISP;
1180 }
1181#ifdef TPROXY
1182 else if (!strcmp(args[0], "transparent")) {
1183 /* enable transparent proxy connections */
1184 curproxy->options |= PR_O_TRANSP;
1185 }
1186#endif
1187 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001188 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1189 return 0;
1190
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191 if (*(args[1]) == 0) {
1192 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1193 return -1;
1194 }
1195 curproxy->maxconn = atol(args[1]);
1196 }
Willy Tarreau86034312006-12-29 00:10:33 +01001197 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001198 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1199 return 0;
1200
Willy Tarreau86034312006-12-29 00:10:33 +01001201 if (*(args[1]) == 0) {
1202 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1203 return -1;
1204 }
1205 curproxy->fullconn = atol(args[1]);
1206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001207 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1208 if (*(args[1]) == 0) {
1209 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1210 return -1;
1211 }
1212 curproxy->grace = atol(args[1]);
1213 }
1214 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1215 if (curproxy == &defproxy) {
1216 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1217 return -1;
1218 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001219 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1220 return 0;
1221
Willy Tarreaubaaee002006-06-26 02:48:02 +02001222 if (strchr(args[1], ':') == NULL) {
1223 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1224 return -1;
1225 }
1226 curproxy->dispatch_addr = *str2sa(args[1]);
1227 }
1228 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001229 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1230 return 0;
1231
Willy Tarreaubaaee002006-06-26 02:48:02 +02001232 if (*(args[1])) {
1233 if (!strcmp(args[1], "roundrobin")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001234 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001235 curproxy->options |= PR_O_BALANCE_RR;
1236 }
1237 else if (!strcmp(args[1], "source")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001238 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001239 curproxy->options |= PR_O_BALANCE_SH;
1240 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001241 else if (!strcmp(args[1], "uri")) {
1242 curproxy->options &= ~PR_O_BALANCE;
1243 curproxy->options |= PR_O_BALANCE_UH;
1244 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001245 else {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001246 Alert("parsing [%s:%d] : '%s' only supports 'roundrobin', 'source' and 'uri' options.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001247 return -1;
1248 }
1249 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001250 else {/* if no option is set, use round-robin by default */
1251 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001252 curproxy->options |= PR_O_BALANCE_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001254 }
1255 else if (!strcmp(args[0], "server")) { /* server address */
1256 int cur_arg;
1257 char *rport;
1258 char *raddr;
1259 short realport;
1260 int do_check;
1261
1262 if (curproxy == &defproxy) {
1263 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1264 return -1;
1265 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001266 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1267 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001268
1269 if (!*args[2]) {
1270 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1271 file, linenum, args[0]);
1272 return -1;
1273 }
1274 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1275 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1276 return -1;
1277 }
1278
1279 /* the servers are linked backwards first */
1280 newsrv->next = curproxy->srv;
1281 curproxy->srv = newsrv;
1282 newsrv->proxy = curproxy;
1283
1284 LIST_INIT(&newsrv->pendconns);
1285 do_check = 0;
1286 newsrv->state = SRV_RUNNING; /* early server setup */
1287 newsrv->id = strdup(args[1]);
1288
1289 /* several ways to check the port component :
1290 * - IP => port=+0, relative
1291 * - IP: => port=+0, relative
1292 * - IP:N => port=N, absolute
1293 * - IP:+N => port=+N, relative
1294 * - IP:-N => port=-N, relative
1295 */
1296 raddr = strdup(args[2]);
1297 rport = strchr(raddr, ':');
1298 if (rport) {
1299 *rport++ = 0;
1300 realport = atol(rport);
1301 if (!isdigit((int)*rport))
1302 newsrv->state |= SRV_MAPPORTS;
1303 } else {
1304 realport = 0;
1305 newsrv->state |= SRV_MAPPORTS;
1306 }
1307
1308 newsrv->addr = *str2sa(raddr);
1309 newsrv->addr.sin_port = htons(realport);
1310 free(raddr);
1311
1312 newsrv->curfd = -1; /* no health-check in progress */
1313 newsrv->inter = DEF_CHKINTR;
1314 newsrv->rise = DEF_RISETIME;
1315 newsrv->fall = DEF_FALLTIME;
1316 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001317 newsrv->uweight = 1;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001318
Willy Tarreaubaaee002006-06-26 02:48:02 +02001319 cur_arg = 3;
1320 while (*args[cur_arg]) {
1321 if (!strcmp(args[cur_arg], "cookie")) {
1322 newsrv->cookie = strdup(args[cur_arg + 1]);
1323 newsrv->cklen = strlen(args[cur_arg + 1]);
1324 cur_arg += 2;
1325 }
1326 else if (!strcmp(args[cur_arg], "rise")) {
1327 newsrv->rise = atol(args[cur_arg + 1]);
1328 newsrv->health = newsrv->rise;
1329 cur_arg += 2;
1330 }
1331 else if (!strcmp(args[cur_arg], "fall")) {
1332 newsrv->fall = atol(args[cur_arg + 1]);
1333 cur_arg += 2;
1334 }
1335 else if (!strcmp(args[cur_arg], "inter")) {
1336 newsrv->inter = atol(args[cur_arg + 1]);
1337 cur_arg += 2;
1338 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001339 else if (!strcmp(args[cur_arg], "addr")) {
1340 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001341 cur_arg += 2;
1342 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001343 else if (!strcmp(args[cur_arg], "port")) {
1344 newsrv->check_port = atol(args[cur_arg + 1]);
1345 cur_arg += 2;
1346 }
1347 else if (!strcmp(args[cur_arg], "backup")) {
1348 newsrv->state |= SRV_BACKUP;
1349 cur_arg ++;
1350 }
1351 else if (!strcmp(args[cur_arg], "weight")) {
1352 int w;
1353 w = atol(args[cur_arg + 1]);
1354 if (w < 1 || w > 256) {
1355 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1356 file, linenum, newsrv->id, w);
1357 return -1;
1358 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001359 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001360 cur_arg += 2;
1361 }
1362 else if (!strcmp(args[cur_arg], "minconn")) {
1363 newsrv->minconn = atol(args[cur_arg + 1]);
1364 cur_arg += 2;
1365 }
1366 else if (!strcmp(args[cur_arg], "maxconn")) {
1367 newsrv->maxconn = atol(args[cur_arg + 1]);
1368 cur_arg += 2;
1369 }
1370 else if (!strcmp(args[cur_arg], "check")) {
1371 global.maxsock++;
1372 do_check = 1;
1373 cur_arg += 1;
1374 }
1375 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1376 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001377#ifdef CONFIG_HAP_CTTPROXY
1378 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1379 file, linenum, "source", "usesrc");
1380#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001381 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1382 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001383#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 return -1;
1385 }
1386 newsrv->state |= SRV_BIND_SRC;
1387 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1388 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001389 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001390#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001391 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001392 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1393 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001394 return -1;
1395 }
1396 if (!*args[cur_arg + 1]) {
1397 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1398 file, linenum, "usesrc");
1399 return -1;
1400 }
1401 if (!strcmp(args[cur_arg + 1], "client")) {
1402 newsrv->state |= SRV_TPROXY_CLI;
1403 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1404 newsrv->state |= SRV_TPROXY_CIP;
1405 } else {
1406 newsrv->state |= SRV_TPROXY_ADDR;
1407 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1408 }
1409 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1410 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001411#else /* no CTTPROXY support */
1412 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1413 file, linenum, "usesrc");
1414 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001415#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001416 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001417 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001418#ifdef CONFIG_HAP_CTTPROXY
1419 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1420 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1421 file, linenum, "usesrc", "source");
1422 return -1;
1423 }
1424#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001425 else {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001426 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn' and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427 file, linenum, newsrv->id);
1428 return -1;
1429 }
1430 }
1431
1432 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001433 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1434 newsrv->check_port = newsrv->check_addr.sin_port;
1435
Willy Tarreaubaaee002006-06-26 02:48:02 +02001436 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1437 newsrv->check_port = realport; /* by default */
1438 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001439 /* not yet valid, because no port was set on
1440 * the server either. We'll check if we have
1441 * a known port on the first listener.
1442 */
1443 struct listener *l;
1444 l = curproxy->listen;
1445 if (l) {
1446 int port;
1447 port = (l->addr.ss_family == AF_INET6)
1448 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1449 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1450 newsrv->check_port = port;
1451 }
1452 }
1453 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1455 file, linenum, newsrv->id);
1456 return -1;
1457 }
1458 newsrv->state |= SRV_CHECKED;
1459 }
1460
1461 if (newsrv->state & SRV_BACKUP)
1462 curproxy->srv_bck++;
1463 else
1464 curproxy->srv_act++;
1465 }
1466 else if (!strcmp(args[0], "log")) { /* syslog server address */
1467 struct sockaddr_in *sa;
1468 int facility;
1469
1470 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1471 curproxy->logfac1 = global.logfac1;
1472 curproxy->logsrv1 = global.logsrv1;
1473 curproxy->loglev1 = global.loglev1;
1474 curproxy->logfac2 = global.logfac2;
1475 curproxy->logsrv2 = global.logsrv2;
1476 curproxy->loglev2 = global.loglev2;
1477 }
1478 else if (*(args[1]) && *(args[2])) {
1479 int level;
1480
1481 facility = get_log_facility(args[2]);
1482 if (facility < 0) {
1483 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1484 exit(1);
1485 }
1486
1487 level = 7; /* max syslog level = debug */
1488 if (*(args[3])) {
1489 level = get_log_level(args[3]);
1490 if (level < 0) {
1491 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1492 exit(1);
1493 }
1494 }
1495
1496 sa = str2sa(args[1]);
1497 if (!sa->sin_port)
1498 sa->sin_port = htons(SYSLOG_PORT);
1499
1500 if (curproxy->logfac1 == -1) {
1501 curproxy->logsrv1 = *sa;
1502 curproxy->logfac1 = facility;
1503 curproxy->loglev1 = level;
1504 }
1505 else if (curproxy->logfac2 == -1) {
1506 curproxy->logsrv2 = *sa;
1507 curproxy->logfac2 = facility;
1508 curproxy->loglev2 = level;
1509 }
1510 else {
1511 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1512 return -1;
1513 }
1514 }
1515 else {
1516 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1517 file, linenum);
1518 return -1;
1519 }
1520 }
1521 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001522 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1523 return 0;
1524
Willy Tarreaubaaee002006-06-26 02:48:02 +02001525 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001526#ifdef CONFIG_HAP_CTTPROXY
1527 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1528 file, linenum, "source", "usesrc");
1529#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1531 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001532#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001533 return -1;
1534 }
1535
1536 curproxy->source_addr = *str2sa(args[1]);
1537 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001538 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001539#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001540 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1541 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1542 file, linenum, "usesrc");
1543 return -1;
1544 }
1545 if (!*args[3]) {
1546 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1547 file, linenum, "usesrc");
1548 return -1;
1549 }
1550
1551 if (!strcmp(args[3], "client")) {
1552 curproxy->options |= PR_O_TPXY_CLI;
1553 } else if (!strcmp(args[3], "clientip")) {
1554 curproxy->options |= PR_O_TPXY_CIP;
1555 } else {
1556 curproxy->options |= PR_O_TPXY_ADDR;
1557 curproxy->tproxy_addr = *str2sa(args[3]);
1558 }
1559 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001560#else /* no CTTPROXY support */
1561 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1562 file, linenum, "usesrc");
1563 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001564#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001566 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001567#ifdef CONFIG_HAP_CTTPROXY
1568 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1569 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1570 file, linenum, "usesrc", "source");
1571 return -1;
1572 }
1573#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001574 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1575 regex_t *preg;
1576 if (curproxy == &defproxy) {
1577 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1578 return -1;
1579 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001580 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1581 return 0;
1582
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 if (*(args[1]) == 0 || *(args[2]) == 0) {
1584 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1585 file, linenum, args[0]);
1586 return -1;
1587 }
1588
1589 preg = calloc(1, sizeof(regex_t));
1590 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1591 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1592 return -1;
1593 }
1594
1595 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1596 if (err) {
1597 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1598 file, linenum, *err);
1599 return -1;
1600 }
1601 }
1602 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1603 regex_t *preg;
1604 if (curproxy == &defproxy) {
1605 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1606 return -1;
1607 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001608 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1609 return 0;
1610
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611 if (*(args[1]) == 0) {
1612 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1613 return -1;
1614 }
1615
1616 preg = calloc(1, sizeof(regex_t));
1617 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1618 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1619 return -1;
1620 }
1621
1622 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1623 }
1624 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1625 regex_t *preg;
1626 if (curproxy == &defproxy) {
1627 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1628 return -1;
1629 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001630 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1631 return 0;
1632
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 if (*(args[1]) == 0) {
1634 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1635 return -1;
1636 }
1637
1638 preg = calloc(1, sizeof(regex_t));
1639 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1640 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1641 return -1;
1642 }
1643
1644 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1645 }
1646 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1647 regex_t *preg;
1648 if (curproxy == &defproxy) {
1649 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1650 return -1;
1651 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001652 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1653 return 0;
1654
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 if (*(args[1]) == 0) {
1656 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1657 return -1;
1658 }
1659
1660 preg = calloc(1, sizeof(regex_t));
1661 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1662 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1663 return -1;
1664 }
1665
1666 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1667 }
1668 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1669 regex_t *preg;
1670 if (curproxy == &defproxy) {
1671 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1672 return -1;
1673 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001674 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1675 return 0;
1676
Willy Tarreaubaaee002006-06-26 02:48:02 +02001677 if (*(args[1]) == 0) {
1678 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1679 return -1;
1680 }
1681
1682 preg = calloc(1, sizeof(regex_t));
1683 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1684 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1685 return -1;
1686 }
1687
1688 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1689 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001690 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1691 regex_t *preg;
1692 if (curproxy == &defproxy) {
1693 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1694 return -1;
1695 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001696 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1697 return 0;
1698
Willy Tarreaub8750a82006-09-03 09:56:00 +02001699 if (*(args[1]) == 0) {
1700 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1701 return -1;
1702 }
1703
1704 preg = calloc(1, sizeof(regex_t));
1705 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1706 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1707 return -1;
1708 }
1709
1710 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1711 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001712 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1713 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001714 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001715 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1716 return -1;
1717 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001718 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1719 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001720
Willy Tarreau977b8e42006-12-29 14:19:17 +01001721 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001722 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1723 file, linenum, args[0]);
1724 return -1;
1725 }
1726
1727 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001728 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001729 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1730 }
1731
1732 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1733 }
1734 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1735 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001736 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001737 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1738 return -1;
1739 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001740 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1741 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001742
Willy Tarreau977b8e42006-12-29 14:19:17 +01001743 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001744 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1745 file, linenum, args[0]);
1746 return -1;
1747 }
1748
1749 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001750 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001751 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1752 }
1753
1754 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1755 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001756 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1757 regex_t *preg;
1758 if (curproxy == &defproxy) {
1759 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1760 return -1;
1761 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001762 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1763 return 0;
1764
Willy Tarreaubaaee002006-06-26 02:48:02 +02001765 if (*(args[1]) == 0 || *(args[2]) == 0) {
1766 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1767 file, linenum, args[0]);
1768 return -1;
1769 }
1770
1771 preg = calloc(1, sizeof(regex_t));
1772 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1773 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1774 return -1;
1775 }
1776
1777 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1778 if (err) {
1779 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1780 file, linenum, *err);
1781 return -1;
1782 }
1783 }
1784 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1785 regex_t *preg;
1786 if (curproxy == &defproxy) {
1787 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1788 return -1;
1789 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001790 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1791 return 0;
1792
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793 if (*(args[1]) == 0) {
1794 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1795 return -1;
1796 }
1797
1798 preg = calloc(1, sizeof(regex_t));
1799 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1800 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1801 return -1;
1802 }
1803
1804 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1805 }
1806 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1807 regex_t *preg;
1808 if (curproxy == &defproxy) {
1809 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1810 return -1;
1811 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001812 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1813 return 0;
1814
Willy Tarreaubaaee002006-06-26 02:48:02 +02001815 if (*(args[1]) == 0) {
1816 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1817 return -1;
1818 }
1819
1820 preg = calloc(1, sizeof(regex_t));
1821 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1822 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1823 return -1;
1824 }
1825
1826 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1827 }
1828 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1829 regex_t *preg;
1830 if (curproxy == &defproxy) {
1831 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1832 return -1;
1833 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001834 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1835 return 0;
1836
Willy Tarreaubaaee002006-06-26 02:48:02 +02001837 if (*(args[1]) == 0) {
1838 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1839 return -1;
1840 }
1841
1842 preg = calloc(1, sizeof(regex_t));
1843 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1844 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1845 return -1;
1846 }
1847
1848 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1849 }
1850 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1851 regex_t *preg;
1852 if (curproxy == &defproxy) {
1853 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1854 return -1;
1855 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001856 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1857 return 0;
1858
Willy Tarreaubaaee002006-06-26 02:48:02 +02001859 if (*(args[1]) == 0) {
1860 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1861 return -1;
1862 }
1863
1864 preg = calloc(1, sizeof(regex_t));
1865 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1866 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1867 return -1;
1868 }
1869
1870 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1871 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001872 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1873 regex_t *preg;
1874 if (curproxy == &defproxy) {
1875 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1876 return -1;
1877 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001878 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1879 return 0;
1880
Willy Tarreaub8750a82006-09-03 09:56:00 +02001881 if (*(args[1]) == 0) {
1882 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1883 return -1;
1884 }
1885
1886 preg = calloc(1, sizeof(regex_t));
1887 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1888 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1889 return -1;
1890 }
1891
1892 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1895 if (curproxy == &defproxy) {
1896 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1897 return -1;
1898 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001899 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1900 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901
1902 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
1903 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1904 return 0;
1905 }
1906
1907 if (*(args[1]) == 0) {
1908 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1909 return -1;
1910 }
1911
1912 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
1913 }
1914 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
1915 regex_t *preg;
1916
1917 if (*(args[1]) == 0 || *(args[2]) == 0) {
1918 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1919 file, linenum, args[0]);
1920 return -1;
1921 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001922 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1923 return 0;
1924
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 preg = calloc(1, sizeof(regex_t));
1926 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1927 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1928 return -1;
1929 }
1930
1931 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1932 if (err) {
1933 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1934 file, linenum, *err);
1935 return -1;
1936 }
1937 }
1938 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
1939 regex_t *preg;
1940 if (curproxy == &defproxy) {
1941 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1942 return -1;
1943 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001944 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1945 return 0;
1946
Willy Tarreaubaaee002006-06-26 02:48:02 +02001947 if (*(args[1]) == 0) {
1948 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1949 return -1;
1950 }
1951
1952 preg = calloc(1, sizeof(regex_t));
1953 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1954 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1955 return -1;
1956 }
1957
1958 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
1959 if (err) {
1960 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1961 file, linenum, *err);
1962 return -1;
1963 }
1964 }
1965 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
1966 regex_t *preg;
1967 if (curproxy == &defproxy) {
1968 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1969 return -1;
1970 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001971 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1972 return 0;
1973
Willy Tarreaubaaee002006-06-26 02:48:02 +02001974 if (*(args[1]) == 0) {
1975 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1976 return -1;
1977 }
1978
1979 preg = calloc(1, sizeof(regex_t));
1980 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1981 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1982 return -1;
1983 }
1984
1985 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
1986 if (err) {
1987 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1988 file, linenum, *err);
1989 return -1;
1990 }
1991 }
1992 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
1993 regex_t *preg;
1994 if (curproxy == &defproxy) {
1995 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1996 return -1;
1997 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001998 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1999 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002000
2001 if (*(args[1]) == 0 || *(args[2]) == 0) {
2002 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2003 file, linenum, args[0]);
2004 return -1;
2005 }
2006
2007 preg = calloc(1, sizeof(regex_t));
2008 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2009 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2010 return -1;
2011 }
2012
2013 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2014 if (err) {
2015 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2016 file, linenum, *err);
2017 return -1;
2018 }
2019 }
2020 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2021 regex_t *preg;
2022 if (curproxy == &defproxy) {
2023 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2024 return -1;
2025 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002026 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2027 return 0;
2028
Willy Tarreaubaaee002006-06-26 02:48:02 +02002029 if (*(args[1]) == 0) {
2030 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2031 return -1;
2032 }
2033
2034 preg = calloc(1, sizeof(regex_t));
2035 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2036 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2037 return -1;
2038 }
2039
2040 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2041 if (err) {
2042 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2043 file, linenum, *err);
2044 return -1;
2045 }
2046 }
2047 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2048 regex_t *preg;
2049 if (curproxy == &defproxy) {
2050 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2051 return -1;
2052 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002053 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2054 return 0;
2055
Willy Tarreaubaaee002006-06-26 02:48:02 +02002056 if (*(args[1]) == 0) {
2057 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2058 return -1;
2059 }
2060
2061 preg = calloc(1, sizeof(regex_t));
2062 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2063 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2064 return -1;
2065 }
2066
2067 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2068 if (err) {
2069 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2070 file, linenum, *err);
2071 return -1;
2072 }
2073 }
2074 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2075 if (curproxy == &defproxy) {
2076 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2077 return -1;
2078 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002079 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2080 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081
2082 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2083 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2084 return 0;
2085 }
2086
2087 if (*(args[1]) == 0) {
2088 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2089 return -1;
2090 }
2091
2092 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2093 }
2094 else if (!strcmp(args[0], "errorloc") ||
2095 !strcmp(args[0], "errorloc302") ||
2096 !strcmp(args[0], "errorloc303")) { /* error location */
2097 int errnum, errlen;
2098 char *err;
2099
Willy Tarreau977b8e42006-12-29 14:19:17 +01002100 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2101 return 0;
2102
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002104 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002105 return -1;
2106 }
2107
2108 errnum = atol(args[1]);
2109 if (!strcmp(args[0], "errorloc303")) {
2110 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2111 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2112 } else {
2113 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2114 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2115 }
2116
Willy Tarreau0f772532006-12-23 20:51:41 +01002117 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2118 if (http_err_codes[rc] == errnum) {
2119 if (curproxy->errmsg[rc].str)
2120 free(curproxy->errmsg[rc].str);
2121 curproxy->errmsg[rc].str = err;
2122 curproxy->errmsg[rc].len = errlen;
2123 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002124 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002126
2127 if (rc >= HTTP_ERR_SIZE) {
2128 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2129 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002130 free(err);
2131 }
2132 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002133 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2134 int errnum, errlen, fd;
2135 char *err;
2136 struct stat stat;
2137
2138 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2139 return 0;
2140
2141 if (*(args[2]) == 0) {
2142 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2143 return -1;
2144 }
2145
2146 fd = open(args[2], O_RDONLY);
2147 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2148 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2149 file, linenum, args[2], args[1]);
2150 if (fd >= 0)
2151 close(fd);
2152 return -1;
2153 }
2154
2155 if (stat.st_size <= BUFSIZE) {
2156 errlen = stat.st_size;
2157 } else {
2158 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2159 file, linenum, args[2], BUFSIZE);
2160 errlen = BUFSIZE;
2161 }
2162
2163 err = malloc(errlen); /* malloc() must succeed during parsing */
2164 errnum = read(fd, err, errlen);
2165 if (errnum != errlen) {
2166 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2167 file, linenum, args[2], args[1]);
2168 close(fd);
2169 free(err);
2170 return -1;
2171 }
2172 close(fd);
2173
2174 errnum = atol(args[1]);
2175 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2176 if (http_err_codes[rc] == errnum) {
2177 if (curproxy->errmsg[rc].str)
2178 free(curproxy->errmsg[rc].str);
2179 curproxy->errmsg[rc].str = err;
2180 curproxy->errmsg[rc].len = errlen;
2181 break;
2182 }
2183 }
2184
2185 if (rc >= HTTP_ERR_SIZE) {
2186 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2187 file, linenum, errnum);
2188 free(err);
2189 }
2190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002191 else {
2192 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2193 return -1;
2194 }
2195 return 0;
2196}
2197
2198
2199/*
2200 * This function reads and parses the configuration file given in the argument.
2201 * returns 0 if OK, -1 if error.
2202 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002203int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204{
2205 char thisline[256];
2206 char *line;
2207 FILE *f;
2208 int linenum = 0;
2209 char *end;
Willy Tarreau540abe42007-05-02 20:50:16 +02002210 char *args[MAX_LINE_ARGS + 1];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002211 int arg;
2212 int cfgerr = 0;
Willy Tarreau80587432006-12-24 17:47:20 +01002213 int nbchk, mininter;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002214 int confsect = CFG_NONE;
2215
2216 struct proxy *curproxy = NULL;
2217 struct server *newsrv = NULL;
2218
2219 if ((f=fopen(file,"r")) == NULL)
2220 return -1;
2221
2222 init_default_instance();
2223
2224 while (fgets(line = thisline, sizeof(thisline), f) != NULL) {
2225 linenum++;
2226
2227 end = line + strlen(line);
2228
2229 /* skip leading spaces */
2230 while (isspace((int)*line))
2231 line++;
2232
2233 arg = 0;
2234 args[arg] = line;
2235
2236 while (*line && arg < MAX_LINE_ARGS) {
2237 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2238 * C equivalent value. Other combinations left unchanged (eg: \1).
2239 */
2240 if (*line == '\\') {
2241 int skip = 0;
2242 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2243 *line = line[1];
2244 skip = 1;
2245 }
2246 else if (line[1] == 'r') {
2247 *line = '\r';
2248 skip = 1;
2249 }
2250 else if (line[1] == 'n') {
2251 *line = '\n';
2252 skip = 1;
2253 }
2254 else if (line[1] == 't') {
2255 *line = '\t';
2256 skip = 1;
2257 }
2258 else if (line[1] == 'x') {
2259 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2260 unsigned char hex1, hex2;
2261 hex1 = toupper(line[2]) - '0';
2262 hex2 = toupper(line[3]) - '0';
2263 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2264 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2265 *line = (hex1<<4) + hex2;
2266 skip = 3;
2267 }
2268 else {
2269 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2270 return -1;
2271 }
2272 }
2273 if (skip) {
2274 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2275 end -= skip;
2276 }
2277 line++;
2278 }
2279 else if (*line == '#' || *line == '\n' || *line == '\r') {
2280 /* end of string, end of loop */
2281 *line = 0;
2282 break;
2283 }
2284 else if (isspace((int)*line)) {
2285 /* a non-escaped space is an argument separator */
2286 *line++ = 0;
2287 while (isspace((int)*line))
2288 line++;
2289 args[++arg] = line;
2290 }
2291 else {
2292 line++;
2293 }
2294 }
2295
2296 /* empty line */
2297 if (!**args)
2298 continue;
2299
Willy Tarreau540abe42007-05-02 20:50:16 +02002300 /* zero out remaining args and ensure that at least one entry
2301 * is zeroed out.
2302 */
2303 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002304 args[arg] = line;
2305 }
2306
Willy Tarreau977b8e42006-12-29 14:19:17 +01002307 if (!strcmp(args[0], "listen") ||
2308 !strcmp(args[0], "frontend") ||
2309 !strcmp(args[0], "backend") ||
2310 !strcmp(args[0], "ruleset") ||
2311 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 confsect = CFG_LISTEN;
2313 else if (!strcmp(args[0], "global")) /* global config */
2314 confsect = CFG_GLOBAL;
2315 /* else it's a section keyword */
2316
2317 switch (confsect) {
2318 case CFG_LISTEN:
2319 if (cfg_parse_listen(file, linenum, args) < 0)
2320 return -1;
2321 break;
2322 case CFG_GLOBAL:
2323 if (cfg_parse_global(file, linenum, args) < 0)
2324 return -1;
2325 break;
2326 default:
2327 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2328 return -1;
2329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 }
2331 fclose(f);
2332
2333 /*
2334 * Now, check for the integrity of all that we have collected.
2335 */
2336
2337 /* will be needed further to delay some tasks */
2338 tv_now(&now);
2339
2340 if ((curproxy = proxy) == NULL) {
2341 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2342 file);
2343 return -1;
2344 }
2345
2346 while (curproxy != NULL) {
2347 if (curproxy->state == PR_STSTOPPED) {
2348 curproxy = curproxy->next;
2349 continue;
2350 }
2351
Willy Tarreau977b8e42006-12-29 14:19:17 +01002352 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2353 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 +01002354 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002355 cfgerr++;
2356 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002357 else if (curproxy->cap & PR_CAP_BE &&
2358 ((curproxy->mode != PR_MODE_HEALTH) &&
2359 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
2360 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2361 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 +01002362 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 cfgerr++;
2364 }
2365 else if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
2366 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002367 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002368 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 cfgerr++;
2370 }
2371#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2372 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002373 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002374 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 cfgerr++;
2376 }
2377#endif
2378 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002379 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002380 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 }
2382 }
2383 else if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2384 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002385 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002386 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387 }
2388 if ((newsrv = curproxy->srv) != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002389 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002390 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 }
2392 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002393 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002394 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 }
2396 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002397 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002398 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002400 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002401 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002402 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002403 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002404 if (curproxy->options & PR_O_BALANCE_UH) {
2405 curproxy->options &= ~PR_O_BALANCE;
2406 curproxy->options |= PR_O_BALANCE_RR;
2407
2408 Warning("parsing %s : URI hash will be ignored for %s '%s'. Falling back to round robin.\n",
2409 file, proxy_type_str(curproxy), curproxy->id);
2410 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 }
2412 else if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
2413 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2414 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2415 file, curproxy->id);
2416 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002417 }
2418 }
2419
2420 /* if a default backend was specified, let's find it */
2421 if (curproxy->defbe.name) {
2422 struct proxy *target;
2423
2424 for (target = proxy; target != NULL; target = target->next) {
2425 if (strcmp(target->id, curproxy->defbe.name) == 0)
2426 break;
2427 }
2428 if (target == NULL) {
2429 Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n",
2430 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2431 cfgerr++;
2432 } else if (target == curproxy) {
2433 Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
2434 cfgerr++;
2435 } else if (!(target->cap & PR_CAP_BE)) {
2436 Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n",
2437 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2438 cfgerr++;
2439 } else if (target->mode != curproxy->mode) {
2440 Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
2441 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2442 cfgerr++;
2443 } else {
2444 free(curproxy->defbe.name);
2445 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446 }
2447 }
2448
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002449 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002450 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2451 /* map jump target for ACT_SETBE in req_rep chain */
2452 struct hdr_exp *exp;
2453 struct proxy *target;
2454 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
2455 if (exp->action != ACT_SETBE)
2456 continue;
2457 for (target = proxy; target != NULL; target = target->next) {
2458 if (strcmp(target->id, exp->replace) == 0)
2459 break;
2460 }
2461 if (target == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002462 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002463 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaua496b602006-12-17 23:15:24 +01002464 cfgerr++;
2465 } else if (target == curproxy) {
2466 Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
2467 cfgerr++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002468 } else if (!(target->cap & PR_CAP_BE)) {
2469 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002470 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002471 cfgerr++;
2472 } else if (target->mode != PR_MODE_HTTP) {
2473 Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002474 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002475 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002476 } else {
2477 free((void *)exp->replace);
2478 exp->replace = (const char *)target;
2479 }
2480 }
2481 }
Willy Tarreau2738a142006-07-08 17:28:09 +02002482 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002483 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2484 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2485 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002486 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002487 " | While not properly invalid, you will certainly encounter various problems\n"
2488 " | with such a configuration. To fix this, please ensure that all following\n"
2489 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002490 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002491 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002492
2493 if (curproxy->options & PR_O_SSL3_CHK) {
2494 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2495 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2496 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2497 }
2498
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002499 /* The small pools required for the capture lists */
2500 if (curproxy->nb_req_cap)
2501 curproxy->req_cap_pool = create_pool("ptrcap",
2502 curproxy->nb_req_cap * sizeof(char *),
2503 MEM_F_SHARED);
2504 if (curproxy->nb_rsp_cap)
2505 curproxy->rsp_cap_pool = create_pool("ptrcap",
2506 curproxy->nb_rsp_cap * sizeof(char *),
2507 MEM_F_SHARED);
2508
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002509 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2510 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2511 MEM_F_SHARED);
2512
Willy Tarreau86034312006-12-29 00:10:33 +01002513 /* for backwards compatibility with "listen" instances, if
2514 * fullconn is not set but maxconn is set, then maxconn
2515 * is used.
2516 */
2517 if (!curproxy->fullconn)
2518 curproxy->fullconn = curproxy->maxconn;
2519
Willy Tarreaubaaee002006-06-26 02:48:02 +02002520 /* first, we will invert the servers list order */
2521 newsrv = NULL;
2522 while (curproxy->srv) {
2523 struct server *next;
2524
2525 next = curproxy->srv->next;
2526 curproxy->srv->next = newsrv;
2527 newsrv = curproxy->srv;
2528 if (!next)
2529 break;
2530 curproxy->srv = next;
2531 }
2532
2533 /* now, newsrv == curproxy->srv */
2534 if (newsrv) {
2535 struct server *srv;
2536 int pgcd;
2537 int act, bck;
2538
2539 /* We will factor the weights to reduce the table,
2540 * using Euclide's largest common divisor algorithm
2541 */
Willy Tarreau417fae02007-03-25 21:16:40 +02002542 pgcd = newsrv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2544 int t, w;
2545
Willy Tarreau417fae02007-03-25 21:16:40 +02002546 w = srv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 while (w) {
2548 t = pgcd % w;
2549 pgcd = w;
2550 w = t;
2551 }
2552 }
2553
2554 act = bck = 0;
2555 for (srv = newsrv; srv; srv = srv->next) {
Willy Tarreau417fae02007-03-25 21:16:40 +02002556 srv->eweight = srv->uweight / pgcd;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 if (srv->state & SRV_BACKUP)
Willy Tarreau417fae02007-03-25 21:16:40 +02002558 bck += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 else
Willy Tarreau417fae02007-03-25 21:16:40 +02002560 act += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 }
2562
2563 /* this is the largest map we will ever need for this servers list */
2564 if (act < bck)
2565 act = bck;
2566
2567 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2568 /* recounts servers and their weights */
2569 recount_servers(curproxy);
2570 recalc_server_map(curproxy);
2571 }
2572
2573 if (curproxy->options & PR_O_LOGASAP)
2574 curproxy->to_log &= ~LW_BYTES;
2575
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 /*
2577 * If this server supports a maxconn parameter, it needs a dedicated
2578 * tasks to fill the emptied slots when a connection leaves.
2579 */
2580 newsrv = curproxy->srv;
2581 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002582 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 /* Only 'minconn' was specified, or it was higher than or equal
2584 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2585 * this will avoid further useless expensive computations.
2586 */
2587 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002588 } else if (newsrv->maxconn && !newsrv->minconn) {
2589 /* minconn was not specified, so we set it to maxconn */
2590 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002591 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2592 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002593 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002594 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 }
2596
2597 if (newsrv->maxconn > 0) {
2598 struct task *t;
2599
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002600 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002601 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2602 return -1;
2603 }
2604
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002605 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002606 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 t->state = TASK_IDLE;
2608 t->process = process_srv_queue;
2609 t->context = newsrv;
2610 newsrv->queue_mgt = t;
2611
2612 /* never run it unless specifically woken up */
2613 tv_eternity(&t->expire);
2614 task_queue(t);
2615 }
2616 newsrv = newsrv->next;
2617 }
2618
2619 /* now we'll start this proxy's health checks if any */
2620 /* 1- count the checkers to run simultaneously */
2621 nbchk = 0;
2622 mininter = 0;
2623 newsrv = curproxy->srv;
2624 while (newsrv != NULL) {
2625 if (newsrv->state & SRV_CHECKED) {
2626 if (!mininter || mininter > newsrv->inter)
2627 mininter = newsrv->inter;
2628 nbchk++;
2629 }
2630 newsrv = newsrv->next;
2631 }
2632
2633 /* 2- start them as far as possible from each others while respecting
2634 * their own intervals. For this, we will start them after their own
2635 * interval added to the min interval divided by the number of servers,
2636 * weighted by the server's position in the list.
2637 */
2638 if (nbchk > 0) {
2639 struct task *t;
2640 int srvpos;
2641
2642 newsrv = curproxy->srv;
2643 srvpos = 0;
2644 while (newsrv != NULL) {
2645 /* should this server be checked ? */
2646 if (newsrv->state & SRV_CHECKED) {
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002647 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002648 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2649 return -1;
2650 }
2651
Willy Tarreau964c9362007-01-07 00:38:00 +01002652 t->wq = NULL;
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002653 t->qlist.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002654 t->state = TASK_IDLE;
2655 t->process = process_chk;
2656 t->context = newsrv;
2657
2658 /* check this every ms */
Willy Tarreau42aae5c2007-04-29 17:43:56 +02002659 tv_ms_add(&t->expire, &now,
2660 newsrv->inter + mininter * srvpos / nbchk);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002661 task_queue(t);
2662 //task_wakeup(&rq, t);
2663 srvpos++;
2664 }
2665 newsrv = newsrv->next;
2666 }
2667 }
2668
2669 curproxy = curproxy->next;
2670 }
2671 if (cfgerr > 0) {
2672 Alert("Errors found in configuration file, aborting.\n");
2673 return -1;
2674 }
2675 else
2676 return 0;
2677}
2678
2679
2680
2681/*
2682 * Local variables:
2683 * c-indent-level: 8
2684 * c-basic-offset: 8
2685 * End:
2686 */