blob: f3aefa0d551b425649fccf91795b046fb3cc5f29 [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 Tarreau55ea7572007-06-17 19:56:27 +0200513 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200514
Willy Tarreauee991362007-05-14 14:37:50 +0200515 /* Timeouts are defined as -1, so we cannot use the zeroed area
516 * as a default value.
517 */
518 tv_eternity(&curproxy->clitimeout);
519 tv_eternity(&curproxy->srvtimeout);
520 tv_eternity(&curproxy->contimeout);
521 tv_eternity(&curproxy->appsession_timeout);
522
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100524 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200525
526 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100527 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200528 curproxy->listen = str2listener(args[2], curproxy->listen);
529 if (!curproxy->listen)
530 return -1;
531 global.maxsock++;
532 }
533
534 /* set default values */
535 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200536 curproxy->options = defproxy.options;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200537 curproxy->except_net = defproxy.except_net;
538 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200539
Willy Tarreau977b8e42006-12-29 14:19:17 +0100540 if (curproxy->cap & PR_CAP_FE) {
541 curproxy->maxconn = defproxy.maxconn;
542
543 /* initialize error relocations */
544 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
545 if (defproxy.errmsg[rc].str)
546 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
547 }
548
549 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
550 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200551
Willy Tarreau977b8e42006-12-29 14:19:17 +0100552 if (curproxy->cap & PR_CAP_BE) {
553 curproxy->fullconn = defproxy.fullconn;
554 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200555
Willy Tarreau977b8e42006-12-29 14:19:17 +0100556 if (defproxy.check_req)
557 curproxy->check_req = strdup(defproxy.check_req);
558 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200559
Willy Tarreau977b8e42006-12-29 14:19:17 +0100560 if (defproxy.cookie_name)
561 curproxy->cookie_name = strdup(defproxy.cookie_name);
562 curproxy->cookie_len = defproxy.cookie_len;
563 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200564
Willy Tarreau977b8e42006-12-29 14:19:17 +0100565 if (curproxy->cap & PR_CAP_RS) {
566 if (defproxy.capture_name)
567 curproxy->capture_name = strdup(defproxy.capture_name);
568 curproxy->capture_namelen = defproxy.capture_namelen;
569 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200571
Willy Tarreau977b8e42006-12-29 14:19:17 +0100572 if (curproxy->cap & PR_CAP_FE) {
573 curproxy->clitimeout = defproxy.clitimeout;
574 curproxy->uri_auth = defproxy.uri_auth;
575 curproxy->mon_net = defproxy.mon_net;
576 curproxy->mon_mask = defproxy.mon_mask;
577 if (defproxy.monitor_uri)
578 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
579 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100580 if (defproxy.defbe.name)
581 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100582 }
583
584 if (curproxy->cap & PR_CAP_BE) {
585 curproxy->contimeout = defproxy.contimeout;
586 curproxy->srvtimeout = defproxy.srvtimeout;
587 curproxy->source_addr = defproxy.source_addr;
588 }
589
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 curproxy->mode = defproxy.mode;
591 curproxy->logfac1 = defproxy.logfac1;
592 curproxy->logsrv1 = defproxy.logsrv1;
593 curproxy->loglev1 = defproxy.loglev1;
594 curproxy->logfac2 = defproxy.logfac2;
595 curproxy->logsrv2 = defproxy.logsrv2;
596 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200597 curproxy->grace = defproxy.grace;
Willy Tarreau1c47f852006-07-09 08:22:27 +0200598
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 return 0;
600 }
601 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
602 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100603 /* FIXME-20070101: we should do this too at the end of the
604 * config parsing to free all default values.
605 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200606 if (defproxy.check_req) free(defproxy.check_req);
607 if (defproxy.cookie_name) free(defproxy.cookie_name);
608 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200609 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100610 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100611
612 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
613 if (defproxy.errmsg[rc].len)
614 free(defproxy.errmsg[rc].str);
615 }
616
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 /* we cannot free uri_auth because it might already be used */
618 init_default_instance();
619 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100620 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200621 return 0;
622 }
623 else if (curproxy == NULL) {
624 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
625 return -1;
626 }
627
Willy Tarreau977b8e42006-12-29 14:19:17 +0100628
629 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 if (!strcmp(args[0], "bind")) { /* new listen addresses */
631 if (curproxy == &defproxy) {
632 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
633 return -1;
634 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100635 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
636 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200637
638 if (strchr(args[1], ':') == NULL) {
639 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
640 file, linenum, args[0]);
641 return -1;
642 }
643 curproxy->listen = str2listener(args[1], curproxy->listen);
644 if (!curproxy->listen)
645 return -1;
646 global.maxsock++;
647 return 0;
648 }
649 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
650 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
651 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
652 file, linenum, args[0]);
653 return -1;
654 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100655 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
656 return 0;
657
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658 /* flush useless bits */
659 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
660 return 0;
661 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200662 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100663 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
664 return 0;
665
Willy Tarreau1c47f852006-07-09 08:22:27 +0200666 if (!*args[1]) {
667 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
668 file, linenum, args[0]);
669 return -1;
670 }
671
672 if (curproxy->monitor_uri != NULL)
673 free(curproxy->monitor_uri);
674
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100675 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200676 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100677 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200678 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
679
680 return 0;
681 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
683 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
684 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
685 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
686 else {
687 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
688 return -1;
689 }
690 }
691 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
692 curproxy->state = PR_STSTOPPED;
693 }
694 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
695 curproxy->state = PR_STNEW;
696 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200697 else if (!strcmp(args[0], "acl")) { /* add an ACL */
698 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
699 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
700 file, linenum, args[1]);
701 return -1;
702 }
703 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200704 else if (!strcmp(args[0], "cookie")) { /* cookie name */
705 int cur_arg;
706 // if (curproxy == &defproxy) {
707 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
708 // return -1;
709 // }
710
Willy Tarreau977b8e42006-12-29 14:19:17 +0100711 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
712 return 0;
713
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714 if (curproxy->cookie_name != NULL) {
715 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
716 // file, linenum);
717 // return 0;
718 free(curproxy->cookie_name);
719 }
720
721 if (*(args[1]) == 0) {
722 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
723 file, linenum, args[0]);
724 return -1;
725 }
726 curproxy->cookie_name = strdup(args[1]);
727 curproxy->cookie_len = strlen(curproxy->cookie_name);
728
729 cur_arg = 2;
730 while (*(args[cur_arg])) {
731 if (!strcmp(args[cur_arg], "rewrite")) {
732 curproxy->options |= PR_O_COOK_RW;
733 }
734 else if (!strcmp(args[cur_arg], "indirect")) {
735 curproxy->options |= PR_O_COOK_IND;
736 }
737 else if (!strcmp(args[cur_arg], "insert")) {
738 curproxy->options |= PR_O_COOK_INS;
739 }
740 else if (!strcmp(args[cur_arg], "nocache")) {
741 curproxy->options |= PR_O_COOK_NOC;
742 }
743 else if (!strcmp(args[cur_arg], "postonly")) {
744 curproxy->options |= PR_O_COOK_POST;
745 }
746 else if (!strcmp(args[cur_arg], "prefix")) {
747 curproxy->options |= PR_O_COOK_PFX;
748 }
749 else {
750 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
751 file, linenum, args[0]);
752 return -1;
753 }
754 cur_arg++;
755 }
756 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
757 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
758 file, linenum);
759 return -1;
760 }
761
762 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
763 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
764 file, linenum);
765 return -1;
766 }
767 }/* end else if (!strcmp(args[0], "cookie")) */
768 else if (!strcmp(args[0], "appsession")) { /* cookie name */
769 // if (curproxy == &defproxy) {
770 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
771 // return -1;
772 // }
773
Willy Tarreau977b8e42006-12-29 14:19:17 +0100774 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
775 return 0;
776
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 if (curproxy->appsession_name != NULL) {
778 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
779 // file, linenum);
780 // return 0;
781 free(curproxy->appsession_name);
782 }
783
784 if (*(args[5]) == 0) {
785 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
786 file, linenum, args[0]);
787 return -1;
788 }
789 have_appsession = 1;
790 curproxy->appsession_name = strdup(args[1]);
791 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
792 curproxy->appsession_len = atoi(args[3]);
Willy Tarreauee991362007-05-14 14:37:50 +0200793 val = atoi(args[5]);
794 if (val > 0)
795 __tv_from_ms(&curproxy->appsession_timeout, val);
796 else
797 tv_eternity(&curproxy->appsession_timeout);
798
Willy Tarreaubaaee002006-06-26 02:48:02 +0200799 rc = chtbl_init(&(curproxy->htbl_proxy), TBLSIZ, hashpjw, match_str, destroy);
800 if (rc) {
801 Alert("Error Init Appsession Hashtable.\n");
802 return -1;
803 }
804 } /* Url App Session */
805 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100806 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
807 return 0;
808
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
810 // if (curproxy == &defproxy) {
811 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
812 // return -1;
813 // }
814
815 if (curproxy->capture_name != NULL) {
816 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
817 // file, linenum, args[0]);
818 // return 0;
819 free(curproxy->capture_name);
820 }
821
822 if (*(args[4]) == 0) {
823 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
824 file, linenum, args[0]);
825 return -1;
826 }
827 curproxy->capture_name = strdup(args[2]);
828 curproxy->capture_namelen = strlen(curproxy->capture_name);
829 curproxy->capture_len = atol(args[4]);
830 if (curproxy->capture_len >= CAPTURE_LEN) {
831 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
832 file, linenum, CAPTURE_LEN - 1);
833 curproxy->capture_len = CAPTURE_LEN - 1;
834 }
835 curproxy->to_log |= LW_COOKIE;
836 }
837 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
838 struct cap_hdr *hdr;
839
840 if (curproxy == &defproxy) {
841 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
842 return -1;
843 }
844
845 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
846 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
847 file, linenum, args[0], args[1]);
848 return -1;
849 }
850
851 hdr = calloc(sizeof(struct cap_hdr), 1);
852 hdr->next = curproxy->req_cap;
853 hdr->name = strdup(args[3]);
854 hdr->namelen = strlen(args[3]);
855 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200856 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200857 hdr->index = curproxy->nb_req_cap++;
858 curproxy->req_cap = hdr;
859 curproxy->to_log |= LW_REQHDR;
860 }
861 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
862 struct cap_hdr *hdr;
863
864 if (curproxy == &defproxy) {
865 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
866 return -1;
867 }
868
869 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
870 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
871 file, linenum, args[0], args[1]);
872 return -1;
873 }
874 hdr = calloc(sizeof(struct cap_hdr), 1);
875 hdr->next = curproxy->rsp_cap;
876 hdr->name = strdup(args[3]);
877 hdr->namelen = strlen(args[3]);
878 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200879 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200880 hdr->index = curproxy->nb_rsp_cap++;
881 curproxy->rsp_cap = hdr;
882 curproxy->to_log |= LW_RSPHDR;
883 }
884 else {
885 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
886 file, linenum, args[0]);
887 return -1;
888 }
889 }
890 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200891 if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
893 return 0;
894 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100895 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
896 return 0;
897
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898 if (*(args[1]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
900 file, linenum, args[0]);
901 return -1;
902 }
Willy Tarreauee991362007-05-14 14:37:50 +0200903 val = atoi(args[1]);
904 if (val > 0)
905 __tv_from_ms(&curproxy->contimeout, val);
906 else
907 tv_eternity(&curproxy->contimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908 }
909 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200910 if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200911 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
912 file, linenum, args[0]);
913 return 0;
914 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100915 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
916 return 0;
917
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 if (*(args[1]) == 0) {
919 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
920 file, linenum, args[0]);
921 return -1;
922 }
Willy Tarreauee991362007-05-14 14:37:50 +0200923 val = atoi(args[1]);
924 if (val > 0)
925 __tv_from_ms(&curproxy->clitimeout, val);
926 else
927 tv_eternity(&curproxy->clitimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200928 }
929 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200930 if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
932 return 0;
933 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100934 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
935 return 0;
936
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 if (*(args[1]) == 0) {
938 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
939 file, linenum, args[0]);
940 return -1;
941 }
Willy Tarreauee991362007-05-14 14:37:50 +0200942 val = atoi(args[1]);
943 if (val > 0)
944 __tv_from_ms(&curproxy->srvtimeout, val);
945 else
946 tv_eternity(&curproxy->srvtimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947 }
948 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100949 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
950 return 0;
951
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 if (*(args[1]) == 0) {
953 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
954 file, linenum, args[0]);
955 return -1;
956 }
957 curproxy->conn_retries = atol(args[1]);
958 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200959 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
960 int pol = ACL_COND_NONE;
961 struct acl_cond *cond;
962
963 if (!strcmp(args[1], "if"))
964 pol = ACL_COND_IF;
965 else if (!strcmp(args[1], "unless"))
966 pol = ACL_COND_UNLESS;
967
968 if (pol == ACL_COND_NONE) {
969 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
970 file, linenum, args[0]);
971 return -1;
972 }
973
974 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
975 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
976 file, linenum);
977 return -1;
978 }
979 LIST_ADDQ(&curproxy->block_cond, &cond->list);
980 }
Willy Tarreau55ea7572007-06-17 19:56:27 +0200981 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
982 int pol = ACL_COND_NONE;
983 struct acl_cond *cond;
984 struct switching_rule *rule;
985
986 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
987 return 0;
988
989 if (*(args[1]) == 0) {
990 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
991 return -1;
992 }
993
994 if (!strcmp(args[2], "if"))
995 pol = ACL_COND_IF;
996 else if (!strcmp(args[2], "unless"))
997 pol = ACL_COND_UNLESS;
998
999 if (pol == ACL_COND_NONE) {
1000 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1001 file, linenum, args[0]);
1002 return -1;
1003 }
1004
1005 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1006 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1007 file, linenum);
1008 return -1;
1009 }
1010
1011 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1012 rule->cond = cond;
1013 rule->be.name = strdup(args[1]);
1014 LIST_INIT(&rule->list);
1015 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1016 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001018 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1019 return 0;
1020
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1022 curproxy->uri_auth = NULL; /* we must detach from the default config */
1023
1024 if (*(args[1]) == 0) {
1025 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1026 return -1;
1027 } else if (!strcmp(args[1], "uri")) {
1028 if (*(args[2]) == 0) {
1029 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1030 return -1;
1031 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1032 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1033 return -1;
1034 }
1035 } else if (!strcmp(args[1], "realm")) {
1036 if (*(args[2]) == 0) {
1037 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1038 return -1;
1039 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1040 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1041 return -1;
1042 }
1043 } else if (!strcmp(args[1], "auth")) {
1044 if (*(args[2]) == 0) {
1045 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1046 return -1;
1047 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1048 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1049 return -1;
1050 }
1051 } else if (!strcmp(args[1], "scope")) {
1052 if (*(args[2]) == 0) {
1053 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1054 return -1;
1055 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1056 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1057 return -1;
1058 }
1059 } else if (!strcmp(args[1], "enable")) {
1060 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1061 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1062 return -1;
1063 }
1064 } else {
1065 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'uri', 'realm', 'auth' or 'enable').\n",
1066 file, linenum, args[0]);
1067 return -1;
1068 }
1069 }
1070 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001071 int optnum;
1072
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 if (*(args[1]) == 0) {
1074 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
1075 return -1;
1076 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001077
1078 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1079 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1080 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1081 return 0;
1082 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001083 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001084 return 0;
1085 }
1086 }
1087
1088 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 /* generate a complete HTTP log */
1090 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1091 else if (!strcmp(args[1], "tcplog"))
1092 /* generate a detailed TCP log */
1093 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 else if (!strcmp(args[1], "tcpka")) {
1095 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001096 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1097 return 0;
1098
1099 if (curproxy->cap & PR_CAP_FE)
1100 curproxy->options |= PR_O_TCP_CLI_KA;
1101 if (curproxy->cap & PR_CAP_BE)
1102 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 }
1104 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001105 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1106 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 /* use HTTP request to check servers' health */
1108 if (curproxy->check_req != NULL) {
1109 free(curproxy->check_req);
1110 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001111 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001112 curproxy->options &= ~PR_O_SMTP_CHK;
1113 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001114 if (!*args[2]) { /* no argument */
1115 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1116 curproxy->check_len = strlen(DEF_CHECK_REQ);
1117 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001118 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 curproxy->check_req = (char *)malloc(reqlen);
1120 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1121 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1122 } else { /* more arguments : METHOD URI [HTTP_VER] */
1123 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1124 if (*args[4])
1125 reqlen += strlen(args[4]);
1126 else
1127 reqlen += strlen("HTTP/1.0");
1128
1129 curproxy->check_req = (char *)malloc(reqlen);
1130 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1131 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1132 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001133 }
1134 else if (!strcmp(args[1], "ssl-hello-chk")) {
1135 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001136 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1137 return 0;
1138
Willy Tarreauf3c69202006-07-09 16:42:34 +02001139 if (curproxy->check_req != NULL) {
1140 free(curproxy->check_req);
1141 }
1142 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001143 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001144 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001145 }
Willy Tarreau23677902007-05-08 23:50:35 +02001146 else if (!strcmp(args[1], "smtpchk")) {
1147 /* use SMTP request to check servers' health */
1148 if (curproxy->check_req != NULL) {
1149 free(curproxy->check_req);
1150 }
1151 curproxy->options &= ~PR_O_HTTP_CHK;
1152 curproxy->options &= ~PR_O_SSL3_CHK;
1153 curproxy->options |= PR_O_SMTP_CHK;
1154
1155 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1156 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1157 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1158 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1159 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1160 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1161 curproxy->check_req = (char *)malloc(reqlen);
1162 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1163 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1164 } else {
1165 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1166 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1167 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1168 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1169 }
1170 }
1171 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001172 else if (!strcmp(args[1], "forwardfor")) {
1173 /* insert x-forwarded-for field, but not for the
1174 * IP address listed as an except.
1175 */
1176 if (*(args[2])) {
1177 if (!strcmp(args[2], "except")) {
1178 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1179 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1180 file, linenum, args[0]);
1181 return -1;
1182 }
1183 /* flush useless bits */
1184 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1185 } else {
1186 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1187 file, linenum, args[0]);
1188 return -1;
1189 }
1190 }
1191 curproxy->options |= PR_O_FWDFOR;
1192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 else {
1194 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1195 return -1;
1196 }
1197 return 0;
1198 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001199 else if (!strcmp(args[0], "default_backend")) {
1200 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1201 return 0;
1202
1203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1205 return -1;
1206 }
1207 if (curproxy->defbe.name)
1208 free(curproxy->defbe.name);
1209 curproxy->defbe.name = strdup(args[1]);
1210 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001211 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001212 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1213 return 0;
1214
Willy Tarreaubaaee002006-06-26 02:48:02 +02001215 /* enable reconnections to dispatch */
1216 curproxy->options |= PR_O_REDISP;
1217 }
1218#ifdef TPROXY
1219 else if (!strcmp(args[0], "transparent")) {
1220 /* enable transparent proxy connections */
1221 curproxy->options |= PR_O_TRANSP;
1222 }
1223#endif
1224 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001225 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1226 return 0;
1227
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 if (*(args[1]) == 0) {
1229 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1230 return -1;
1231 }
1232 curproxy->maxconn = atol(args[1]);
1233 }
Willy Tarreau86034312006-12-29 00:10:33 +01001234 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001235 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1236 return 0;
1237
Willy Tarreau86034312006-12-29 00:10:33 +01001238 if (*(args[1]) == 0) {
1239 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1240 return -1;
1241 }
1242 curproxy->fullconn = atol(args[1]);
1243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001244 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1245 if (*(args[1]) == 0) {
1246 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1247 return -1;
1248 }
1249 curproxy->grace = atol(args[1]);
1250 }
1251 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1252 if (curproxy == &defproxy) {
1253 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1254 return -1;
1255 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001256 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1257 return 0;
1258
Willy Tarreaubaaee002006-06-26 02:48:02 +02001259 if (strchr(args[1], ':') == NULL) {
1260 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1261 return -1;
1262 }
1263 curproxy->dispatch_addr = *str2sa(args[1]);
1264 }
1265 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001266 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1267 return 0;
1268
Willy Tarreaubaaee002006-06-26 02:48:02 +02001269 if (*(args[1])) {
1270 if (!strcmp(args[1], "roundrobin")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001271 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001272 curproxy->options |= PR_O_BALANCE_RR;
1273 }
1274 else if (!strcmp(args[1], "source")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001275 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001276 curproxy->options |= PR_O_BALANCE_SH;
1277 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001278 else if (!strcmp(args[1], "uri")) {
1279 curproxy->options &= ~PR_O_BALANCE;
1280 curproxy->options |= PR_O_BALANCE_UH;
1281 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001282 else {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001283 Alert("parsing [%s:%d] : '%s' only supports 'roundrobin', 'source' and 'uri' options.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284 return -1;
1285 }
1286 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001287 else {/* if no option is set, use round-robin by default */
1288 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001289 curproxy->options |= PR_O_BALANCE_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001290 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001291 }
1292 else if (!strcmp(args[0], "server")) { /* server address */
1293 int cur_arg;
1294 char *rport;
1295 char *raddr;
1296 short realport;
1297 int do_check;
1298
1299 if (curproxy == &defproxy) {
1300 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1301 return -1;
1302 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001303 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1304 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001305
1306 if (!*args[2]) {
1307 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1308 file, linenum, args[0]);
1309 return -1;
1310 }
1311 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1312 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1313 return -1;
1314 }
1315
1316 /* the servers are linked backwards first */
1317 newsrv->next = curproxy->srv;
1318 curproxy->srv = newsrv;
1319 newsrv->proxy = curproxy;
1320
1321 LIST_INIT(&newsrv->pendconns);
1322 do_check = 0;
1323 newsrv->state = SRV_RUNNING; /* early server setup */
1324 newsrv->id = strdup(args[1]);
1325
1326 /* several ways to check the port component :
1327 * - IP => port=+0, relative
1328 * - IP: => port=+0, relative
1329 * - IP:N => port=N, absolute
1330 * - IP:+N => port=+N, relative
1331 * - IP:-N => port=-N, relative
1332 */
1333 raddr = strdup(args[2]);
1334 rport = strchr(raddr, ':');
1335 if (rport) {
1336 *rport++ = 0;
1337 realport = atol(rport);
1338 if (!isdigit((int)*rport))
1339 newsrv->state |= SRV_MAPPORTS;
1340 } else {
1341 realport = 0;
1342 newsrv->state |= SRV_MAPPORTS;
1343 }
1344
1345 newsrv->addr = *str2sa(raddr);
1346 newsrv->addr.sin_port = htons(realport);
1347 free(raddr);
1348
1349 newsrv->curfd = -1; /* no health-check in progress */
1350 newsrv->inter = DEF_CHKINTR;
1351 newsrv->rise = DEF_RISETIME;
1352 newsrv->fall = DEF_FALLTIME;
1353 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001354 newsrv->uweight = 1;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001355
Willy Tarreaubaaee002006-06-26 02:48:02 +02001356 cur_arg = 3;
1357 while (*args[cur_arg]) {
1358 if (!strcmp(args[cur_arg], "cookie")) {
1359 newsrv->cookie = strdup(args[cur_arg + 1]);
1360 newsrv->cklen = strlen(args[cur_arg + 1]);
1361 cur_arg += 2;
1362 }
1363 else if (!strcmp(args[cur_arg], "rise")) {
1364 newsrv->rise = atol(args[cur_arg + 1]);
1365 newsrv->health = newsrv->rise;
1366 cur_arg += 2;
1367 }
1368 else if (!strcmp(args[cur_arg], "fall")) {
1369 newsrv->fall = atol(args[cur_arg + 1]);
1370 cur_arg += 2;
1371 }
1372 else if (!strcmp(args[cur_arg], "inter")) {
1373 newsrv->inter = atol(args[cur_arg + 1]);
1374 cur_arg += 2;
1375 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001376 else if (!strcmp(args[cur_arg], "addr")) {
1377 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001378 cur_arg += 2;
1379 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 else if (!strcmp(args[cur_arg], "port")) {
1381 newsrv->check_port = atol(args[cur_arg + 1]);
1382 cur_arg += 2;
1383 }
1384 else if (!strcmp(args[cur_arg], "backup")) {
1385 newsrv->state |= SRV_BACKUP;
1386 cur_arg ++;
1387 }
1388 else if (!strcmp(args[cur_arg], "weight")) {
1389 int w;
1390 w = atol(args[cur_arg + 1]);
1391 if (w < 1 || w > 256) {
1392 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1393 file, linenum, newsrv->id, w);
1394 return -1;
1395 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001396 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001397 cur_arg += 2;
1398 }
1399 else if (!strcmp(args[cur_arg], "minconn")) {
1400 newsrv->minconn = atol(args[cur_arg + 1]);
1401 cur_arg += 2;
1402 }
1403 else if (!strcmp(args[cur_arg], "maxconn")) {
1404 newsrv->maxconn = atol(args[cur_arg + 1]);
1405 cur_arg += 2;
1406 }
1407 else if (!strcmp(args[cur_arg], "check")) {
1408 global.maxsock++;
1409 do_check = 1;
1410 cur_arg += 1;
1411 }
1412 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1413 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001414#ifdef CONFIG_HAP_CTTPROXY
1415 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1416 file, linenum, "source", "usesrc");
1417#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1419 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001420#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 return -1;
1422 }
1423 newsrv->state |= SRV_BIND_SRC;
1424 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1425 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001426 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001427#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001428 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001429 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1430 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001431 return -1;
1432 }
1433 if (!*args[cur_arg + 1]) {
1434 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1435 file, linenum, "usesrc");
1436 return -1;
1437 }
1438 if (!strcmp(args[cur_arg + 1], "client")) {
1439 newsrv->state |= SRV_TPROXY_CLI;
1440 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1441 newsrv->state |= SRV_TPROXY_CIP;
1442 } else {
1443 newsrv->state |= SRV_TPROXY_ADDR;
1444 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1445 }
1446 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1447 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001448#else /* no CTTPROXY support */
1449 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1450 file, linenum, "usesrc");
1451 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001452#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001455#ifdef CONFIG_HAP_CTTPROXY
1456 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1457 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1458 file, linenum, "usesrc", "source");
1459 return -1;
1460 }
1461#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462 else {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001463 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 +02001464 file, linenum, newsrv->id);
1465 return -1;
1466 }
1467 }
1468
1469 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001470 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1471 newsrv->check_port = newsrv->check_addr.sin_port;
1472
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1474 newsrv->check_port = realport; /* by default */
1475 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001476 /* not yet valid, because no port was set on
1477 * the server either. We'll check if we have
1478 * a known port on the first listener.
1479 */
1480 struct listener *l;
1481 l = curproxy->listen;
1482 if (l) {
1483 int port;
1484 port = (l->addr.ss_family == AF_INET6)
1485 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1486 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1487 newsrv->check_port = port;
1488 }
1489 }
1490 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1492 file, linenum, newsrv->id);
1493 return -1;
1494 }
1495 newsrv->state |= SRV_CHECKED;
1496 }
1497
1498 if (newsrv->state & SRV_BACKUP)
1499 curproxy->srv_bck++;
1500 else
1501 curproxy->srv_act++;
1502 }
1503 else if (!strcmp(args[0], "log")) { /* syslog server address */
1504 struct sockaddr_in *sa;
1505 int facility;
1506
1507 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1508 curproxy->logfac1 = global.logfac1;
1509 curproxy->logsrv1 = global.logsrv1;
1510 curproxy->loglev1 = global.loglev1;
1511 curproxy->logfac2 = global.logfac2;
1512 curproxy->logsrv2 = global.logsrv2;
1513 curproxy->loglev2 = global.loglev2;
1514 }
1515 else if (*(args[1]) && *(args[2])) {
1516 int level;
1517
1518 facility = get_log_facility(args[2]);
1519 if (facility < 0) {
1520 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1521 exit(1);
1522 }
1523
1524 level = 7; /* max syslog level = debug */
1525 if (*(args[3])) {
1526 level = get_log_level(args[3]);
1527 if (level < 0) {
1528 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1529 exit(1);
1530 }
1531 }
1532
1533 sa = str2sa(args[1]);
1534 if (!sa->sin_port)
1535 sa->sin_port = htons(SYSLOG_PORT);
1536
1537 if (curproxy->logfac1 == -1) {
1538 curproxy->logsrv1 = *sa;
1539 curproxy->logfac1 = facility;
1540 curproxy->loglev1 = level;
1541 }
1542 else if (curproxy->logfac2 == -1) {
1543 curproxy->logsrv2 = *sa;
1544 curproxy->logfac2 = facility;
1545 curproxy->loglev2 = level;
1546 }
1547 else {
1548 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1549 return -1;
1550 }
1551 }
1552 else {
1553 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1554 file, linenum);
1555 return -1;
1556 }
1557 }
1558 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001559 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1560 return 0;
1561
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001563#ifdef CONFIG_HAP_CTTPROXY
1564 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1565 file, linenum, "source", "usesrc");
1566#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1568 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001569#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 return -1;
1571 }
1572
1573 curproxy->source_addr = *str2sa(args[1]);
1574 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001575 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001576#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001577 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1578 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1579 file, linenum, "usesrc");
1580 return -1;
1581 }
1582 if (!*args[3]) {
1583 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1584 file, linenum, "usesrc");
1585 return -1;
1586 }
1587
1588 if (!strcmp(args[3], "client")) {
1589 curproxy->options |= PR_O_TPXY_CLI;
1590 } else if (!strcmp(args[3], "clientip")) {
1591 curproxy->options |= PR_O_TPXY_CIP;
1592 } else {
1593 curproxy->options |= PR_O_TPXY_ADDR;
1594 curproxy->tproxy_addr = *str2sa(args[3]);
1595 }
1596 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001597#else /* no CTTPROXY support */
1598 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1599 file, linenum, "usesrc");
1600 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001601#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001604#ifdef CONFIG_HAP_CTTPROXY
1605 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1606 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1607 file, linenum, "usesrc", "source");
1608 return -1;
1609 }
1610#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1612 regex_t *preg;
1613 if (curproxy == &defproxy) {
1614 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1615 return -1;
1616 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001617 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1618 return 0;
1619
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 if (*(args[1]) == 0 || *(args[2]) == 0) {
1621 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1622 file, linenum, args[0]);
1623 return -1;
1624 }
1625
1626 preg = calloc(1, sizeof(regex_t));
1627 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1628 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1629 return -1;
1630 }
1631
1632 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1633 if (err) {
1634 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1635 file, linenum, *err);
1636 return -1;
1637 }
1638 }
1639 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1640 regex_t *preg;
1641 if (curproxy == &defproxy) {
1642 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1643 return -1;
1644 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001645 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1646 return 0;
1647
Willy Tarreaubaaee002006-06-26 02:48:02 +02001648 if (*(args[1]) == 0) {
1649 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1650 return -1;
1651 }
1652
1653 preg = calloc(1, sizeof(regex_t));
1654 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1655 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1656 return -1;
1657 }
1658
1659 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1660 }
1661 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1662 regex_t *preg;
1663 if (curproxy == &defproxy) {
1664 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1665 return -1;
1666 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001667 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1668 return 0;
1669
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670 if (*(args[1]) == 0) {
1671 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1672 return -1;
1673 }
1674
1675 preg = calloc(1, sizeof(regex_t));
1676 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1677 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1678 return -1;
1679 }
1680
1681 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1682 }
1683 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1684 regex_t *preg;
1685 if (curproxy == &defproxy) {
1686 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1687 return -1;
1688 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001689 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1690 return 0;
1691
Willy Tarreaubaaee002006-06-26 02:48:02 +02001692 if (*(args[1]) == 0) {
1693 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1694 return -1;
1695 }
1696
1697 preg = calloc(1, sizeof(regex_t));
1698 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1699 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1700 return -1;
1701 }
1702
1703 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1704 }
1705 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1706 regex_t *preg;
1707 if (curproxy == &defproxy) {
1708 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1709 return -1;
1710 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001711 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1712 return 0;
1713
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 if (*(args[1]) == 0) {
1715 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1716 return -1;
1717 }
1718
1719 preg = calloc(1, sizeof(regex_t));
1720 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1721 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1722 return -1;
1723 }
1724
1725 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1726 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001727 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1728 regex_t *preg;
1729 if (curproxy == &defproxy) {
1730 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1731 return -1;
1732 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001733 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1734 return 0;
1735
Willy Tarreaub8750a82006-09-03 09:56:00 +02001736 if (*(args[1]) == 0) {
1737 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1738 return -1;
1739 }
1740
1741 preg = calloc(1, sizeof(regex_t));
1742 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1743 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1744 return -1;
1745 }
1746
1747 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1748 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001749 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1750 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001751 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001752 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1753 return -1;
1754 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001755 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1756 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001757
Willy Tarreau977b8e42006-12-29 14:19:17 +01001758 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001759 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1760 file, linenum, args[0]);
1761 return -1;
1762 }
1763
1764 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001765 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001766 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1767 }
1768
1769 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1770 }
1771 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1772 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001773 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001774 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1775 return -1;
1776 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001777 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1778 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001779
Willy Tarreau977b8e42006-12-29 14:19:17 +01001780 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001781 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1782 file, linenum, args[0]);
1783 return -1;
1784 }
1785
1786 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001787 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001788 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1789 }
1790
1791 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1792 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1794 regex_t *preg;
1795 if (curproxy == &defproxy) {
1796 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1797 return -1;
1798 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001799 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1800 return 0;
1801
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802 if (*(args[1]) == 0 || *(args[2]) == 0) {
1803 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1804 file, linenum, args[0]);
1805 return -1;
1806 }
1807
1808 preg = calloc(1, sizeof(regex_t));
1809 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1810 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1811 return -1;
1812 }
1813
1814 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1815 if (err) {
1816 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1817 file, linenum, *err);
1818 return -1;
1819 }
1820 }
1821 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1822 regex_t *preg;
1823 if (curproxy == &defproxy) {
1824 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1825 return -1;
1826 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001827 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1828 return 0;
1829
Willy Tarreaubaaee002006-06-26 02:48:02 +02001830 if (*(args[1]) == 0) {
1831 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1832 return -1;
1833 }
1834
1835 preg = calloc(1, sizeof(regex_t));
1836 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1837 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1838 return -1;
1839 }
1840
1841 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1842 }
1843 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1844 regex_t *preg;
1845 if (curproxy == &defproxy) {
1846 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1847 return -1;
1848 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001849 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1850 return 0;
1851
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852 if (*(args[1]) == 0) {
1853 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1854 return -1;
1855 }
1856
1857 preg = calloc(1, sizeof(regex_t));
1858 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1859 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1860 return -1;
1861 }
1862
1863 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1864 }
1865 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1866 regex_t *preg;
1867 if (curproxy == &defproxy) {
1868 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1869 return -1;
1870 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001871 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1872 return 0;
1873
Willy Tarreaubaaee002006-06-26 02:48:02 +02001874 if (*(args[1]) == 0) {
1875 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1876 return -1;
1877 }
1878
1879 preg = calloc(1, sizeof(regex_t));
1880 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1881 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1882 return -1;
1883 }
1884
1885 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1886 }
1887 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1888 regex_t *preg;
1889 if (curproxy == &defproxy) {
1890 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1891 return -1;
1892 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001893 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1894 return 0;
1895
Willy Tarreaubaaee002006-06-26 02:48:02 +02001896 if (*(args[1]) == 0) {
1897 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1898 return -1;
1899 }
1900
1901 preg = calloc(1, sizeof(regex_t));
1902 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1903 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1904 return -1;
1905 }
1906
1907 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1908 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001909 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1910 regex_t *preg;
1911 if (curproxy == &defproxy) {
1912 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1913 return -1;
1914 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001915 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1916 return 0;
1917
Willy Tarreaub8750a82006-09-03 09:56:00 +02001918 if (*(args[1]) == 0) {
1919 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1920 return -1;
1921 }
1922
1923 preg = calloc(1, sizeof(regex_t));
1924 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1925 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1926 return -1;
1927 }
1928
1929 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1930 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1932 if (curproxy == &defproxy) {
1933 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1934 return -1;
1935 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001936 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1937 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938
1939 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
1940 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1941 return 0;
1942 }
1943
1944 if (*(args[1]) == 0) {
1945 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1946 return -1;
1947 }
1948
1949 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
1950 }
1951 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
1952 regex_t *preg;
1953
1954 if (*(args[1]) == 0 || *(args[2]) == 0) {
1955 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1956 file, linenum, args[0]);
1957 return -1;
1958 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001959 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1960 return 0;
1961
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962 preg = calloc(1, sizeof(regex_t));
1963 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1964 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1965 return -1;
1966 }
1967
1968 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1969 if (err) {
1970 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1971 file, linenum, *err);
1972 return -1;
1973 }
1974 }
1975 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
1976 regex_t *preg;
1977 if (curproxy == &defproxy) {
1978 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1979 return -1;
1980 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001981 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1982 return 0;
1983
Willy Tarreaubaaee002006-06-26 02:48:02 +02001984 if (*(args[1]) == 0) {
1985 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1986 return -1;
1987 }
1988
1989 preg = calloc(1, sizeof(regex_t));
1990 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1991 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1992 return -1;
1993 }
1994
1995 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
1996 if (err) {
1997 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1998 file, linenum, *err);
1999 return -1;
2000 }
2001 }
2002 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2003 regex_t *preg;
2004 if (curproxy == &defproxy) {
2005 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2006 return -1;
2007 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002008 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2009 return 0;
2010
Willy Tarreaubaaee002006-06-26 02:48:02 +02002011 if (*(args[1]) == 0) {
2012 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2013 return -1;
2014 }
2015
2016 preg = calloc(1, sizeof(regex_t));
2017 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2018 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2019 return -1;
2020 }
2021
2022 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2023 if (err) {
2024 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2025 file, linenum, *err);
2026 return -1;
2027 }
2028 }
2029 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2030 regex_t *preg;
2031 if (curproxy == &defproxy) {
2032 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2033 return -1;
2034 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002035 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2036 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002037
2038 if (*(args[1]) == 0 || *(args[2]) == 0) {
2039 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2040 file, linenum, args[0]);
2041 return -1;
2042 }
2043
2044 preg = calloc(1, sizeof(regex_t));
2045 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2046 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2047 return -1;
2048 }
2049
2050 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2051 if (err) {
2052 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2053 file, linenum, *err);
2054 return -1;
2055 }
2056 }
2057 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2058 regex_t *preg;
2059 if (curproxy == &defproxy) {
2060 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2061 return -1;
2062 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002063 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2064 return 0;
2065
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066 if (*(args[1]) == 0) {
2067 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2068 return -1;
2069 }
2070
2071 preg = calloc(1, sizeof(regex_t));
2072 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2073 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2074 return -1;
2075 }
2076
2077 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2078 if (err) {
2079 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2080 file, linenum, *err);
2081 return -1;
2082 }
2083 }
2084 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2085 regex_t *preg;
2086 if (curproxy == &defproxy) {
2087 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2088 return -1;
2089 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002090 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2091 return 0;
2092
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093 if (*(args[1]) == 0) {
2094 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2095 return -1;
2096 }
2097
2098 preg = calloc(1, sizeof(regex_t));
2099 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2100 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2101 return -1;
2102 }
2103
2104 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2105 if (err) {
2106 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2107 file, linenum, *err);
2108 return -1;
2109 }
2110 }
2111 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2112 if (curproxy == &defproxy) {
2113 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2114 return -1;
2115 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002116 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2117 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002118
2119 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2120 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2121 return 0;
2122 }
2123
2124 if (*(args[1]) == 0) {
2125 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2126 return -1;
2127 }
2128
2129 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2130 }
2131 else if (!strcmp(args[0], "errorloc") ||
2132 !strcmp(args[0], "errorloc302") ||
2133 !strcmp(args[0], "errorloc303")) { /* error location */
2134 int errnum, errlen;
2135 char *err;
2136
Willy Tarreau977b8e42006-12-29 14:19:17 +01002137 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2138 return 0;
2139
Willy Tarreaubaaee002006-06-26 02:48:02 +02002140 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002141 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002142 return -1;
2143 }
2144
2145 errnum = atol(args[1]);
2146 if (!strcmp(args[0], "errorloc303")) {
2147 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2148 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2149 } else {
2150 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2151 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2152 }
2153
Willy Tarreau0f772532006-12-23 20:51:41 +01002154 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2155 if (http_err_codes[rc] == errnum) {
2156 if (curproxy->errmsg[rc].str)
2157 free(curproxy->errmsg[rc].str);
2158 curproxy->errmsg[rc].str = err;
2159 curproxy->errmsg[rc].len = errlen;
2160 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002161 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002162 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002163
2164 if (rc >= HTTP_ERR_SIZE) {
2165 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2166 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002167 free(err);
2168 }
2169 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002170 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2171 int errnum, errlen, fd;
2172 char *err;
2173 struct stat stat;
2174
2175 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2176 return 0;
2177
2178 if (*(args[2]) == 0) {
2179 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2180 return -1;
2181 }
2182
2183 fd = open(args[2], O_RDONLY);
2184 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2185 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2186 file, linenum, args[2], args[1]);
2187 if (fd >= 0)
2188 close(fd);
2189 return -1;
2190 }
2191
2192 if (stat.st_size <= BUFSIZE) {
2193 errlen = stat.st_size;
2194 } else {
2195 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2196 file, linenum, args[2], BUFSIZE);
2197 errlen = BUFSIZE;
2198 }
2199
2200 err = malloc(errlen); /* malloc() must succeed during parsing */
2201 errnum = read(fd, err, errlen);
2202 if (errnum != errlen) {
2203 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2204 file, linenum, args[2], args[1]);
2205 close(fd);
2206 free(err);
2207 return -1;
2208 }
2209 close(fd);
2210
2211 errnum = atol(args[1]);
2212 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2213 if (http_err_codes[rc] == errnum) {
2214 if (curproxy->errmsg[rc].str)
2215 free(curproxy->errmsg[rc].str);
2216 curproxy->errmsg[rc].str = err;
2217 curproxy->errmsg[rc].len = errlen;
2218 break;
2219 }
2220 }
2221
2222 if (rc >= HTTP_ERR_SIZE) {
2223 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2224 file, linenum, errnum);
2225 free(err);
2226 }
2227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 else {
2229 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2230 return -1;
2231 }
2232 return 0;
2233}
2234
2235
2236/*
2237 * This function reads and parses the configuration file given in the argument.
2238 * returns 0 if OK, -1 if error.
2239 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002240int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241{
2242 char thisline[256];
2243 char *line;
2244 FILE *f;
2245 int linenum = 0;
2246 char *end;
Willy Tarreau540abe42007-05-02 20:50:16 +02002247 char *args[MAX_LINE_ARGS + 1];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 int arg;
2249 int cfgerr = 0;
Willy Tarreau80587432006-12-24 17:47:20 +01002250 int nbchk, mininter;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 int confsect = CFG_NONE;
2252
2253 struct proxy *curproxy = NULL;
2254 struct server *newsrv = NULL;
2255
2256 if ((f=fopen(file,"r")) == NULL)
2257 return -1;
2258
2259 init_default_instance();
2260
2261 while (fgets(line = thisline, sizeof(thisline), f) != NULL) {
2262 linenum++;
2263
2264 end = line + strlen(line);
2265
2266 /* skip leading spaces */
2267 while (isspace((int)*line))
2268 line++;
2269
2270 arg = 0;
2271 args[arg] = line;
2272
2273 while (*line && arg < MAX_LINE_ARGS) {
2274 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2275 * C equivalent value. Other combinations left unchanged (eg: \1).
2276 */
2277 if (*line == '\\') {
2278 int skip = 0;
2279 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2280 *line = line[1];
2281 skip = 1;
2282 }
2283 else if (line[1] == 'r') {
2284 *line = '\r';
2285 skip = 1;
2286 }
2287 else if (line[1] == 'n') {
2288 *line = '\n';
2289 skip = 1;
2290 }
2291 else if (line[1] == 't') {
2292 *line = '\t';
2293 skip = 1;
2294 }
2295 else if (line[1] == 'x') {
2296 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2297 unsigned char hex1, hex2;
2298 hex1 = toupper(line[2]) - '0';
2299 hex2 = toupper(line[3]) - '0';
2300 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2301 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2302 *line = (hex1<<4) + hex2;
2303 skip = 3;
2304 }
2305 else {
2306 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2307 return -1;
2308 }
2309 }
2310 if (skip) {
2311 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2312 end -= skip;
2313 }
2314 line++;
2315 }
2316 else if (*line == '#' || *line == '\n' || *line == '\r') {
2317 /* end of string, end of loop */
2318 *line = 0;
2319 break;
2320 }
2321 else if (isspace((int)*line)) {
2322 /* a non-escaped space is an argument separator */
2323 *line++ = 0;
2324 while (isspace((int)*line))
2325 line++;
2326 args[++arg] = line;
2327 }
2328 else {
2329 line++;
2330 }
2331 }
2332
2333 /* empty line */
2334 if (!**args)
2335 continue;
2336
Willy Tarreau540abe42007-05-02 20:50:16 +02002337 /* zero out remaining args and ensure that at least one entry
2338 * is zeroed out.
2339 */
2340 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 args[arg] = line;
2342 }
2343
Willy Tarreau977b8e42006-12-29 14:19:17 +01002344 if (!strcmp(args[0], "listen") ||
2345 !strcmp(args[0], "frontend") ||
2346 !strcmp(args[0], "backend") ||
2347 !strcmp(args[0], "ruleset") ||
2348 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002349 confsect = CFG_LISTEN;
2350 else if (!strcmp(args[0], "global")) /* global config */
2351 confsect = CFG_GLOBAL;
2352 /* else it's a section keyword */
2353
2354 switch (confsect) {
2355 case CFG_LISTEN:
2356 if (cfg_parse_listen(file, linenum, args) < 0)
2357 return -1;
2358 break;
2359 case CFG_GLOBAL:
2360 if (cfg_parse_global(file, linenum, args) < 0)
2361 return -1;
2362 break;
2363 default:
2364 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2365 return -1;
2366 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002367 }
2368 fclose(f);
2369
2370 /*
2371 * Now, check for the integrity of all that we have collected.
2372 */
2373
2374 /* will be needed further to delay some tasks */
2375 tv_now(&now);
2376
2377 if ((curproxy = proxy) == NULL) {
2378 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2379 file);
2380 return -1;
2381 }
2382
2383 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002384 struct switching_rule *rule;
2385
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 if (curproxy->state == PR_STSTOPPED) {
2387 curproxy = curproxy->next;
2388 continue;
2389 }
2390
Willy Tarreau977b8e42006-12-29 14:19:17 +01002391 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2392 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 +01002393 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002394 cfgerr++;
2395 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002396 else if (curproxy->cap & PR_CAP_BE &&
2397 ((curproxy->mode != PR_MODE_HEALTH) &&
2398 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
2399 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2400 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 +01002401 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 cfgerr++;
2403 }
2404 else if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
2405 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002406 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002407 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 cfgerr++;
2409 }
2410#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2411 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002412 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002413 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002414 cfgerr++;
2415 }
2416#endif
2417 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002418 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002419 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 }
2421 }
2422 else if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2423 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002424 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002425 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 }
2427 if ((newsrv = curproxy->srv) != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002428 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002429 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 }
2431 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002432 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002433 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 }
2435 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002436 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002437 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002439 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002440 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002441 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002442 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002443 if (curproxy->options & PR_O_BALANCE_UH) {
2444 curproxy->options &= ~PR_O_BALANCE;
2445 curproxy->options |= PR_O_BALANCE_RR;
2446
2447 Warning("parsing %s : URI hash will be ignored for %s '%s'. Falling back to round robin.\n",
2448 file, proxy_type_str(curproxy), curproxy->id);
2449 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 }
2451 else if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
2452 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2453 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2454 file, curproxy->id);
2455 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002456 }
2457 }
2458
2459 /* if a default backend was specified, let's find it */
2460 if (curproxy->defbe.name) {
2461 struct proxy *target;
2462
2463 for (target = proxy; target != NULL; target = target->next) {
2464 if (strcmp(target->id, curproxy->defbe.name) == 0)
2465 break;
2466 }
2467 if (target == NULL) {
2468 Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n",
2469 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2470 cfgerr++;
2471 } else if (target == curproxy) {
2472 Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
2473 cfgerr++;
2474 } else if (!(target->cap & PR_CAP_BE)) {
2475 Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n",
2476 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2477 cfgerr++;
2478 } else if (target->mode != curproxy->mode) {
2479 Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
2480 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2481 cfgerr++;
2482 } else {
2483 free(curproxy->defbe.name);
2484 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 }
2486 }
2487
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002488 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002489 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2490 /* map jump target for ACT_SETBE in req_rep chain */
2491 struct hdr_exp *exp;
2492 struct proxy *target;
2493 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
2494 if (exp->action != ACT_SETBE)
2495 continue;
2496 for (target = proxy; target != NULL; target = target->next) {
2497 if (strcmp(target->id, exp->replace) == 0)
2498 break;
2499 }
2500 if (target == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002501 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002502 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaua496b602006-12-17 23:15:24 +01002503 cfgerr++;
2504 } else if (target == curproxy) {
2505 Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
2506 cfgerr++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002507 } else if (!(target->cap & PR_CAP_BE)) {
2508 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002509 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002510 cfgerr++;
2511 } else if (target->mode != PR_MODE_HTTP) {
2512 Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002513 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002514 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002515 } else {
2516 free((void *)exp->replace);
2517 exp->replace = (const char *)target;
2518 }
2519 }
2520 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002521
2522 /* find the target proxy for 'use_backend' rules */
2523 list_for_each_entry(rule, &curproxy->switching_rules, list) {
2524 /* map jump target for ACT_SETBE in req_rep chain */
2525 struct proxy *target;
2526
2527 for (target = proxy; target != NULL; target = target->next) {
2528 if (strcmp(target->id, rule->be.name) == 0)
2529 break;
2530 }
2531
2532 if (target == NULL) {
2533 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
2534 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2535 cfgerr++;
2536 } else if (target == curproxy) {
2537 Alert("parsing %s : loop detected for backend %s !\n", file, rule->be.name);
2538 cfgerr++;
2539 } else if (!(target->cap & PR_CAP_BE)) {
2540 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
2541 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2542 cfgerr++;
2543 } else if (target->mode != curproxy->mode) {
2544 Alert("parsing %s : backend '%s' referenced in %s '%s' is of different mode !\n",
2545 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2546 cfgerr++;
2547 } else {
2548 free((void *)rule->be.name);
2549 rule->be.backend = target;
2550 }
2551 }
2552
Willy Tarreau2738a142006-07-08 17:28:09 +02002553 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002554 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2555 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2556 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002557 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002558 " | While not properly invalid, you will certainly encounter various problems\n"
2559 " | with such a configuration. To fix this, please ensure that all following\n"
2560 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002561 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002562 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002563
2564 if (curproxy->options & PR_O_SSL3_CHK) {
2565 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2566 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2567 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2568 }
2569
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002570 /* The small pools required for the capture lists */
2571 if (curproxy->nb_req_cap)
2572 curproxy->req_cap_pool = create_pool("ptrcap",
2573 curproxy->nb_req_cap * sizeof(char *),
2574 MEM_F_SHARED);
2575 if (curproxy->nb_rsp_cap)
2576 curproxy->rsp_cap_pool = create_pool("ptrcap",
2577 curproxy->nb_rsp_cap * sizeof(char *),
2578 MEM_F_SHARED);
2579
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002580 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2581 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2582 MEM_F_SHARED);
2583
Willy Tarreau86034312006-12-29 00:10:33 +01002584 /* for backwards compatibility with "listen" instances, if
2585 * fullconn is not set but maxconn is set, then maxconn
2586 * is used.
2587 */
2588 if (!curproxy->fullconn)
2589 curproxy->fullconn = curproxy->maxconn;
2590
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 /* first, we will invert the servers list order */
2592 newsrv = NULL;
2593 while (curproxy->srv) {
2594 struct server *next;
2595
2596 next = curproxy->srv->next;
2597 curproxy->srv->next = newsrv;
2598 newsrv = curproxy->srv;
2599 if (!next)
2600 break;
2601 curproxy->srv = next;
2602 }
2603
2604 /* now, newsrv == curproxy->srv */
2605 if (newsrv) {
2606 struct server *srv;
2607 int pgcd;
2608 int act, bck;
2609
2610 /* We will factor the weights to reduce the table,
2611 * using Euclide's largest common divisor algorithm
2612 */
Willy Tarreau417fae02007-03-25 21:16:40 +02002613 pgcd = newsrv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2615 int t, w;
2616
Willy Tarreau417fae02007-03-25 21:16:40 +02002617 w = srv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002618 while (w) {
2619 t = pgcd % w;
2620 pgcd = w;
2621 w = t;
2622 }
2623 }
2624
2625 act = bck = 0;
2626 for (srv = newsrv; srv; srv = srv->next) {
Willy Tarreau417fae02007-03-25 21:16:40 +02002627 srv->eweight = srv->uweight / pgcd;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002628 if (srv->state & SRV_BACKUP)
Willy Tarreau417fae02007-03-25 21:16:40 +02002629 bck += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630 else
Willy Tarreau417fae02007-03-25 21:16:40 +02002631 act += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632 }
2633
2634 /* this is the largest map we will ever need for this servers list */
2635 if (act < bck)
2636 act = bck;
2637
2638 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2639 /* recounts servers and their weights */
2640 recount_servers(curproxy);
2641 recalc_server_map(curproxy);
2642 }
2643
2644 if (curproxy->options & PR_O_LOGASAP)
2645 curproxy->to_log &= ~LW_BYTES;
2646
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 /*
2648 * If this server supports a maxconn parameter, it needs a dedicated
2649 * tasks to fill the emptied slots when a connection leaves.
2650 */
2651 newsrv = curproxy->srv;
2652 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002653 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002654 /* Only 'minconn' was specified, or it was higher than or equal
2655 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2656 * this will avoid further useless expensive computations.
2657 */
2658 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002659 } else if (newsrv->maxconn && !newsrv->minconn) {
2660 /* minconn was not specified, so we set it to maxconn */
2661 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002662 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2663 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002664 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002665 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666 }
2667
2668 if (newsrv->maxconn > 0) {
2669 struct task *t;
2670
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002671 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2673 return -1;
2674 }
2675
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002676 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002677 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002678 t->state = TASK_IDLE;
2679 t->process = process_srv_queue;
2680 t->context = newsrv;
2681 newsrv->queue_mgt = t;
2682
2683 /* never run it unless specifically woken up */
2684 tv_eternity(&t->expire);
2685 task_queue(t);
2686 }
2687 newsrv = newsrv->next;
2688 }
2689
2690 /* now we'll start this proxy's health checks if any */
2691 /* 1- count the checkers to run simultaneously */
2692 nbchk = 0;
2693 mininter = 0;
2694 newsrv = curproxy->srv;
2695 while (newsrv != NULL) {
2696 if (newsrv->state & SRV_CHECKED) {
2697 if (!mininter || mininter > newsrv->inter)
2698 mininter = newsrv->inter;
2699 nbchk++;
2700 }
2701 newsrv = newsrv->next;
2702 }
2703
2704 /* 2- start them as far as possible from each others while respecting
2705 * their own intervals. For this, we will start them after their own
2706 * interval added to the min interval divided by the number of servers,
2707 * weighted by the server's position in the list.
2708 */
2709 if (nbchk > 0) {
2710 struct task *t;
2711 int srvpos;
2712
2713 newsrv = curproxy->srv;
2714 srvpos = 0;
2715 while (newsrv != NULL) {
2716 /* should this server be checked ? */
2717 if (newsrv->state & SRV_CHECKED) {
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002718 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002719 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2720 return -1;
2721 }
2722
Willy Tarreau964c9362007-01-07 00:38:00 +01002723 t->wq = NULL;
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002724 t->qlist.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002725 t->state = TASK_IDLE;
2726 t->process = process_chk;
2727 t->context = newsrv;
2728
2729 /* check this every ms */
Willy Tarreau42aae5c2007-04-29 17:43:56 +02002730 tv_ms_add(&t->expire, &now,
2731 newsrv->inter + mininter * srvpos / nbchk);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 task_queue(t);
2733 //task_wakeup(&rq, t);
2734 srvpos++;
2735 }
2736 newsrv = newsrv->next;
2737 }
2738 }
2739
2740 curproxy = curproxy->next;
2741 }
2742 if (cfgerr > 0) {
2743 Alert("Errors found in configuration file, aborting.\n");
2744 return -1;
2745 }
2746 else
2747 return 0;
2748}
2749
2750
2751
2752/*
2753 * Local variables:
2754 * c-indent-level: 8
2755 * c-basic-offset: 8
2756 * End:
2757 */