blob: 43ed8aa81077e3d0c8e1e5459344836f742d9140 [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 },
Alexandre Cassen87ea5482007-10-11 20:48:58 +020095 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010096 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
97 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
98 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
99 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
100 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
101 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
102 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
103 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
104 { "forceclose", PR_O_FORCE_CLO | PR_O_HTTP_CLOSE, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100105#ifdef CONFIG_HAP_TCPSPLICE
106 { "tcpsplice", PR_O_TCPSPLICE , PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
107#endif
108
Willy Tarreau13943ab2006-12-31 00:24:10 +0100109 { NULL, 0, 0 }
110};
111
Willy Tarreaubaaee002006-06-26 02:48:02 +0200112
113static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
114int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
115int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
116
117/*
118 * converts <str> to a list of listeners which are dynamically allocated.
119 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
120 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
121 * - <port> is a numerical port from 1 to 65535 ;
122 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
123 * This can be repeated as many times as necessary, separated by a coma.
124 * The <tail> argument is a pointer to a current list which should be appended
125 * to the tail of the new list. The pointer to the new list is returned.
126 */
127static struct listener *str2listener(char *str, struct listener *tail)
128{
129 struct listener *l;
130 char *c, *next, *range, *dupstr;
131 int port, end;
132
133 next = dupstr = strdup(str);
134
135 while (next && *next) {
136 struct sockaddr_storage ss;
137
138 str = next;
139 /* 1) look for the end of the first address */
140 if ((next = strrchr(str, ',')) != NULL) {
141 *next++ = 0;
142 }
143
144 /* 2) look for the addr/port delimiter, it's the last colon. */
145 if ((range = strrchr(str, ':')) == NULL) {
146 Alert("Missing port number: '%s'\n", str);
147 goto fail;
148 }
149
150 *range++ = 0;
151
152 if (strrchr(str, ':') != NULL) {
153 /* IPv6 address contains ':' */
154 memset(&ss, 0, sizeof(ss));
155 ss.ss_family = AF_INET6;
156
157 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
158 Alert("Invalid server address: '%s'\n", str);
159 goto fail;
160 }
161 }
162 else {
163 memset(&ss, 0, sizeof(ss));
164 ss.ss_family = AF_INET;
165
166 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
167 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
168 }
169 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
170 struct hostent *he;
171
172 if ((he = gethostbyname(str)) == NULL) {
173 Alert("Invalid server name: '%s'\n", str);
174 goto fail;
175 }
176 else
177 ((struct sockaddr_in *)&ss)->sin_addr =
178 *(struct in_addr *) *(he->h_addr_list);
179 }
180 }
181
182 /* 3) look for the port-end delimiter */
183 if ((c = strchr(range, '-')) != NULL) {
184 *c++ = 0;
185 end = atol(c);
186 }
187 else {
188 end = atol(range);
189 }
190
191 port = atol(range);
192
193 if (port < 1 || port > 65535) {
194 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
195 goto fail;
196 }
197
198 if (end < 1 || end > 65535) {
199 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
200 goto fail;
201 }
202
203 for (; port <= end; port++) {
204 l = (struct listener *)calloc(1, sizeof(struct listener));
205 l->next = tail;
206 tail = l;
207
208 l->fd = -1;
209 l->addr = ss;
210 if (ss.ss_family == AF_INET6)
211 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
212 else
213 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
214
215 } /* end for(port) */
216 } /* end while(next) */
217 free(dupstr);
218 return tail;
219 fail:
220 free(dupstr);
221 return NULL;
222}
223
Willy Tarreau977b8e42006-12-29 14:19:17 +0100224/*
225 * Sends a warning if proxy <proxy> does not have at least one of the
226 * capabilities in <cap>. An optionnal <hint> may be added at the end
227 * of the warning to help the user. Returns 1 if a warning was emitted
228 * or 0 if the condition is valid.
229 */
230int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
231{
232 char *msg;
233
234 switch (cap) {
235 case PR_CAP_BE: msg = "no backend"; break;
236 case PR_CAP_FE: msg = "no frontend"; break;
237 case PR_CAP_RS: msg = "no ruleset"; break;
238 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
239 default: msg = "not enough"; break;
240 }
241
242 if (!(proxy->cap & cap)) {
243 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100244 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100245 return 1;
246 }
247 return 0;
248}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249
250/*
251 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
252 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200253int cfg_parse_global(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254{
255
256 if (!strcmp(args[0], "global")) { /* new section */
257 /* no option, nothing special to do */
258 return 0;
259 }
260 else if (!strcmp(args[0], "daemon")) {
261 global.mode |= MODE_DAEMON;
262 }
263 else if (!strcmp(args[0], "debug")) {
264 global.mode |= MODE_DEBUG;
265 }
266 else if (!strcmp(args[0], "noepoll")) {
267 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
268 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200269 else if (!strcmp(args[0], "nosepoll")) {
270 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
271 }
272 else if (!strcmp(args[0], "nokqueue")) {
273 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275 else if (!strcmp(args[0], "nopoll")) {
276 cfg_polling_mechanism &= ~POLL_USE_POLL;
277 }
278 else if (!strcmp(args[0], "quiet")) {
279 global.mode |= MODE_QUIET;
280 }
281 else if (!strcmp(args[0], "stats")) {
282 global.mode |= MODE_STATS;
283 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200284 else if (!strcmp(args[0], "tune.maxpollevents")) {
285 if (global.tune.maxpollevents != 0) {
286 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
287 return 0;
288 }
289 if (*(args[1]) == 0) {
290 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
291 return -1;
292 }
293 global.tune.maxpollevents = atol(args[1]);
294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295 else if (!strcmp(args[0], "uid")) {
296 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200297 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 return 0;
299 }
300 if (*(args[1]) == 0) {
301 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
302 return -1;
303 }
304 global.uid = atol(args[1]);
305 }
306 else if (!strcmp(args[0], "gid")) {
307 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200308 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200309 return 0;
310 }
311 if (*(args[1]) == 0) {
312 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
313 return -1;
314 }
315 global.gid = atol(args[1]);
316 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200317 /* user/group name handling */
318 else if (!strcmp(args[0], "user")) {
319 struct passwd *ha_user;
320 if (global.uid != 0) {
321 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
322 return 0;
323 }
324 errno = 0;
325 ha_user = getpwnam(args[1]);
326 if (ha_user != NULL) {
327 global.uid = (int)ha_user->pw_uid;
328 }
329 else {
330 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
331 exit(1);
332 }
333 }
334 else if (!strcmp(args[0], "group")) {
335 struct group *ha_group;
336 if (global.gid != 0) {
337 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
338 return 0;
339 }
340 errno = 0;
341 ha_group = getgrnam(args[1]);
342 if (ha_group != NULL) {
343 global.gid = (int)ha_group->gr_gid;
344 }
345 else {
346 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
347 exit(1);
348 }
349 }
350 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200351 else if (!strcmp(args[0], "nbproc")) {
352 if (global.nbproc != 0) {
353 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
354 return 0;
355 }
356 if (*(args[1]) == 0) {
357 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
358 return -1;
359 }
360 global.nbproc = atol(args[1]);
361 }
362 else if (!strcmp(args[0], "maxconn")) {
363 if (global.maxconn != 0) {
364 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
365 return 0;
366 }
367 if (*(args[1]) == 0) {
368 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
369 return -1;
370 }
371 global.maxconn = atol(args[1]);
372#ifdef SYSTEM_MAXCONN
373 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
374 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);
375 global.maxconn = DEFAULT_MAXCONN;
376 }
377#endif /* SYSTEM_MAXCONN */
378 }
379 else if (!strcmp(args[0], "ulimit-n")) {
380 if (global.rlimit_nofile != 0) {
381 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
382 return 0;
383 }
384 if (*(args[1]) == 0) {
385 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
386 return -1;
387 }
388 global.rlimit_nofile = atol(args[1]);
389 }
390 else if (!strcmp(args[0], "chroot")) {
391 if (global.chroot != NULL) {
392 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
393 return 0;
394 }
395 if (*(args[1]) == 0) {
396 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
397 return -1;
398 }
399 global.chroot = strdup(args[1]);
400 }
401 else if (!strcmp(args[0], "pidfile")) {
402 if (global.pidfile != NULL) {
403 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
404 return 0;
405 }
406 if (*(args[1]) == 0) {
407 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
408 return -1;
409 }
410 global.pidfile = strdup(args[1]);
411 }
412 else if (!strcmp(args[0], "log")) { /* syslog server address */
413 struct sockaddr_in *sa;
414 int facility, level;
415
416 if (*(args[1]) == 0 || *(args[2]) == 0) {
417 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
418 return -1;
419 }
420
421 facility = get_log_facility(args[2]);
422 if (facility < 0) {
423 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
424 exit(1);
425 }
426
427 level = 7; /* max syslog level = debug */
428 if (*(args[3])) {
429 level = get_log_level(args[3]);
430 if (level < 0) {
431 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
432 exit(1);
433 }
434 }
435
436 sa = str2sa(args[1]);
437 if (!sa->sin_port)
438 sa->sin_port = htons(SYSLOG_PORT);
439
440 if (global.logfac1 == -1) {
441 global.logsrv1 = *sa;
442 global.logfac1 = facility;
443 global.loglev1 = level;
444 }
445 else if (global.logfac2 == -1) {
446 global.logsrv2 = *sa;
447 global.logfac2 = facility;
448 global.loglev2 = level;
449 }
450 else {
451 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
452 return -1;
453 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200454 }
455 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
456 if (global.spread_checks != 0) {
457 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
458 return 0;
459 }
460 if (*(args[1]) == 0) {
461 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
462 return -1;
463 }
464 global.spread_checks = atol(args[1]);
465 if (global.spread_checks < 0 || global.spread_checks > 50) {
466 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
467 return -1;
468 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200469 }
470 else {
471 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
472 return -1;
473 }
474 return 0;
475}
476
477
478static void init_default_instance()
479{
480 memset(&defproxy, 0, sizeof(defproxy));
481 defproxy.mode = PR_MODE_TCP;
482 defproxy.state = PR_STNEW;
483 defproxy.maxconn = cfg_maxpconn;
484 defproxy.conn_retries = CONN_RETRIES;
485 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaufdd0f552007-09-17 11:12:40 +0200486 tv_eternity(&defproxy.clitimeout);
487 tv_eternity(&defproxy.contimeout);
488 tv_eternity(&defproxy.srvtimeout);
489 tv_eternity(&defproxy.appsession_timeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200490}
491
492/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100493 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
494 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200495 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200496int cfg_parse_listen(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200497{
498 static struct proxy *curproxy = NULL;
499 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200500 const char *err;
Willy Tarreauee991362007-05-14 14:37:50 +0200501 int rc, val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200502
Willy Tarreau977b8e42006-12-29 14:19:17 +0100503 if (!strcmp(args[0], "listen"))
504 rc = PR_CAP_LISTEN;
505 else if (!strcmp(args[0], "frontend"))
506 rc = PR_CAP_FE | PR_CAP_RS;
507 else if (!strcmp(args[0], "backend"))
508 rc = PR_CAP_BE | PR_CAP_RS;
509 else if (!strcmp(args[0], "ruleset"))
510 rc = PR_CAP_RS;
511 else
512 rc = PR_CAP_NONE;
513
514 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200515 if (!*args[1]) {
516 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
517 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
518 file, linenum, args[0]);
519 return -1;
520 }
521
522 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
523 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
524 return -1;
525 }
526
527 curproxy->next = proxy;
528 proxy = curproxy;
529 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200530 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200531 LIST_INIT(&curproxy->block_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200532 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200533
Willy Tarreauee991362007-05-14 14:37:50 +0200534 /* Timeouts are defined as -1, so we cannot use the zeroed area
535 * as a default value.
536 */
537 tv_eternity(&curproxy->clitimeout);
538 tv_eternity(&curproxy->srvtimeout);
539 tv_eternity(&curproxy->contimeout);
540 tv_eternity(&curproxy->appsession_timeout);
541
Willy Tarreaubaaee002006-06-26 02:48:02 +0200542 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100543 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200544
545 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100546 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200547 curproxy->listen = str2listener(args[2], curproxy->listen);
548 if (!curproxy->listen)
549 return -1;
550 global.maxsock++;
551 }
552
553 /* set default values */
554 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200555 curproxy->options = defproxy.options;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200556 curproxy->except_net = defproxy.except_net;
557 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200558
Willy Tarreau977b8e42006-12-29 14:19:17 +0100559 if (curproxy->cap & PR_CAP_FE) {
560 curproxy->maxconn = defproxy.maxconn;
561
562 /* initialize error relocations */
563 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
564 if (defproxy.errmsg[rc].str)
565 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
566 }
567
568 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
569 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200570
Willy Tarreau977b8e42006-12-29 14:19:17 +0100571 if (curproxy->cap & PR_CAP_BE) {
572 curproxy->fullconn = defproxy.fullconn;
573 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200574
Willy Tarreau977b8e42006-12-29 14:19:17 +0100575 if (defproxy.check_req)
576 curproxy->check_req = strdup(defproxy.check_req);
577 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200578
Willy Tarreau977b8e42006-12-29 14:19:17 +0100579 if (defproxy.cookie_name)
580 curproxy->cookie_name = strdup(defproxy.cookie_name);
581 curproxy->cookie_len = defproxy.cookie_len;
582 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200583
Willy Tarreau977b8e42006-12-29 14:19:17 +0100584 if (curproxy->cap & PR_CAP_RS) {
585 if (defproxy.capture_name)
586 curproxy->capture_name = strdup(defproxy.capture_name);
587 curproxy->capture_namelen = defproxy.capture_namelen;
588 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590
Willy Tarreau977b8e42006-12-29 14:19:17 +0100591 if (curproxy->cap & PR_CAP_FE) {
592 curproxy->clitimeout = defproxy.clitimeout;
593 curproxy->uri_auth = defproxy.uri_auth;
594 curproxy->mon_net = defproxy.mon_net;
595 curproxy->mon_mask = defproxy.mon_mask;
596 if (defproxy.monitor_uri)
597 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
598 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100599 if (defproxy.defbe.name)
600 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100601 }
602
603 if (curproxy->cap & PR_CAP_BE) {
604 curproxy->contimeout = defproxy.contimeout;
605 curproxy->srvtimeout = defproxy.srvtimeout;
606 curproxy->source_addr = defproxy.source_addr;
607 }
608
Willy Tarreaubaaee002006-06-26 02:48:02 +0200609 curproxy->mode = defproxy.mode;
610 curproxy->logfac1 = defproxy.logfac1;
611 curproxy->logsrv1 = defproxy.logsrv1;
612 curproxy->loglev1 = defproxy.loglev1;
613 curproxy->logfac2 = defproxy.logfac2;
614 curproxy->logsrv2 = defproxy.logsrv2;
615 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616 curproxy->grace = defproxy.grace;
Willy Tarreau1c47f852006-07-09 08:22:27 +0200617
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 return 0;
619 }
620 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
621 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100622 /* FIXME-20070101: we should do this too at the end of the
623 * config parsing to free all default values.
624 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200625 if (defproxy.check_req) free(defproxy.check_req);
626 if (defproxy.cookie_name) free(defproxy.cookie_name);
627 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200628 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100629 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100630
631 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
632 if (defproxy.errmsg[rc].len)
633 free(defproxy.errmsg[rc].str);
634 }
635
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 /* we cannot free uri_auth because it might already be used */
637 init_default_instance();
638 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100639 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200640 return 0;
641 }
642 else if (curproxy == NULL) {
643 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
644 return -1;
645 }
646
Willy Tarreau977b8e42006-12-29 14:19:17 +0100647
648 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200649 if (!strcmp(args[0], "bind")) { /* new listen addresses */
650 if (curproxy == &defproxy) {
651 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
652 return -1;
653 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100654 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
655 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656
657 if (strchr(args[1], ':') == NULL) {
658 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
659 file, linenum, args[0]);
660 return -1;
661 }
662 curproxy->listen = str2listener(args[1], curproxy->listen);
663 if (!curproxy->listen)
664 return -1;
665 global.maxsock++;
666 return 0;
667 }
668 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
669 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
670 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
671 file, linenum, args[0]);
672 return -1;
673 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100674 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
675 return 0;
676
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 /* flush useless bits */
678 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
679 return 0;
680 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200681 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100682 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
683 return 0;
684
Willy Tarreau1c47f852006-07-09 08:22:27 +0200685 if (!*args[1]) {
686 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
687 file, linenum, args[0]);
688 return -1;
689 }
690
691 if (curproxy->monitor_uri != NULL)
692 free(curproxy->monitor_uri);
693
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100694 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200695 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100696 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200697 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
698
699 return 0;
700 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
702 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
703 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
704 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
705 else {
706 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
707 return -1;
708 }
709 }
710 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
711 curproxy->state = PR_STSTOPPED;
712 }
713 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
714 curproxy->state = PR_STNEW;
715 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200716 else if (!strcmp(args[0], "acl")) { /* add an ACL */
717 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
718 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
719 file, linenum, args[1]);
720 return -1;
721 }
722 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200723 else if (!strcmp(args[0], "cookie")) { /* cookie name */
724 int cur_arg;
725 // if (curproxy == &defproxy) {
726 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
727 // return -1;
728 // }
729
Willy Tarreau977b8e42006-12-29 14:19:17 +0100730 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
731 return 0;
732
Willy Tarreaubaaee002006-06-26 02:48:02 +0200733 if (curproxy->cookie_name != NULL) {
734 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
735 // file, linenum);
736 // return 0;
737 free(curproxy->cookie_name);
738 }
739
740 if (*(args[1]) == 0) {
741 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
742 file, linenum, args[0]);
743 return -1;
744 }
745 curproxy->cookie_name = strdup(args[1]);
746 curproxy->cookie_len = strlen(curproxy->cookie_name);
747
748 cur_arg = 2;
749 while (*(args[cur_arg])) {
750 if (!strcmp(args[cur_arg], "rewrite")) {
751 curproxy->options |= PR_O_COOK_RW;
752 }
753 else if (!strcmp(args[cur_arg], "indirect")) {
754 curproxy->options |= PR_O_COOK_IND;
755 }
756 else if (!strcmp(args[cur_arg], "insert")) {
757 curproxy->options |= PR_O_COOK_INS;
758 }
759 else if (!strcmp(args[cur_arg], "nocache")) {
760 curproxy->options |= PR_O_COOK_NOC;
761 }
762 else if (!strcmp(args[cur_arg], "postonly")) {
763 curproxy->options |= PR_O_COOK_POST;
764 }
765 else if (!strcmp(args[cur_arg], "prefix")) {
766 curproxy->options |= PR_O_COOK_PFX;
767 }
768 else {
769 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
770 file, linenum, args[0]);
771 return -1;
772 }
773 cur_arg++;
774 }
775 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
776 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
777 file, linenum);
778 return -1;
779 }
780
781 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
782 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
783 file, linenum);
784 return -1;
785 }
786 }/* end else if (!strcmp(args[0], "cookie")) */
787 else if (!strcmp(args[0], "appsession")) { /* cookie name */
788 // if (curproxy == &defproxy) {
789 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
790 // return -1;
791 // }
792
Willy Tarreau977b8e42006-12-29 14:19:17 +0100793 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
794 return 0;
795
Willy Tarreaubaaee002006-06-26 02:48:02 +0200796 if (curproxy->appsession_name != NULL) {
797 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
798 // file, linenum);
799 // return 0;
800 free(curproxy->appsession_name);
801 }
802
803 if (*(args[5]) == 0) {
804 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
805 file, linenum, args[0]);
806 return -1;
807 }
808 have_appsession = 1;
809 curproxy->appsession_name = strdup(args[1]);
810 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
811 curproxy->appsession_len = atoi(args[3]);
Willy Tarreauee991362007-05-14 14:37:50 +0200812 val = atoi(args[5]);
813 if (val > 0)
814 __tv_from_ms(&curproxy->appsession_timeout, val);
815 else
816 tv_eternity(&curproxy->appsession_timeout);
817
Willy Tarreau51041c72007-09-09 21:56:53 +0200818 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
819 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200820 return -1;
821 }
822 } /* Url App Session */
823 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100824 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
825 return 0;
826
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
828 // if (curproxy == &defproxy) {
829 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
830 // return -1;
831 // }
832
833 if (curproxy->capture_name != NULL) {
834 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
835 // file, linenum, args[0]);
836 // return 0;
837 free(curproxy->capture_name);
838 }
839
840 if (*(args[4]) == 0) {
841 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
842 file, linenum, args[0]);
843 return -1;
844 }
845 curproxy->capture_name = strdup(args[2]);
846 curproxy->capture_namelen = strlen(curproxy->capture_name);
847 curproxy->capture_len = atol(args[4]);
848 if (curproxy->capture_len >= CAPTURE_LEN) {
849 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
850 file, linenum, CAPTURE_LEN - 1);
851 curproxy->capture_len = CAPTURE_LEN - 1;
852 }
853 curproxy->to_log |= LW_COOKIE;
854 }
855 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
856 struct cap_hdr *hdr;
857
858 if (curproxy == &defproxy) {
859 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
860 return -1;
861 }
862
863 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
864 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
865 file, linenum, args[0], args[1]);
866 return -1;
867 }
868
869 hdr = calloc(sizeof(struct cap_hdr), 1);
870 hdr->next = curproxy->req_cap;
871 hdr->name = strdup(args[3]);
872 hdr->namelen = strlen(args[3]);
873 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200874 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200875 hdr->index = curproxy->nb_req_cap++;
876 curproxy->req_cap = hdr;
877 curproxy->to_log |= LW_REQHDR;
878 }
879 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
880 struct cap_hdr *hdr;
881
882 if (curproxy == &defproxy) {
883 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
884 return -1;
885 }
886
887 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
888 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
889 file, linenum, args[0], args[1]);
890 return -1;
891 }
892 hdr = calloc(sizeof(struct cap_hdr), 1);
893 hdr->next = curproxy->rsp_cap;
894 hdr->name = strdup(args[3]);
895 hdr->namelen = strlen(args[3]);
896 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200897 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898 hdr->index = curproxy->nb_rsp_cap++;
899 curproxy->rsp_cap = hdr;
900 curproxy->to_log |= LW_RSPHDR;
901 }
902 else {
903 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
904 file, linenum, args[0]);
905 return -1;
906 }
907 }
908 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200909 if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
911 return 0;
912 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100913 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
914 return 0;
915
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916 if (*(args[1]) == 0) {
917 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
918 file, linenum, args[0]);
919 return -1;
920 }
Willy Tarreauee991362007-05-14 14:37:50 +0200921 val = atoi(args[1]);
922 if (val > 0)
923 __tv_from_ms(&curproxy->contimeout, val);
924 else
925 tv_eternity(&curproxy->contimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 }
927 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200928 if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
930 file, linenum, args[0]);
931 return 0;
932 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100933 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
934 return 0;
935
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936 if (*(args[1]) == 0) {
937 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
938 file, linenum, args[0]);
939 return -1;
940 }
Willy Tarreauee991362007-05-14 14:37:50 +0200941 val = atoi(args[1]);
942 if (val > 0)
943 __tv_from_ms(&curproxy->clitimeout, val);
944 else
945 tv_eternity(&curproxy->clitimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 }
947 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200948 if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
950 return 0;
951 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100952 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
953 return 0;
954
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 if (*(args[1]) == 0) {
956 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
957 file, linenum, args[0]);
958 return -1;
959 }
Willy Tarreauee991362007-05-14 14:37:50 +0200960 val = atoi(args[1]);
961 if (val > 0)
962 __tv_from_ms(&curproxy->srvtimeout, val);
963 else
964 tv_eternity(&curproxy->srvtimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200965 }
966 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100967 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
968 return 0;
969
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 if (*(args[1]) == 0) {
971 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
972 file, linenum, args[0]);
973 return -1;
974 }
975 curproxy->conn_retries = atol(args[1]);
976 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200977 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
978 int pol = ACL_COND_NONE;
979 struct acl_cond *cond;
980
981 if (!strcmp(args[1], "if"))
982 pol = ACL_COND_IF;
983 else if (!strcmp(args[1], "unless"))
984 pol = ACL_COND_UNLESS;
985
986 if (pol == ACL_COND_NONE) {
987 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
988 file, linenum, args[0]);
989 return -1;
990 }
991
992 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
993 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
994 file, linenum);
995 return -1;
996 }
997 LIST_ADDQ(&curproxy->block_cond, &cond->list);
998 }
Willy Tarreau55ea7572007-06-17 19:56:27 +0200999 else if (!strcmp(args[0], "use_backend")) { /* early blocking based on ACLs */
1000 int pol = ACL_COND_NONE;
1001 struct acl_cond *cond;
1002 struct switching_rule *rule;
1003
1004 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1005 return 0;
1006
1007 if (*(args[1]) == 0) {
1008 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1009 return -1;
1010 }
1011
1012 if (!strcmp(args[2], "if"))
1013 pol = ACL_COND_IF;
1014 else if (!strcmp(args[2], "unless"))
1015 pol = ACL_COND_UNLESS;
1016
1017 if (pol == ACL_COND_NONE) {
1018 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1019 file, linenum, args[0]);
1020 return -1;
1021 }
1022
1023 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1024 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1025 file, linenum);
1026 return -1;
1027 }
1028
1029 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1030 rule->cond = cond;
1031 rule->be.name = strdup(args[1]);
1032 LIST_INIT(&rule->list);
1033 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1034 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001035 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001036 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1037 return 0;
1038
Willy Tarreaubaaee002006-06-26 02:48:02 +02001039 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1040 curproxy->uri_auth = NULL; /* we must detach from the default config */
1041
1042 if (*(args[1]) == 0) {
1043 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1044 return -1;
1045 } else if (!strcmp(args[1], "uri")) {
1046 if (*(args[2]) == 0) {
1047 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1048 return -1;
1049 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1050 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1051 return -1;
1052 }
1053 } else if (!strcmp(args[1], "realm")) {
1054 if (*(args[2]) == 0) {
1055 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1056 return -1;
1057 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1058 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1059 return -1;
1060 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001061 } else if (!strcmp(args[1], "refresh")) {
1062 int interval = atoi(args[2]);
1063
1064 if (interval < 0) {
1065 Alert("parsing [%s:%d] : 'refresh' needs a positive interval in seconds.\n", file, linenum);
1066 return -1;
1067 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1068 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1069 return -1;
1070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 } else if (!strcmp(args[1], "auth")) {
1072 if (*(args[2]) == 0) {
1073 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1074 return -1;
1075 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1076 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1077 return -1;
1078 }
1079 } else if (!strcmp(args[1], "scope")) {
1080 if (*(args[2]) == 0) {
1081 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1082 return -1;
1083 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1084 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1085 return -1;
1086 }
1087 } else if (!strcmp(args[1], "enable")) {
1088 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1089 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1090 return -1;
1091 }
1092 } else {
1093 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'uri', 'realm', 'auth' or 'enable').\n",
1094 file, linenum, args[0]);
1095 return -1;
1096 }
1097 }
1098 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001099 int optnum;
1100
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 if (*(args[1]) == 0) {
1102 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
1103 return -1;
1104 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001105
1106 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1107 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1108 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1109 return 0;
1110 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001111 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001112 return 0;
1113 }
1114 }
1115
1116 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117 /* generate a complete HTTP log */
1118 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1119 else if (!strcmp(args[1], "tcplog"))
1120 /* generate a detailed TCP log */
1121 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 else if (!strcmp(args[1], "tcpka")) {
1123 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001124 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1125 return 0;
1126
1127 if (curproxy->cap & PR_CAP_FE)
1128 curproxy->options |= PR_O_TCP_CLI_KA;
1129 if (curproxy->cap & PR_CAP_BE)
1130 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001131 }
1132 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001133 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1134 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 /* use HTTP request to check servers' health */
1136 if (curproxy->check_req != NULL) {
1137 free(curproxy->check_req);
1138 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001139 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001140 curproxy->options &= ~PR_O_SMTP_CHK;
1141 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001142 if (!*args[2]) { /* no argument */
1143 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1144 curproxy->check_len = strlen(DEF_CHECK_REQ);
1145 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001146 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147 curproxy->check_req = (char *)malloc(reqlen);
1148 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1149 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1150 } else { /* more arguments : METHOD URI [HTTP_VER] */
1151 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1152 if (*args[4])
1153 reqlen += strlen(args[4]);
1154 else
1155 reqlen += strlen("HTTP/1.0");
1156
1157 curproxy->check_req = (char *)malloc(reqlen);
1158 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1159 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1160 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001161 }
1162 else if (!strcmp(args[1], "ssl-hello-chk")) {
1163 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001164 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1165 return 0;
1166
Willy Tarreauf3c69202006-07-09 16:42:34 +02001167 if (curproxy->check_req != NULL) {
1168 free(curproxy->check_req);
1169 }
1170 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001171 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001172 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 }
Willy Tarreau23677902007-05-08 23:50:35 +02001174 else if (!strcmp(args[1], "smtpchk")) {
1175 /* use SMTP request to check servers' health */
1176 if (curproxy->check_req != NULL) {
1177 free(curproxy->check_req);
1178 }
1179 curproxy->options &= ~PR_O_HTTP_CHK;
1180 curproxy->options &= ~PR_O_SSL3_CHK;
1181 curproxy->options |= PR_O_SMTP_CHK;
1182
1183 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1184 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1185 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1186 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1187 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1188 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1189 curproxy->check_req = (char *)malloc(reqlen);
1190 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1191 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1192 } else {
1193 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1194 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1195 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1196 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1197 }
1198 }
1199 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001200 else if (!strcmp(args[1], "forwardfor")) {
1201 /* insert x-forwarded-for field, but not for the
1202 * IP address listed as an except.
1203 */
1204 if (*(args[2])) {
1205 if (!strcmp(args[2], "except")) {
1206 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1207 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1208 file, linenum, args[0]);
1209 return -1;
1210 }
1211 /* flush useless bits */
1212 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1213 } else {
1214 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1215 file, linenum, args[0]);
1216 return -1;
1217 }
1218 }
1219 curproxy->options |= PR_O_FWDFOR;
1220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001221 else {
1222 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1223 return -1;
1224 }
1225 return 0;
1226 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001227 else if (!strcmp(args[0], "default_backend")) {
1228 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1229 return 0;
1230
1231 if (*(args[1]) == 0) {
1232 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1233 return -1;
1234 }
1235 if (curproxy->defbe.name)
1236 free(curproxy->defbe.name);
1237 curproxy->defbe.name = strdup(args[1]);
1238 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001239 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001240 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1241 return 0;
1242
Willy Tarreaubaaee002006-06-26 02:48:02 +02001243 /* enable reconnections to dispatch */
1244 curproxy->options |= PR_O_REDISP;
1245 }
1246#ifdef TPROXY
1247 else if (!strcmp(args[0], "transparent")) {
1248 /* enable transparent proxy connections */
1249 curproxy->options |= PR_O_TRANSP;
1250 }
1251#endif
1252 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001253 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1254 return 0;
1255
Willy Tarreaubaaee002006-06-26 02:48:02 +02001256 if (*(args[1]) == 0) {
1257 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1258 return -1;
1259 }
1260 curproxy->maxconn = atol(args[1]);
1261 }
Willy Tarreau86034312006-12-29 00:10:33 +01001262 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001263 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1264 return 0;
1265
Willy Tarreau86034312006-12-29 00:10:33 +01001266 if (*(args[1]) == 0) {
1267 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1268 return -1;
1269 }
1270 curproxy->fullconn = atol(args[1]);
1271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001272 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1273 if (*(args[1]) == 0) {
1274 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1275 return -1;
1276 }
1277 curproxy->grace = atol(args[1]);
1278 }
1279 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1280 if (curproxy == &defproxy) {
1281 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1282 return -1;
1283 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001284 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1285 return 0;
1286
Willy Tarreaubaaee002006-06-26 02:48:02 +02001287 if (strchr(args[1], ':') == NULL) {
1288 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1289 return -1;
1290 }
1291 curproxy->dispatch_addr = *str2sa(args[1]);
1292 }
1293 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001294 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1295 return 0;
1296
Willy Tarreaubaaee002006-06-26 02:48:02 +02001297 if (*(args[1])) {
1298 if (!strcmp(args[1], "roundrobin")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001299 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001300 curproxy->options |= PR_O_BALANCE_RR;
1301 }
1302 else if (!strcmp(args[1], "source")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001303 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304 curproxy->options |= PR_O_BALANCE_SH;
1305 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001306 else if (!strcmp(args[1], "uri")) {
1307 curproxy->options &= ~PR_O_BALANCE;
1308 curproxy->options |= PR_O_BALANCE_UH;
1309 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001310 else {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001311 Alert("parsing [%s:%d] : '%s' only supports 'roundrobin', 'source' and 'uri' options.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001312 return -1;
1313 }
1314 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001315 else {/* if no option is set, use round-robin by default */
1316 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001317 curproxy->options |= PR_O_BALANCE_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001318 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001319 }
1320 else if (!strcmp(args[0], "server")) { /* server address */
1321 int cur_arg;
1322 char *rport;
1323 char *raddr;
1324 short realport;
1325 int do_check;
1326
1327 if (curproxy == &defproxy) {
1328 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1329 return -1;
1330 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001331 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1332 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001333
1334 if (!*args[2]) {
1335 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1336 file, linenum, args[0]);
1337 return -1;
1338 }
1339 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1340 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1341 return -1;
1342 }
1343
1344 /* the servers are linked backwards first */
1345 newsrv->next = curproxy->srv;
1346 curproxy->srv = newsrv;
1347 newsrv->proxy = curproxy;
1348
1349 LIST_INIT(&newsrv->pendconns);
1350 do_check = 0;
1351 newsrv->state = SRV_RUNNING; /* early server setup */
1352 newsrv->id = strdup(args[1]);
1353
1354 /* several ways to check the port component :
1355 * - IP => port=+0, relative
1356 * - IP: => port=+0, relative
1357 * - IP:N => port=N, absolute
1358 * - IP:+N => port=+N, relative
1359 * - IP:-N => port=-N, relative
1360 */
1361 raddr = strdup(args[2]);
1362 rport = strchr(raddr, ':');
1363 if (rport) {
1364 *rport++ = 0;
1365 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001366 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 newsrv->state |= SRV_MAPPORTS;
1368 } else {
1369 realport = 0;
1370 newsrv->state |= SRV_MAPPORTS;
1371 }
1372
1373 newsrv->addr = *str2sa(raddr);
1374 newsrv->addr.sin_port = htons(realport);
1375 free(raddr);
1376
1377 newsrv->curfd = -1; /* no health-check in progress */
1378 newsrv->inter = DEF_CHKINTR;
1379 newsrv->rise = DEF_RISETIME;
1380 newsrv->fall = DEF_FALLTIME;
1381 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001382 newsrv->uweight = 1;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001383
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 cur_arg = 3;
1385 while (*args[cur_arg]) {
1386 if (!strcmp(args[cur_arg], "cookie")) {
1387 newsrv->cookie = strdup(args[cur_arg + 1]);
1388 newsrv->cklen = strlen(args[cur_arg + 1]);
1389 cur_arg += 2;
1390 }
1391 else if (!strcmp(args[cur_arg], "rise")) {
1392 newsrv->rise = atol(args[cur_arg + 1]);
1393 newsrv->health = newsrv->rise;
1394 cur_arg += 2;
1395 }
1396 else if (!strcmp(args[cur_arg], "fall")) {
1397 newsrv->fall = atol(args[cur_arg + 1]);
1398 cur_arg += 2;
1399 }
1400 else if (!strcmp(args[cur_arg], "inter")) {
1401 newsrv->inter = atol(args[cur_arg + 1]);
1402 cur_arg += 2;
1403 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001404 else if (!strcmp(args[cur_arg], "addr")) {
1405 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001406 cur_arg += 2;
1407 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001408 else if (!strcmp(args[cur_arg], "port")) {
1409 newsrv->check_port = atol(args[cur_arg + 1]);
1410 cur_arg += 2;
1411 }
1412 else if (!strcmp(args[cur_arg], "backup")) {
1413 newsrv->state |= SRV_BACKUP;
1414 cur_arg ++;
1415 }
1416 else if (!strcmp(args[cur_arg], "weight")) {
1417 int w;
1418 w = atol(args[cur_arg + 1]);
1419 if (w < 1 || w > 256) {
1420 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1421 file, linenum, newsrv->id, w);
1422 return -1;
1423 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001424 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001425 cur_arg += 2;
1426 }
1427 else if (!strcmp(args[cur_arg], "minconn")) {
1428 newsrv->minconn = atol(args[cur_arg + 1]);
1429 cur_arg += 2;
1430 }
1431 else if (!strcmp(args[cur_arg], "maxconn")) {
1432 newsrv->maxconn = atol(args[cur_arg + 1]);
1433 cur_arg += 2;
1434 }
1435 else if (!strcmp(args[cur_arg], "check")) {
1436 global.maxsock++;
1437 do_check = 1;
1438 cur_arg += 1;
1439 }
1440 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1441 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001442#ifdef CONFIG_HAP_CTTPROXY
1443 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1444 file, linenum, "source", "usesrc");
1445#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001446 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1447 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001448#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001449 return -1;
1450 }
1451 newsrv->state |= SRV_BIND_SRC;
1452 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1453 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001454 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001455#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001456 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001457 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1458 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001459 return -1;
1460 }
1461 if (!*args[cur_arg + 1]) {
1462 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1463 file, linenum, "usesrc");
1464 return -1;
1465 }
1466 if (!strcmp(args[cur_arg + 1], "client")) {
1467 newsrv->state |= SRV_TPROXY_CLI;
1468 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1469 newsrv->state |= SRV_TPROXY_CIP;
1470 } else {
1471 newsrv->state |= SRV_TPROXY_ADDR;
1472 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1473 }
1474 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1475 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001476#else /* no CTTPROXY support */
1477 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1478 file, linenum, "usesrc");
1479 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001480#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001481 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001482 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001483#ifdef CONFIG_HAP_CTTPROXY
1484 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1485 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1486 file, linenum, "usesrc", "source");
1487 return -1;
1488 }
1489#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 else {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001491 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 +02001492 file, linenum, newsrv->id);
1493 return -1;
1494 }
1495 }
1496
1497 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001498 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1499 newsrv->check_port = newsrv->check_addr.sin_port;
1500
Willy Tarreaubaaee002006-06-26 02:48:02 +02001501 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1502 newsrv->check_port = realport; /* by default */
1503 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001504 /* not yet valid, because no port was set on
1505 * the server either. We'll check if we have
1506 * a known port on the first listener.
1507 */
1508 struct listener *l;
1509 l = curproxy->listen;
1510 if (l) {
1511 int port;
1512 port = (l->addr.ss_family == AF_INET6)
1513 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1514 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1515 newsrv->check_port = port;
1516 }
1517 }
1518 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001519 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1520 file, linenum, newsrv->id);
1521 return -1;
1522 }
1523 newsrv->state |= SRV_CHECKED;
1524 }
1525
1526 if (newsrv->state & SRV_BACKUP)
1527 curproxy->srv_bck++;
1528 else
1529 curproxy->srv_act++;
1530 }
1531 else if (!strcmp(args[0], "log")) { /* syslog server address */
1532 struct sockaddr_in *sa;
1533 int facility;
1534
1535 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1536 curproxy->logfac1 = global.logfac1;
1537 curproxy->logsrv1 = global.logsrv1;
1538 curproxy->loglev1 = global.loglev1;
1539 curproxy->logfac2 = global.logfac2;
1540 curproxy->logsrv2 = global.logsrv2;
1541 curproxy->loglev2 = global.loglev2;
1542 }
1543 else if (*(args[1]) && *(args[2])) {
1544 int level;
1545
1546 facility = get_log_facility(args[2]);
1547 if (facility < 0) {
1548 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1549 exit(1);
1550 }
1551
1552 level = 7; /* max syslog level = debug */
1553 if (*(args[3])) {
1554 level = get_log_level(args[3]);
1555 if (level < 0) {
1556 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1557 exit(1);
1558 }
1559 }
1560
1561 sa = str2sa(args[1]);
1562 if (!sa->sin_port)
1563 sa->sin_port = htons(SYSLOG_PORT);
1564
1565 if (curproxy->logfac1 == -1) {
1566 curproxy->logsrv1 = *sa;
1567 curproxy->logfac1 = facility;
1568 curproxy->loglev1 = level;
1569 }
1570 else if (curproxy->logfac2 == -1) {
1571 curproxy->logsrv2 = *sa;
1572 curproxy->logfac2 = facility;
1573 curproxy->loglev2 = level;
1574 }
1575 else {
1576 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1577 return -1;
1578 }
1579 }
1580 else {
1581 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1582 file, linenum);
1583 return -1;
1584 }
1585 }
1586 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001587 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1588 return 0;
1589
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001591#ifdef CONFIG_HAP_CTTPROXY
1592 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1593 file, linenum, "source", "usesrc");
1594#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001595 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1596 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001597#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 return -1;
1599 }
1600
1601 curproxy->source_addr = *str2sa(args[1]);
1602 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001603 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001604#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001605 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1606 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1607 file, linenum, "usesrc");
1608 return -1;
1609 }
1610 if (!*args[3]) {
1611 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1612 file, linenum, "usesrc");
1613 return -1;
1614 }
1615
1616 if (!strcmp(args[3], "client")) {
1617 curproxy->options |= PR_O_TPXY_CLI;
1618 } else if (!strcmp(args[3], "clientip")) {
1619 curproxy->options |= PR_O_TPXY_CIP;
1620 } else {
1621 curproxy->options |= PR_O_TPXY_ADDR;
1622 curproxy->tproxy_addr = *str2sa(args[3]);
1623 }
1624 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001625#else /* no CTTPROXY support */
1626 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1627 file, linenum, "usesrc");
1628 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001629#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001630 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001632#ifdef CONFIG_HAP_CTTPROXY
1633 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1634 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1635 file, linenum, "usesrc", "source");
1636 return -1;
1637 }
1638#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace 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 || *(args[2]) == 0) {
1649 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1650 file, linenum, args[0]);
1651 return -1;
1652 }
1653
1654 preg = calloc(1, sizeof(regex_t));
1655 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1656 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1657 return -1;
1658 }
1659
1660 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1661 if (err) {
1662 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1663 file, linenum, *err);
1664 return -1;
1665 }
1666 }
1667 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1668 regex_t *preg;
1669 if (curproxy == &defproxy) {
1670 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1671 return -1;
1672 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001673 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1674 return 0;
1675
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 if (*(args[1]) == 0) {
1677 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1678 return -1;
1679 }
1680
1681 preg = calloc(1, sizeof(regex_t));
1682 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1683 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1684 return -1;
1685 }
1686
1687 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1688 }
1689 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1690 regex_t *preg;
1691 if (curproxy == &defproxy) {
1692 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1693 return -1;
1694 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001695 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1696 return 0;
1697
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698 if (*(args[1]) == 0) {
1699 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1700 return -1;
1701 }
1702
1703 preg = calloc(1, sizeof(regex_t));
1704 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1705 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1706 return -1;
1707 }
1708
1709 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1710 }
1711 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1712 regex_t *preg;
1713 if (curproxy == &defproxy) {
1714 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1715 return -1;
1716 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001717 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1718 return 0;
1719
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 if (*(args[1]) == 0) {
1721 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1722 return -1;
1723 }
1724
1725 preg = calloc(1, sizeof(regex_t));
1726 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1727 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1728 return -1;
1729 }
1730
1731 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1732 }
1733 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1734 regex_t *preg;
1735 if (curproxy == &defproxy) {
1736 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1737 return -1;
1738 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001739 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1740 return 0;
1741
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742 if (*(args[1]) == 0) {
1743 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1744 return -1;
1745 }
1746
1747 preg = calloc(1, sizeof(regex_t));
1748 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1749 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1750 return -1;
1751 }
1752
1753 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1754 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001755 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1756 regex_t *preg;
1757 if (curproxy == &defproxy) {
1758 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1759 return -1;
1760 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001761 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1762 return 0;
1763
Willy Tarreaub8750a82006-09-03 09:56:00 +02001764 if (*(args[1]) == 0) {
1765 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1766 return -1;
1767 }
1768
1769 preg = calloc(1, sizeof(regex_t));
1770 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1771 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1772 return -1;
1773 }
1774
1775 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1776 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001777 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1778 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001779 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001780 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1781 return -1;
1782 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001783 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1784 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001785
Willy Tarreau977b8e42006-12-29 14:19:17 +01001786 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001787 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1788 file, linenum, args[0]);
1789 return -1;
1790 }
1791
1792 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001793 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001794 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1795 }
1796
1797 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1798 }
1799 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1800 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001801 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001802 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1803 return -1;
1804 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001805 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1806 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001807
Willy Tarreau977b8e42006-12-29 14:19:17 +01001808 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001809 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1810 file, linenum, args[0]);
1811 return -1;
1812 }
1813
1814 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001815 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001816 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1817 }
1818
1819 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1820 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001821 else if (!strcmp(args[0], "reqirep")) { /* replace 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 || *(args[2]) == 0) {
1831 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1832 file, linenum, args[0]);
1833 return -1;
1834 }
1835
1836 preg = calloc(1, sizeof(regex_t));
1837 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1838 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1839 return -1;
1840 }
1841
1842 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1843 if (err) {
1844 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1845 file, linenum, *err);
1846 return -1;
1847 }
1848 }
1849 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1850 regex_t *preg;
1851 if (curproxy == &defproxy) {
1852 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1853 return -1;
1854 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001855 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1856 return 0;
1857
Willy Tarreaubaaee002006-06-26 02:48:02 +02001858 if (*(args[1]) == 0) {
1859 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1860 return -1;
1861 }
1862
1863 preg = calloc(1, sizeof(regex_t));
1864 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1865 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1866 return -1;
1867 }
1868
1869 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1870 }
1871 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1872 regex_t *preg;
1873 if (curproxy == &defproxy) {
1874 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1875 return -1;
1876 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001877 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1878 return 0;
1879
Willy Tarreaubaaee002006-06-26 02:48:02 +02001880 if (*(args[1]) == 0) {
1881 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1882 return -1;
1883 }
1884
1885 preg = calloc(1, sizeof(regex_t));
1886 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1887 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1888 return -1;
1889 }
1890
1891 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1892 }
1893 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1894 regex_t *preg;
1895 if (curproxy == &defproxy) {
1896 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1897 return -1;
1898 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001899 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1900 return 0;
1901
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 if (*(args[1]) == 0) {
1903 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1904 return -1;
1905 }
1906
1907 preg = calloc(1, sizeof(regex_t));
1908 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1909 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1910 return -1;
1911 }
1912
1913 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1914 }
1915 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1916 regex_t *preg;
1917 if (curproxy == &defproxy) {
1918 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1919 return -1;
1920 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001921 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1922 return 0;
1923
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 if (*(args[1]) == 0) {
1925 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1926 return -1;
1927 }
1928
1929 preg = calloc(1, sizeof(regex_t));
1930 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1931 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1932 return -1;
1933 }
1934
1935 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1936 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001937 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1938 regex_t *preg;
1939 if (curproxy == &defproxy) {
1940 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1941 return -1;
1942 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001943 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1944 return 0;
1945
Willy Tarreaub8750a82006-09-03 09:56:00 +02001946 if (*(args[1]) == 0) {
1947 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1948 return -1;
1949 }
1950
1951 preg = calloc(1, sizeof(regex_t));
1952 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1953 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1954 return -1;
1955 }
1956
1957 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1958 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001959 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1960 if (curproxy == &defproxy) {
1961 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1962 return -1;
1963 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001964 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1965 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966
1967 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
1968 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1969 return 0;
1970 }
1971
1972 if (*(args[1]) == 0) {
1973 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1974 return -1;
1975 }
1976
1977 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
1978 }
1979 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
1980 regex_t *preg;
1981
1982 if (*(args[1]) == 0 || *(args[2]) == 0) {
1983 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1984 file, linenum, args[0]);
1985 return -1;
1986 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001987 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1988 return 0;
1989
Willy Tarreaubaaee002006-06-26 02:48:02 +02001990 preg = calloc(1, sizeof(regex_t));
1991 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1992 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1993 return -1;
1994 }
1995
1996 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1997 if (err) {
1998 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1999 file, linenum, *err);
2000 return -1;
2001 }
2002 }
2003 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2004 regex_t *preg;
2005 if (curproxy == &defproxy) {
2006 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2007 return -1;
2008 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002009 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2010 return 0;
2011
Willy Tarreaubaaee002006-06-26 02:48:02 +02002012 if (*(args[1]) == 0) {
2013 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2014 return -1;
2015 }
2016
2017 preg = calloc(1, sizeof(regex_t));
2018 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2019 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2020 return -1;
2021 }
2022
2023 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2024 if (err) {
2025 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2026 file, linenum, *err);
2027 return -1;
2028 }
2029 }
2030 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2031 regex_t *preg;
2032 if (curproxy == &defproxy) {
2033 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2034 return -1;
2035 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002036 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2037 return 0;
2038
Willy Tarreaubaaee002006-06-26 02:48:02 +02002039 if (*(args[1]) == 0) {
2040 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2041 return -1;
2042 }
2043
2044 preg = calloc(1, sizeof(regex_t));
2045 if (regcomp(preg, args[1], REG_EXTENDED) != 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_DENY, 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], "rspirep")) { /* replace 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;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002065
2066 if (*(args[1]) == 0 || *(args[2]) == 0) {
2067 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2068 file, linenum, args[0]);
2069 return -1;
2070 }
2071
2072 preg = calloc(1, sizeof(regex_t));
2073 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2074 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2075 return -1;
2076 }
2077
2078 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2079 if (err) {
2080 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2081 file, linenum, *err);
2082 return -1;
2083 }
2084 }
2085 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2086 regex_t *preg;
2087 if (curproxy == &defproxy) {
2088 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2089 return -1;
2090 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002091 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2092 return 0;
2093
Willy Tarreaubaaee002006-06-26 02:48:02 +02002094 if (*(args[1]) == 0) {
2095 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2096 return -1;
2097 }
2098
2099 preg = calloc(1, sizeof(regex_t));
2100 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2101 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2102 return -1;
2103 }
2104
2105 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2106 if (err) {
2107 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2108 file, linenum, *err);
2109 return -1;
2110 }
2111 }
2112 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2113 regex_t *preg;
2114 if (curproxy == &defproxy) {
2115 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2116 return -1;
2117 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002118 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2119 return 0;
2120
Willy Tarreaubaaee002006-06-26 02:48:02 +02002121 if (*(args[1]) == 0) {
2122 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2123 return -1;
2124 }
2125
2126 preg = calloc(1, sizeof(regex_t));
2127 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2128 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2129 return -1;
2130 }
2131
2132 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2133 if (err) {
2134 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2135 file, linenum, *err);
2136 return -1;
2137 }
2138 }
2139 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2140 if (curproxy == &defproxy) {
2141 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2142 return -1;
2143 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002144 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2145 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002146
2147 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2148 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2149 return 0;
2150 }
2151
2152 if (*(args[1]) == 0) {
2153 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2154 return -1;
2155 }
2156
2157 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2158 }
2159 else if (!strcmp(args[0], "errorloc") ||
2160 !strcmp(args[0], "errorloc302") ||
2161 !strcmp(args[0], "errorloc303")) { /* error location */
2162 int errnum, errlen;
2163 char *err;
2164
Willy Tarreau977b8e42006-12-29 14:19:17 +01002165 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2166 return 0;
2167
Willy Tarreaubaaee002006-06-26 02:48:02 +02002168 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002169 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002170 return -1;
2171 }
2172
2173 errnum = atol(args[1]);
2174 if (!strcmp(args[0], "errorloc303")) {
2175 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2176 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2177 } else {
2178 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2179 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2180 }
2181
Willy Tarreau0f772532006-12-23 20:51:41 +01002182 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2183 if (http_err_codes[rc] == errnum) {
2184 if (curproxy->errmsg[rc].str)
2185 free(curproxy->errmsg[rc].str);
2186 curproxy->errmsg[rc].str = err;
2187 curproxy->errmsg[rc].len = errlen;
2188 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002190 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002191
2192 if (rc >= HTTP_ERR_SIZE) {
2193 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2194 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002195 free(err);
2196 }
2197 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002198 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2199 int errnum, errlen, fd;
2200 char *err;
2201 struct stat stat;
2202
2203 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2204 return 0;
2205
2206 if (*(args[2]) == 0) {
2207 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum);
2208 return -1;
2209 }
2210
2211 fd = open(args[2], O_RDONLY);
2212 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2213 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2214 file, linenum, args[2], args[1]);
2215 if (fd >= 0)
2216 close(fd);
2217 return -1;
2218 }
2219
2220 if (stat.st_size <= BUFSIZE) {
2221 errlen = stat.st_size;
2222 } else {
2223 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2224 file, linenum, args[2], BUFSIZE);
2225 errlen = BUFSIZE;
2226 }
2227
2228 err = malloc(errlen); /* malloc() must succeed during parsing */
2229 errnum = read(fd, err, errlen);
2230 if (errnum != errlen) {
2231 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
2232 file, linenum, args[2], args[1]);
2233 close(fd);
2234 free(err);
2235 return -1;
2236 }
2237 close(fd);
2238
2239 errnum = atol(args[1]);
2240 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2241 if (http_err_codes[rc] == errnum) {
2242 if (curproxy->errmsg[rc].str)
2243 free(curproxy->errmsg[rc].str);
2244 curproxy->errmsg[rc].str = err;
2245 curproxy->errmsg[rc].len = errlen;
2246 break;
2247 }
2248 }
2249
2250 if (rc >= HTTP_ERR_SIZE) {
2251 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
2252 file, linenum, errnum);
2253 free(err);
2254 }
2255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 else {
2257 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2258 return -1;
2259 }
2260 return 0;
2261}
2262
2263
2264/*
2265 * This function reads and parses the configuration file given in the argument.
2266 * returns 0 if OK, -1 if error.
2267 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002268int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002269{
2270 char thisline[256];
2271 char *line;
2272 FILE *f;
2273 int linenum = 0;
2274 char *end;
Willy Tarreau540abe42007-05-02 20:50:16 +02002275 char *args[MAX_LINE_ARGS + 1];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 int arg;
2277 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002278 int confsect = CFG_NONE;
2279
2280 struct proxy *curproxy = NULL;
2281 struct server *newsrv = NULL;
2282
2283 if ((f=fopen(file,"r")) == NULL)
2284 return -1;
2285
2286 init_default_instance();
2287
2288 while (fgets(line = thisline, sizeof(thisline), f) != NULL) {
2289 linenum++;
2290
2291 end = line + strlen(line);
2292
2293 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002294 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295 line++;
2296
2297 arg = 0;
2298 args[arg] = line;
2299
2300 while (*line && arg < MAX_LINE_ARGS) {
2301 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2302 * C equivalent value. Other combinations left unchanged (eg: \1).
2303 */
2304 if (*line == '\\') {
2305 int skip = 0;
2306 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2307 *line = line[1];
2308 skip = 1;
2309 }
2310 else if (line[1] == 'r') {
2311 *line = '\r';
2312 skip = 1;
2313 }
2314 else if (line[1] == 'n') {
2315 *line = '\n';
2316 skip = 1;
2317 }
2318 else if (line[1] == 't') {
2319 *line = '\t';
2320 skip = 1;
2321 }
2322 else if (line[1] == 'x') {
2323 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2324 unsigned char hex1, hex2;
2325 hex1 = toupper(line[2]) - '0';
2326 hex2 = toupper(line[3]) - '0';
2327 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2328 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2329 *line = (hex1<<4) + hex2;
2330 skip = 3;
2331 }
2332 else {
2333 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2334 return -1;
2335 }
2336 }
2337 if (skip) {
2338 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2339 end -= skip;
2340 }
2341 line++;
2342 }
2343 else if (*line == '#' || *line == '\n' || *line == '\r') {
2344 /* end of string, end of loop */
2345 *line = 0;
2346 break;
2347 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002348 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002349 /* a non-escaped space is an argument separator */
2350 *line++ = 0;
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002351 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002352 line++;
2353 args[++arg] = line;
2354 }
2355 else {
2356 line++;
2357 }
2358 }
2359
2360 /* empty line */
2361 if (!**args)
2362 continue;
2363
Willy Tarreau540abe42007-05-02 20:50:16 +02002364 /* zero out remaining args and ensure that at least one entry
2365 * is zeroed out.
2366 */
2367 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 args[arg] = line;
2369 }
2370
Willy Tarreau977b8e42006-12-29 14:19:17 +01002371 if (!strcmp(args[0], "listen") ||
2372 !strcmp(args[0], "frontend") ||
2373 !strcmp(args[0], "backend") ||
2374 !strcmp(args[0], "ruleset") ||
2375 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 confsect = CFG_LISTEN;
2377 else if (!strcmp(args[0], "global")) /* global config */
2378 confsect = CFG_GLOBAL;
2379 /* else it's a section keyword */
2380
2381 switch (confsect) {
2382 case CFG_LISTEN:
2383 if (cfg_parse_listen(file, linenum, args) < 0)
2384 return -1;
2385 break;
2386 case CFG_GLOBAL:
2387 if (cfg_parse_global(file, linenum, args) < 0)
2388 return -1;
2389 break;
2390 default:
2391 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2392 return -1;
2393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002394 }
2395 fclose(f);
2396
2397 /*
2398 * Now, check for the integrity of all that we have collected.
2399 */
2400
2401 /* will be needed further to delay some tasks */
2402 tv_now(&now);
2403
2404 if ((curproxy = proxy) == NULL) {
2405 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2406 file);
2407 return -1;
2408 }
2409
2410 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002411 struct switching_rule *rule;
2412
Willy Tarreaubaaee002006-06-26 02:48:02 +02002413 if (curproxy->state == PR_STSTOPPED) {
2414 curproxy = curproxy->next;
2415 continue;
2416 }
2417
Willy Tarreau977b8e42006-12-29 14:19:17 +01002418 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2419 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 +01002420 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 cfgerr++;
2422 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002423 else if (curproxy->cap & PR_CAP_BE &&
2424 ((curproxy->mode != PR_MODE_HEALTH) &&
2425 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
2426 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2427 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 +01002428 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 cfgerr++;
2430 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002431
2432 if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002434 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002435 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002436 cfgerr++;
2437 }
2438#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2439 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002440 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002441 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 cfgerr++;
2443 }
2444#endif
2445 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002446 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002447 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 }
2449 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002450
2451 if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002453 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002454 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002456 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002457 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002458 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002459 }
2460 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002461 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002462 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002464 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002465 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002466 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002467 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002468 if (curproxy->options & PR_O_BALANCE_UH) {
2469 curproxy->options &= ~PR_O_BALANCE;
2470 curproxy->options |= PR_O_BALANCE_RR;
2471
2472 Warning("parsing %s : URI hash will be ignored for %s '%s'. Falling back to round robin.\n",
2473 file, proxy_type_str(curproxy), curproxy->id);
2474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 }
Willy Tarreau193cf932007-09-17 10:17:23 +02002476
2477 if (curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2478 if ((newsrv = curproxy->srv) != NULL) {
2479 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
2480 file, proxy_type_str(curproxy), curproxy->id);
2481 }
2482 }
2483
2484 if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2486 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2487 file, curproxy->id);
2488 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002489 }
2490 }
2491
2492 /* if a default backend was specified, let's find it */
2493 if (curproxy->defbe.name) {
2494 struct proxy *target;
2495
2496 for (target = proxy; target != NULL; target = target->next) {
2497 if (strcmp(target->id, curproxy->defbe.name) == 0)
2498 break;
2499 }
2500 if (target == NULL) {
2501 Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n",
2502 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2503 cfgerr++;
2504 } else if (target == curproxy) {
2505 Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
2506 cfgerr++;
2507 } else if (!(target->cap & PR_CAP_BE)) {
2508 Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n",
2509 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2510 cfgerr++;
2511 } else if (target->mode != curproxy->mode) {
2512 Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
2513 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2514 cfgerr++;
2515 } else {
2516 free(curproxy->defbe.name);
2517 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002518 }
2519 }
2520
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002521 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002522 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2523 /* map jump target for ACT_SETBE in req_rep chain */
2524 struct hdr_exp *exp;
2525 struct proxy *target;
2526 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
2527 if (exp->action != ACT_SETBE)
2528 continue;
2529 for (target = proxy; target != NULL; target = target->next) {
2530 if (strcmp(target->id, exp->replace) == 0)
2531 break;
2532 }
2533 if (target == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002534 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002535 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaua496b602006-12-17 23:15:24 +01002536 cfgerr++;
2537 } else if (target == curproxy) {
2538 Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
2539 cfgerr++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002540 } else if (!(target->cap & PR_CAP_BE)) {
2541 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002542 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002543 cfgerr++;
2544 } else if (target->mode != PR_MODE_HTTP) {
2545 Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002546 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002547 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002548 } else {
2549 free((void *)exp->replace);
2550 exp->replace = (const char *)target;
2551 }
2552 }
2553 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002554
2555 /* find the target proxy for 'use_backend' rules */
2556 list_for_each_entry(rule, &curproxy->switching_rules, list) {
2557 /* map jump target for ACT_SETBE in req_rep chain */
2558 struct proxy *target;
2559
2560 for (target = proxy; target != NULL; target = target->next) {
2561 if (strcmp(target->id, rule->be.name) == 0)
2562 break;
2563 }
2564
2565 if (target == NULL) {
2566 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
2567 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2568 cfgerr++;
2569 } else if (target == curproxy) {
2570 Alert("parsing %s : loop detected for backend %s !\n", file, rule->be.name);
2571 cfgerr++;
2572 } else if (!(target->cap & PR_CAP_BE)) {
2573 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
2574 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2575 cfgerr++;
2576 } else if (target->mode != curproxy->mode) {
2577 Alert("parsing %s : backend '%s' referenced in %s '%s' is of different mode !\n",
2578 file, rule->be.name, proxy_type_str(curproxy), curproxy->id);
2579 cfgerr++;
2580 } else {
2581 free((void *)rule->be.name);
2582 rule->be.backend = target;
2583 }
2584 }
2585
Willy Tarreau2738a142006-07-08 17:28:09 +02002586 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002587 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2588 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2589 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002590 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002591 " | While not properly invalid, you will certainly encounter various problems\n"
2592 " | with such a configuration. To fix this, please ensure that all following\n"
2593 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002594 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002595 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002596
2597 if (curproxy->options & PR_O_SSL3_CHK) {
2598 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2599 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2600 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2601 }
2602
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002603 /* The small pools required for the capture lists */
2604 if (curproxy->nb_req_cap)
2605 curproxy->req_cap_pool = create_pool("ptrcap",
2606 curproxy->nb_req_cap * sizeof(char *),
2607 MEM_F_SHARED);
2608 if (curproxy->nb_rsp_cap)
2609 curproxy->rsp_cap_pool = create_pool("ptrcap",
2610 curproxy->nb_rsp_cap * sizeof(char *),
2611 MEM_F_SHARED);
2612
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002613 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2614 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2615 MEM_F_SHARED);
2616
Willy Tarreau86034312006-12-29 00:10:33 +01002617 /* for backwards compatibility with "listen" instances, if
2618 * fullconn is not set but maxconn is set, then maxconn
2619 * is used.
2620 */
2621 if (!curproxy->fullconn)
2622 curproxy->fullconn = curproxy->maxconn;
2623
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 /* first, we will invert the servers list order */
2625 newsrv = NULL;
2626 while (curproxy->srv) {
2627 struct server *next;
2628
2629 next = curproxy->srv->next;
2630 curproxy->srv->next = newsrv;
2631 newsrv = curproxy->srv;
2632 if (!next)
2633 break;
2634 curproxy->srv = next;
2635 }
2636
2637 /* now, newsrv == curproxy->srv */
2638 if (newsrv) {
2639 struct server *srv;
2640 int pgcd;
2641 int act, bck;
2642
2643 /* We will factor the weights to reduce the table,
2644 * using Euclide's largest common divisor algorithm
2645 */
Willy Tarreau417fae02007-03-25 21:16:40 +02002646 pgcd = newsrv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2648 int t, w;
2649
Willy Tarreau417fae02007-03-25 21:16:40 +02002650 w = srv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651 while (w) {
2652 t = pgcd % w;
2653 pgcd = w;
2654 w = t;
2655 }
2656 }
2657
2658 act = bck = 0;
2659 for (srv = newsrv; srv; srv = srv->next) {
Willy Tarreau417fae02007-03-25 21:16:40 +02002660 srv->eweight = srv->uweight / pgcd;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002661 if (srv->state & SRV_BACKUP)
Willy Tarreau417fae02007-03-25 21:16:40 +02002662 bck += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002663 else
Willy Tarreau417fae02007-03-25 21:16:40 +02002664 act += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002665 }
2666
2667 /* this is the largest map we will ever need for this servers list */
2668 if (act < bck)
2669 act = bck;
2670
2671 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2672 /* recounts servers and their weights */
Willy Tarreau5af3a692007-07-24 23:32:33 +02002673 curproxy->map_state = PR_MAP_RECALC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002674 recount_servers(curproxy);
2675 recalc_server_map(curproxy);
2676 }
2677
2678 if (curproxy->options & PR_O_LOGASAP)
2679 curproxy->to_log &= ~LW_BYTES;
2680
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681 /*
2682 * If this server supports a maxconn parameter, it needs a dedicated
2683 * tasks to fill the emptied slots when a connection leaves.
2684 */
2685 newsrv = curproxy->srv;
2686 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002687 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002688 /* Only 'minconn' was specified, or it was higher than or equal
2689 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2690 * this will avoid further useless expensive computations.
2691 */
2692 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002693 } else if (newsrv->maxconn && !newsrv->minconn) {
2694 /* minconn was not specified, so we set it to maxconn */
2695 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002696 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2697 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002698 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002699 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 }
2701
2702 if (newsrv->maxconn > 0) {
2703 struct task *t;
2704
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002705 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002706 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2707 return -1;
2708 }
2709
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002710 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002711 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 t->state = TASK_IDLE;
2713 t->process = process_srv_queue;
2714 t->context = newsrv;
2715 newsrv->queue_mgt = t;
2716
2717 /* never run it unless specifically woken up */
2718 tv_eternity(&t->expire);
2719 task_queue(t);
2720 }
2721 newsrv = newsrv->next;
2722 }
2723
Willy Tarreaubaaee002006-06-26 02:48:02 +02002724 curproxy = curproxy->next;
2725 }
2726 if (cfgerr > 0) {
2727 Alert("Errors found in configuration file, aborting.\n");
2728 return -1;
2729 }
2730 else
2731 return 0;
2732}
2733
2734
2735
2736/*
2737 * Local variables:
2738 * c-indent-level: 8
2739 * c-basic-offset: 8
2740 * End:
2741 */