blob: ae5433ea4247709fb30f702fa2cf374b1ddd123f [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
4 * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
5 *
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>
18
Willy Tarreau2dd0d472006-06-29 17:53:05 +020019#include <common/cfgparse.h>
20#include <common/config.h>
21#include <common/memory.h>
22#include <common/standard.h>
23#include <common/time.h>
24#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
26#include <types/capture.h>
27#include <types/global.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010028#include <types/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020029#include <types/polling.h>
30#include <types/proxy.h>
31#include <types/queue.h>
32
33#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010034#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035#include <proto/checks.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010036#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <proto/log.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010038#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039#include <proto/server.h>
40#include <proto/task.h>
41
42
Willy Tarreauf3c69202006-07-09 16:42:34 +020043/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
44 * ssl-hello-chk option to ensure that the remote server speaks SSL.
45 *
46 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
47 */
48const char sslv3_client_hello_pkt[] = {
49 "\x16" /* ContentType : 0x16 = Hanshake */
50 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
51 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
52 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
53 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
54 "\x03\x00" /* Hello Version : 0x0300 = v3 */
55 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
56 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
57 "\x00" /* Session ID length : empty (no session ID) */
58 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
59 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
60 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
61 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
62 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
63 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
64 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
65 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
66 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
67 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
68 "\x00\x38" "\x00\x39" "\x00\x3A"
69 "\x01" /* Compression Length : 0x01 = 1 byte for types */
70 "\x00" /* Compression Type : 0x00 = NULL compression */
71};
72
Willy Tarreau13943ab2006-12-31 00:24:10 +010073/* some of the most common options which are also the easiest to handle */
74static const struct {
75 const char *name;
76 unsigned int val;
77 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010078 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010079} cfg_opts[] =
80{
81#ifdef TPROXY
82 { "transparent", PR_O_TRANSP, PR_CAP_FE },
83#endif
Willy Tarreau4fee4e92007-01-06 21:09:17 +010084 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
85 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
86 { "forwardfor", PR_O_FWDFOR, PR_CAP_FE | PR_CAP_BE, 0 },
87 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
88 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
89 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
90 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
91 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
92 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
93 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
94 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
95 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
96 { "forceclose", PR_O_FORCE_CLO | PR_O_HTTP_CLOSE, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +010097#ifdef CONFIG_HAP_TCPSPLICE
98 { "tcpsplice", PR_O_TCPSPLICE , PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
99#endif
100
Willy Tarreau13943ab2006-12-31 00:24:10 +0100101 { NULL, 0, 0 }
102};
103
Willy Tarreaubaaee002006-06-26 02:48:02 +0200104
105static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
106int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
107int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
108
109/*
110 * converts <str> to a list of listeners which are dynamically allocated.
111 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
112 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
113 * - <port> is a numerical port from 1 to 65535 ;
114 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
115 * This can be repeated as many times as necessary, separated by a coma.
116 * The <tail> argument is a pointer to a current list which should be appended
117 * to the tail of the new list. The pointer to the new list is returned.
118 */
119static struct listener *str2listener(char *str, struct listener *tail)
120{
121 struct listener *l;
122 char *c, *next, *range, *dupstr;
123 int port, end;
124
125 next = dupstr = strdup(str);
126
127 while (next && *next) {
128 struct sockaddr_storage ss;
129
130 str = next;
131 /* 1) look for the end of the first address */
132 if ((next = strrchr(str, ',')) != NULL) {
133 *next++ = 0;
134 }
135
136 /* 2) look for the addr/port delimiter, it's the last colon. */
137 if ((range = strrchr(str, ':')) == NULL) {
138 Alert("Missing port number: '%s'\n", str);
139 goto fail;
140 }
141
142 *range++ = 0;
143
144 if (strrchr(str, ':') != NULL) {
145 /* IPv6 address contains ':' */
146 memset(&ss, 0, sizeof(ss));
147 ss.ss_family = AF_INET6;
148
149 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
150 Alert("Invalid server address: '%s'\n", str);
151 goto fail;
152 }
153 }
154 else {
155 memset(&ss, 0, sizeof(ss));
156 ss.ss_family = AF_INET;
157
158 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
159 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
160 }
161 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
162 struct hostent *he;
163
164 if ((he = gethostbyname(str)) == NULL) {
165 Alert("Invalid server name: '%s'\n", str);
166 goto fail;
167 }
168 else
169 ((struct sockaddr_in *)&ss)->sin_addr =
170 *(struct in_addr *) *(he->h_addr_list);
171 }
172 }
173
174 /* 3) look for the port-end delimiter */
175 if ((c = strchr(range, '-')) != NULL) {
176 *c++ = 0;
177 end = atol(c);
178 }
179 else {
180 end = atol(range);
181 }
182
183 port = atol(range);
184
185 if (port < 1 || port > 65535) {
186 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
187 goto fail;
188 }
189
190 if (end < 1 || end > 65535) {
191 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
192 goto fail;
193 }
194
195 for (; port <= end; port++) {
196 l = (struct listener *)calloc(1, sizeof(struct listener));
197 l->next = tail;
198 tail = l;
199
200 l->fd = -1;
201 l->addr = ss;
202 if (ss.ss_family == AF_INET6)
203 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
204 else
205 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
206
207 } /* end for(port) */
208 } /* end while(next) */
209 free(dupstr);
210 return tail;
211 fail:
212 free(dupstr);
213 return NULL;
214}
215
Willy Tarreau977b8e42006-12-29 14:19:17 +0100216/*
217 * Sends a warning if proxy <proxy> does not have at least one of the
218 * capabilities in <cap>. An optionnal <hint> may be added at the end
219 * of the warning to help the user. Returns 1 if a warning was emitted
220 * or 0 if the condition is valid.
221 */
222int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
223{
224 char *msg;
225
226 switch (cap) {
227 case PR_CAP_BE: msg = "no backend"; break;
228 case PR_CAP_FE: msg = "no frontend"; break;
229 case PR_CAP_RS: msg = "no ruleset"; break;
230 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
231 default: msg = "not enough"; break;
232 }
233
234 if (!(proxy->cap & cap)) {
235 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100236 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100237 return 1;
238 }
239 return 0;
240}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
242/*
243 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
244 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200245int cfg_parse_global(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246{
247
248 if (!strcmp(args[0], "global")) { /* new section */
249 /* no option, nothing special to do */
250 return 0;
251 }
252 else if (!strcmp(args[0], "daemon")) {
253 global.mode |= MODE_DAEMON;
254 }
255 else if (!strcmp(args[0], "debug")) {
256 global.mode |= MODE_DEBUG;
257 }
258 else if (!strcmp(args[0], "noepoll")) {
259 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
260 }
261 else if (!strcmp(args[0], "nopoll")) {
262 cfg_polling_mechanism &= ~POLL_USE_POLL;
263 }
264 else if (!strcmp(args[0], "quiet")) {
265 global.mode |= MODE_QUIET;
266 }
267 else if (!strcmp(args[0], "stats")) {
268 global.mode |= MODE_STATS;
269 }
270 else if (!strcmp(args[0], "uid")) {
271 if (global.uid != 0) {
272 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
273 return 0;
274 }
275 if (*(args[1]) == 0) {
276 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
277 return -1;
278 }
279 global.uid = atol(args[1]);
280 }
281 else if (!strcmp(args[0], "gid")) {
282 if (global.gid != 0) {
283 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
284 return 0;
285 }
286 if (*(args[1]) == 0) {
287 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
288 return -1;
289 }
290 global.gid = atol(args[1]);
291 }
292 else if (!strcmp(args[0], "nbproc")) {
293 if (global.nbproc != 0) {
294 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
295 return 0;
296 }
297 if (*(args[1]) == 0) {
298 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
299 return -1;
300 }
301 global.nbproc = atol(args[1]);
302 }
303 else if (!strcmp(args[0], "maxconn")) {
304 if (global.maxconn != 0) {
305 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
306 return 0;
307 }
308 if (*(args[1]) == 0) {
309 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
310 return -1;
311 }
312 global.maxconn = atol(args[1]);
313#ifdef SYSTEM_MAXCONN
314 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
315 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);
316 global.maxconn = DEFAULT_MAXCONN;
317 }
318#endif /* SYSTEM_MAXCONN */
319 }
320 else if (!strcmp(args[0], "ulimit-n")) {
321 if (global.rlimit_nofile != 0) {
322 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
323 return 0;
324 }
325 if (*(args[1]) == 0) {
326 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
327 return -1;
328 }
329 global.rlimit_nofile = atol(args[1]);
330 }
331 else if (!strcmp(args[0], "chroot")) {
332 if (global.chroot != NULL) {
333 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
334 return 0;
335 }
336 if (*(args[1]) == 0) {
337 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
338 return -1;
339 }
340 global.chroot = strdup(args[1]);
341 }
342 else if (!strcmp(args[0], "pidfile")) {
343 if (global.pidfile != NULL) {
344 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
345 return 0;
346 }
347 if (*(args[1]) == 0) {
348 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
349 return -1;
350 }
351 global.pidfile = strdup(args[1]);
352 }
353 else if (!strcmp(args[0], "log")) { /* syslog server address */
354 struct sockaddr_in *sa;
355 int facility, level;
356
357 if (*(args[1]) == 0 || *(args[2]) == 0) {
358 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
359 return -1;
360 }
361
362 facility = get_log_facility(args[2]);
363 if (facility < 0) {
364 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
365 exit(1);
366 }
367
368 level = 7; /* max syslog level = debug */
369 if (*(args[3])) {
370 level = get_log_level(args[3]);
371 if (level < 0) {
372 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
373 exit(1);
374 }
375 }
376
377 sa = str2sa(args[1]);
378 if (!sa->sin_port)
379 sa->sin_port = htons(SYSLOG_PORT);
380
381 if (global.logfac1 == -1) {
382 global.logsrv1 = *sa;
383 global.logfac1 = facility;
384 global.loglev1 = level;
385 }
386 else if (global.logfac2 == -1) {
387 global.logsrv2 = *sa;
388 global.logfac2 = facility;
389 global.loglev2 = level;
390 }
391 else {
392 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
393 return -1;
394 }
395
396 }
397 else {
398 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
399 return -1;
400 }
401 return 0;
402}
403
404
405static void init_default_instance()
406{
407 memset(&defproxy, 0, sizeof(defproxy));
408 defproxy.mode = PR_MODE_TCP;
409 defproxy.state = PR_STNEW;
410 defproxy.maxconn = cfg_maxpconn;
411 defproxy.conn_retries = CONN_RETRIES;
412 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
413}
414
415/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100416 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
417 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200418 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200419int cfg_parse_listen(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200420{
421 static struct proxy *curproxy = NULL;
422 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200423 const char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200424 int rc;
425
Willy Tarreau977b8e42006-12-29 14:19:17 +0100426 if (!strcmp(args[0], "listen"))
427 rc = PR_CAP_LISTEN;
428 else if (!strcmp(args[0], "frontend"))
429 rc = PR_CAP_FE | PR_CAP_RS;
430 else if (!strcmp(args[0], "backend"))
431 rc = PR_CAP_BE | PR_CAP_RS;
432 else if (!strcmp(args[0], "ruleset"))
433 rc = PR_CAP_RS;
434 else
435 rc = PR_CAP_NONE;
436
437 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200438 if (!*args[1]) {
439 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
440 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
441 file, linenum, args[0]);
442 return -1;
443 }
444
445 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
446 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
447 return -1;
448 }
449
450 curproxy->next = proxy;
451 proxy = curproxy;
452 LIST_INIT(&curproxy->pendconns);
453
454 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100455 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200456
457 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100458 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200459 curproxy->listen = str2listener(args[2], curproxy->listen);
460 if (!curproxy->listen)
461 return -1;
462 global.maxsock++;
463 }
464
465 /* set default values */
466 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467 curproxy->options = defproxy.options;
468
Willy Tarreau977b8e42006-12-29 14:19:17 +0100469 if (curproxy->cap & PR_CAP_FE) {
470 curproxy->maxconn = defproxy.maxconn;
471
472 /* initialize error relocations */
473 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
474 if (defproxy.errmsg[rc].str)
475 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
476 }
477
478 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200480
Willy Tarreau977b8e42006-12-29 14:19:17 +0100481 if (curproxy->cap & PR_CAP_BE) {
482 curproxy->fullconn = defproxy.fullconn;
483 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200484
Willy Tarreau977b8e42006-12-29 14:19:17 +0100485 if (defproxy.check_req)
486 curproxy->check_req = strdup(defproxy.check_req);
487 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200488
Willy Tarreau977b8e42006-12-29 14:19:17 +0100489 if (defproxy.cookie_name)
490 curproxy->cookie_name = strdup(defproxy.cookie_name);
491 curproxy->cookie_len = defproxy.cookie_len;
492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200493
Willy Tarreau977b8e42006-12-29 14:19:17 +0100494 if (curproxy->cap & PR_CAP_RS) {
495 if (defproxy.capture_name)
496 curproxy->capture_name = strdup(defproxy.capture_name);
497 curproxy->capture_namelen = defproxy.capture_namelen;
498 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100499 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200500
Willy Tarreau977b8e42006-12-29 14:19:17 +0100501 if (curproxy->cap & PR_CAP_FE) {
502 curproxy->clitimeout = defproxy.clitimeout;
503 curproxy->uri_auth = defproxy.uri_auth;
504 curproxy->mon_net = defproxy.mon_net;
505 curproxy->mon_mask = defproxy.mon_mask;
506 if (defproxy.monitor_uri)
507 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
508 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100509 if (defproxy.defbe.name)
510 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100511 }
512
513 if (curproxy->cap & PR_CAP_BE) {
514 curproxy->contimeout = defproxy.contimeout;
515 curproxy->srvtimeout = defproxy.srvtimeout;
516 curproxy->source_addr = defproxy.source_addr;
517 }
518
Willy Tarreaubaaee002006-06-26 02:48:02 +0200519 curproxy->mode = defproxy.mode;
520 curproxy->logfac1 = defproxy.logfac1;
521 curproxy->logsrv1 = defproxy.logsrv1;
522 curproxy->loglev1 = defproxy.loglev1;
523 curproxy->logfac2 = defproxy.logfac2;
524 curproxy->logsrv2 = defproxy.logsrv2;
525 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200526 curproxy->grace = defproxy.grace;
Willy Tarreau1c47f852006-07-09 08:22:27 +0200527
Willy Tarreaubaaee002006-06-26 02:48:02 +0200528 return 0;
529 }
530 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
531 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100532 /* FIXME-20070101: we should do this too at the end of the
533 * config parsing to free all default values.
534 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200535 if (defproxy.check_req) free(defproxy.check_req);
536 if (defproxy.cookie_name) free(defproxy.cookie_name);
537 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200538 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100539 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100540
541 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
542 if (defproxy.errmsg[rc].len)
543 free(defproxy.errmsg[rc].str);
544 }
545
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 /* we cannot free uri_auth because it might already be used */
547 init_default_instance();
548 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100549 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200550 return 0;
551 }
552 else if (curproxy == NULL) {
553 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
554 return -1;
555 }
556
Willy Tarreau977b8e42006-12-29 14:19:17 +0100557
558 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200559 if (!strcmp(args[0], "bind")) { /* new listen addresses */
560 if (curproxy == &defproxy) {
561 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
562 return -1;
563 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100564 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
565 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566
567 if (strchr(args[1], ':') == NULL) {
568 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
569 file, linenum, args[0]);
570 return -1;
571 }
572 curproxy->listen = str2listener(args[1], curproxy->listen);
573 if (!curproxy->listen)
574 return -1;
575 global.maxsock++;
576 return 0;
577 }
578 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
579 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
580 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
581 file, linenum, args[0]);
582 return -1;
583 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100584 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
585 return 0;
586
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 /* flush useless bits */
588 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
589 return 0;
590 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200591 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100592 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
593 return 0;
594
Willy Tarreau1c47f852006-07-09 08:22:27 +0200595 if (!*args[1]) {
596 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
597 file, linenum, args[0]);
598 return -1;
599 }
600
601 if (curproxy->monitor_uri != NULL)
602 free(curproxy->monitor_uri);
603
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100604 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200605 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100606 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200607 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
608
609 return 0;
610 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
612 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
613 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
614 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
615 else {
616 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
617 return -1;
618 }
619 }
620 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
621 curproxy->state = PR_STSTOPPED;
622 }
623 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
624 curproxy->state = PR_STNEW;
625 }
626 else if (!strcmp(args[0], "cookie")) { /* cookie name */
627 int cur_arg;
628 // if (curproxy == &defproxy) {
629 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
630 // return -1;
631 // }
632
Willy Tarreau977b8e42006-12-29 14:19:17 +0100633 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
634 return 0;
635
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 if (curproxy->cookie_name != NULL) {
637 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
638 // file, linenum);
639 // return 0;
640 free(curproxy->cookie_name);
641 }
642
643 if (*(args[1]) == 0) {
644 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
645 file, linenum, args[0]);
646 return -1;
647 }
648 curproxy->cookie_name = strdup(args[1]);
649 curproxy->cookie_len = strlen(curproxy->cookie_name);
650
651 cur_arg = 2;
652 while (*(args[cur_arg])) {
653 if (!strcmp(args[cur_arg], "rewrite")) {
654 curproxy->options |= PR_O_COOK_RW;
655 }
656 else if (!strcmp(args[cur_arg], "indirect")) {
657 curproxy->options |= PR_O_COOK_IND;
658 }
659 else if (!strcmp(args[cur_arg], "insert")) {
660 curproxy->options |= PR_O_COOK_INS;
661 }
662 else if (!strcmp(args[cur_arg], "nocache")) {
663 curproxy->options |= PR_O_COOK_NOC;
664 }
665 else if (!strcmp(args[cur_arg], "postonly")) {
666 curproxy->options |= PR_O_COOK_POST;
667 }
668 else if (!strcmp(args[cur_arg], "prefix")) {
669 curproxy->options |= PR_O_COOK_PFX;
670 }
671 else {
672 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
673 file, linenum, args[0]);
674 return -1;
675 }
676 cur_arg++;
677 }
678 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
679 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
680 file, linenum);
681 return -1;
682 }
683
684 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
685 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
686 file, linenum);
687 return -1;
688 }
689 }/* end else if (!strcmp(args[0], "cookie")) */
690 else if (!strcmp(args[0], "appsession")) { /* cookie name */
691 // if (curproxy == &defproxy) {
692 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
693 // return -1;
694 // }
695
Willy Tarreau977b8e42006-12-29 14:19:17 +0100696 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
697 return 0;
698
Willy Tarreaubaaee002006-06-26 02:48:02 +0200699 if (curproxy->appsession_name != NULL) {
700 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
701 // file, linenum);
702 // return 0;
703 free(curproxy->appsession_name);
704 }
705
706 if (*(args[5]) == 0) {
707 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
708 file, linenum, args[0]);
709 return -1;
710 }
711 have_appsession = 1;
712 curproxy->appsession_name = strdup(args[1]);
713 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
714 curproxy->appsession_len = atoi(args[3]);
715 curproxy->appsession_timeout = atoi(args[5]);
716 rc = chtbl_init(&(curproxy->htbl_proxy), TBLSIZ, hashpjw, match_str, destroy);
717 if (rc) {
718 Alert("Error Init Appsession Hashtable.\n");
719 return -1;
720 }
721 } /* Url App Session */
722 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100723 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
724 return 0;
725
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
727 // if (curproxy == &defproxy) {
728 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
729 // return -1;
730 // }
731
732 if (curproxy->capture_name != NULL) {
733 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
734 // file, linenum, args[0]);
735 // return 0;
736 free(curproxy->capture_name);
737 }
738
739 if (*(args[4]) == 0) {
740 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
741 file, linenum, args[0]);
742 return -1;
743 }
744 curproxy->capture_name = strdup(args[2]);
745 curproxy->capture_namelen = strlen(curproxy->capture_name);
746 curproxy->capture_len = atol(args[4]);
747 if (curproxy->capture_len >= CAPTURE_LEN) {
748 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
749 file, linenum, CAPTURE_LEN - 1);
750 curproxy->capture_len = CAPTURE_LEN - 1;
751 }
752 curproxy->to_log |= LW_COOKIE;
753 }
754 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
755 struct cap_hdr *hdr;
756
757 if (curproxy == &defproxy) {
758 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
759 return -1;
760 }
761
762 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
763 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
764 file, linenum, args[0], args[1]);
765 return -1;
766 }
767
768 hdr = calloc(sizeof(struct cap_hdr), 1);
769 hdr->next = curproxy->req_cap;
770 hdr->name = strdup(args[3]);
771 hdr->namelen = strlen(args[3]);
772 hdr->len = atol(args[5]);
773 hdr->index = curproxy->nb_req_cap++;
774 curproxy->req_cap = hdr;
775 curproxy->to_log |= LW_REQHDR;
776 }
777 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
778 struct cap_hdr *hdr;
779
780 if (curproxy == &defproxy) {
781 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
782 return -1;
783 }
784
785 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
786 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
787 file, linenum, args[0], args[1]);
788 return -1;
789 }
790 hdr = calloc(sizeof(struct cap_hdr), 1);
791 hdr->next = curproxy->rsp_cap;
792 hdr->name = strdup(args[3]);
793 hdr->namelen = strlen(args[3]);
794 hdr->len = atol(args[5]);
795 hdr->index = curproxy->nb_rsp_cap++;
796 curproxy->rsp_cap = hdr;
797 curproxy->to_log |= LW_RSPHDR;
798 }
799 else {
800 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
801 file, linenum, args[0]);
802 return -1;
803 }
804 }
805 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
806 if (curproxy->contimeout != defproxy.contimeout) {
807 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
808 return 0;
809 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100810 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
811 return 0;
812
Willy Tarreaubaaee002006-06-26 02:48:02 +0200813 if (*(args[1]) == 0) {
814 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
815 file, linenum, args[0]);
816 return -1;
817 }
818 curproxy->contimeout = atol(args[1]);
819 }
820 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
821 if (curproxy->clitimeout != defproxy.clitimeout) {
822 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
823 file, linenum, args[0]);
824 return 0;
825 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100826 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
827 return 0;
828
Willy Tarreaubaaee002006-06-26 02:48:02 +0200829 if (*(args[1]) == 0) {
830 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
831 file, linenum, args[0]);
832 return -1;
833 }
834 curproxy->clitimeout = atol(args[1]);
835 }
836 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
837 if (curproxy->srvtimeout != defproxy.srvtimeout) {
838 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
839 return 0;
840 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100841 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
842 return 0;
843
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
846 file, linenum, args[0]);
847 return -1;
848 }
849 curproxy->srvtimeout = atol(args[1]);
850 }
851 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100852 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
853 return 0;
854
Willy Tarreaubaaee002006-06-26 02:48:02 +0200855 if (*(args[1]) == 0) {
856 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
857 file, linenum, args[0]);
858 return -1;
859 }
860 curproxy->conn_retries = atol(args[1]);
861 }
862 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100863 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
864 return 0;
865
Willy Tarreaubaaee002006-06-26 02:48:02 +0200866 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
867 curproxy->uri_auth = NULL; /* we must detach from the default config */
868
869 if (*(args[1]) == 0) {
870 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
871 return -1;
872 } else if (!strcmp(args[1], "uri")) {
873 if (*(args[2]) == 0) {
874 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
875 return -1;
876 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
877 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
878 return -1;
879 }
880 } else if (!strcmp(args[1], "realm")) {
881 if (*(args[2]) == 0) {
882 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
883 return -1;
884 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
885 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
886 return -1;
887 }
888 } else if (!strcmp(args[1], "auth")) {
889 if (*(args[2]) == 0) {
890 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
891 return -1;
892 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
893 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
894 return -1;
895 }
896 } else if (!strcmp(args[1], "scope")) {
897 if (*(args[2]) == 0) {
898 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
899 return -1;
900 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
901 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
902 return -1;
903 }
904 } else if (!strcmp(args[1], "enable")) {
905 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
906 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
907 return -1;
908 }
909 } else {
910 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'uri', 'realm', 'auth' or 'enable').\n",
911 file, linenum, args[0]);
912 return -1;
913 }
914 }
915 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100916 int optnum;
917
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 if (*(args[1]) == 0) {
919 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
920 return -1;
921 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100922
923 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
924 if (!strcmp(args[1], cfg_opts[optnum].name)) {
925 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
926 return 0;
927 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100928 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +0100929 return 0;
930 }
931 }
932
933 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934 /* generate a complete HTTP log */
935 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
936 else if (!strcmp(args[1], "tcplog"))
937 /* generate a detailed TCP log */
938 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200939 else if (!strcmp(args[1], "tcpka")) {
940 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +0100941 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
942 return 0;
943
944 if (curproxy->cap & PR_CAP_FE)
945 curproxy->options |= PR_O_TCP_CLI_KA;
946 if (curproxy->cap & PR_CAP_BE)
947 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 }
949 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100950 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
951 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 /* use HTTP request to check servers' health */
953 if (curproxy->check_req != NULL) {
954 free(curproxy->check_req);
955 }
956 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +0200957 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958 if (!*args[2]) { /* no argument */
959 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
960 curproxy->check_len = strlen(DEF_CHECK_REQ);
961 } else if (!*args[3]) { /* one argument : URI */
962 int reqlen = strlen(args[2]) + strlen("OPTIONS / HTTP/1.0\r\n\r\n");
963 curproxy->check_req = (char *)malloc(reqlen);
964 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
965 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
966 } else { /* more arguments : METHOD URI [HTTP_VER] */
967 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
968 if (*args[4])
969 reqlen += strlen(args[4]);
970 else
971 reqlen += strlen("HTTP/1.0");
972
973 curproxy->check_req = (char *)malloc(reqlen);
974 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
975 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
976 }
Willy Tarreauf3c69202006-07-09 16:42:34 +0200977 }
978 else if (!strcmp(args[1], "ssl-hello-chk")) {
979 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +0100980 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
981 return 0;
982
Willy Tarreauf3c69202006-07-09 16:42:34 +0200983 if (curproxy->check_req != NULL) {
984 free(curproxy->check_req);
985 }
986 curproxy->options &= ~PR_O_HTTP_CHK;
987 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200989 else {
990 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
991 return -1;
992 }
993 return 0;
994 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100995 else if (!strcmp(args[0], "default_backend")) {
996 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
997 return 0;
998
999 if (*(args[1]) == 0) {
1000 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1001 return -1;
1002 }
1003 if (curproxy->defbe.name)
1004 free(curproxy->defbe.name);
1005 curproxy->defbe.name = strdup(args[1]);
1006 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001007 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001008 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1009 return 0;
1010
Willy Tarreaubaaee002006-06-26 02:48:02 +02001011 /* enable reconnections to dispatch */
1012 curproxy->options |= PR_O_REDISP;
1013 }
1014#ifdef TPROXY
1015 else if (!strcmp(args[0], "transparent")) {
1016 /* enable transparent proxy connections */
1017 curproxy->options |= PR_O_TRANSP;
1018 }
1019#endif
1020 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001021 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1022 return 0;
1023
Willy Tarreaubaaee002006-06-26 02:48:02 +02001024 if (*(args[1]) == 0) {
1025 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1026 return -1;
1027 }
1028 curproxy->maxconn = atol(args[1]);
1029 }
Willy Tarreau86034312006-12-29 00:10:33 +01001030 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001031 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1032 return 0;
1033
Willy Tarreau86034312006-12-29 00:10:33 +01001034 if (*(args[1]) == 0) {
1035 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1036 return -1;
1037 }
1038 curproxy->fullconn = atol(args[1]);
1039 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001040 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1041 if (*(args[1]) == 0) {
1042 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1043 return -1;
1044 }
1045 curproxy->grace = atol(args[1]);
1046 }
1047 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1048 if (curproxy == &defproxy) {
1049 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1050 return -1;
1051 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001052 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1053 return 0;
1054
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 if (strchr(args[1], ':') == NULL) {
1056 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1057 return -1;
1058 }
1059 curproxy->dispatch_addr = *str2sa(args[1]);
1060 }
1061 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001062 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1063 return 0;
1064
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 if (*(args[1])) {
1066 if (!strcmp(args[1], "roundrobin")) {
1067 curproxy->options |= PR_O_BALANCE_RR;
1068 }
1069 else if (!strcmp(args[1], "source")) {
1070 curproxy->options |= PR_O_BALANCE_SH;
1071 }
1072 else {
1073 Alert("parsing [%s:%d] : '%s' only supports 'roundrobin' and 'source' options.\n", file, linenum, args[0]);
1074 return -1;
1075 }
1076 }
1077 else /* if no option is set, use round-robin by default */
1078 curproxy->options |= PR_O_BALANCE_RR;
1079 }
1080 else if (!strcmp(args[0], "server")) { /* server address */
1081 int cur_arg;
1082 char *rport;
1083 char *raddr;
1084 short realport;
1085 int do_check;
1086
1087 if (curproxy == &defproxy) {
1088 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1089 return -1;
1090 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001091 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1092 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001093
1094 if (!*args[2]) {
1095 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1096 file, linenum, args[0]);
1097 return -1;
1098 }
1099 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1100 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1101 return -1;
1102 }
1103
1104 /* the servers are linked backwards first */
1105 newsrv->next = curproxy->srv;
1106 curproxy->srv = newsrv;
1107 newsrv->proxy = curproxy;
1108
1109 LIST_INIT(&newsrv->pendconns);
1110 do_check = 0;
1111 newsrv->state = SRV_RUNNING; /* early server setup */
1112 newsrv->id = strdup(args[1]);
1113
1114 /* several ways to check the port component :
1115 * - IP => port=+0, relative
1116 * - IP: => port=+0, relative
1117 * - IP:N => port=N, absolute
1118 * - IP:+N => port=+N, relative
1119 * - IP:-N => port=-N, relative
1120 */
1121 raddr = strdup(args[2]);
1122 rport = strchr(raddr, ':');
1123 if (rport) {
1124 *rport++ = 0;
1125 realport = atol(rport);
1126 if (!isdigit((int)*rport))
1127 newsrv->state |= SRV_MAPPORTS;
1128 } else {
1129 realport = 0;
1130 newsrv->state |= SRV_MAPPORTS;
1131 }
1132
1133 newsrv->addr = *str2sa(raddr);
1134 newsrv->addr.sin_port = htons(realport);
1135 free(raddr);
1136
1137 newsrv->curfd = -1; /* no health-check in progress */
1138 newsrv->inter = DEF_CHKINTR;
1139 newsrv->rise = DEF_RISETIME;
1140 newsrv->fall = DEF_FALLTIME;
1141 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
1142 cur_arg = 3;
1143 while (*args[cur_arg]) {
1144 if (!strcmp(args[cur_arg], "cookie")) {
1145 newsrv->cookie = strdup(args[cur_arg + 1]);
1146 newsrv->cklen = strlen(args[cur_arg + 1]);
1147 cur_arg += 2;
1148 }
1149 else if (!strcmp(args[cur_arg], "rise")) {
1150 newsrv->rise = atol(args[cur_arg + 1]);
1151 newsrv->health = newsrv->rise;
1152 cur_arg += 2;
1153 }
1154 else if (!strcmp(args[cur_arg], "fall")) {
1155 newsrv->fall = atol(args[cur_arg + 1]);
1156 cur_arg += 2;
1157 }
1158 else if (!strcmp(args[cur_arg], "inter")) {
1159 newsrv->inter = atol(args[cur_arg + 1]);
1160 cur_arg += 2;
1161 }
1162 else if (!strcmp(args[cur_arg], "port")) {
1163 newsrv->check_port = atol(args[cur_arg + 1]);
1164 cur_arg += 2;
1165 }
1166 else if (!strcmp(args[cur_arg], "backup")) {
1167 newsrv->state |= SRV_BACKUP;
1168 cur_arg ++;
1169 }
1170 else if (!strcmp(args[cur_arg], "weight")) {
1171 int w;
1172 w = atol(args[cur_arg + 1]);
1173 if (w < 1 || w > 256) {
1174 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1175 file, linenum, newsrv->id, w);
1176 return -1;
1177 }
1178 newsrv->uweight = w - 1;
1179 cur_arg += 2;
1180 }
1181 else if (!strcmp(args[cur_arg], "minconn")) {
1182 newsrv->minconn = atol(args[cur_arg + 1]);
1183 cur_arg += 2;
1184 }
1185 else if (!strcmp(args[cur_arg], "maxconn")) {
1186 newsrv->maxconn = atol(args[cur_arg + 1]);
1187 cur_arg += 2;
1188 }
1189 else if (!strcmp(args[cur_arg], "check")) {
1190 global.maxsock++;
1191 do_check = 1;
1192 cur_arg += 1;
1193 }
1194 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1195 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001196#ifdef CONFIG_HAP_CTTPROXY
1197 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1198 file, linenum, "source", "usesrc");
1199#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001200 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1201 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001202#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 return -1;
1204 }
1205 newsrv->state |= SRV_BIND_SRC;
1206 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1207 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001208 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001209#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001210 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001211 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1212 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001213 return -1;
1214 }
1215 if (!*args[cur_arg + 1]) {
1216 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1217 file, linenum, "usesrc");
1218 return -1;
1219 }
1220 if (!strcmp(args[cur_arg + 1], "client")) {
1221 newsrv->state |= SRV_TPROXY_CLI;
1222 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1223 newsrv->state |= SRV_TPROXY_CIP;
1224 } else {
1225 newsrv->state |= SRV_TPROXY_ADDR;
1226 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1227 }
1228 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1229 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001230#else /* no CTTPROXY support */
1231 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1232 file, linenum, "usesrc");
1233 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001234#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001236 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001237#ifdef CONFIG_HAP_CTTPROXY
1238 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1239 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1240 file, linenum, "usesrc", "source");
1241 return -1;
1242 }
1243#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001244 else {
1245 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'port', 'source', 'minconn', 'maxconn' and 'weight'.\n",
1246 file, linenum, newsrv->id);
1247 return -1;
1248 }
1249 }
1250
1251 if (do_check) {
1252 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1253 newsrv->check_port = realport; /* by default */
1254 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001255 /* not yet valid, because no port was set on
1256 * the server either. We'll check if we have
1257 * a known port on the first listener.
1258 */
1259 struct listener *l;
1260 l = curproxy->listen;
1261 if (l) {
1262 int port;
1263 port = (l->addr.ss_family == AF_INET6)
1264 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1265 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1266 newsrv->check_port = port;
1267 }
1268 }
1269 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001270 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1271 file, linenum, newsrv->id);
1272 return -1;
1273 }
1274 newsrv->state |= SRV_CHECKED;
1275 }
1276
1277 if (newsrv->state & SRV_BACKUP)
1278 curproxy->srv_bck++;
1279 else
1280 curproxy->srv_act++;
1281 }
1282 else if (!strcmp(args[0], "log")) { /* syslog server address */
1283 struct sockaddr_in *sa;
1284 int facility;
1285
1286 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1287 curproxy->logfac1 = global.logfac1;
1288 curproxy->logsrv1 = global.logsrv1;
1289 curproxy->loglev1 = global.loglev1;
1290 curproxy->logfac2 = global.logfac2;
1291 curproxy->logsrv2 = global.logsrv2;
1292 curproxy->loglev2 = global.loglev2;
1293 }
1294 else if (*(args[1]) && *(args[2])) {
1295 int level;
1296
1297 facility = get_log_facility(args[2]);
1298 if (facility < 0) {
1299 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1300 exit(1);
1301 }
1302
1303 level = 7; /* max syslog level = debug */
1304 if (*(args[3])) {
1305 level = get_log_level(args[3]);
1306 if (level < 0) {
1307 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1308 exit(1);
1309 }
1310 }
1311
1312 sa = str2sa(args[1]);
1313 if (!sa->sin_port)
1314 sa->sin_port = htons(SYSLOG_PORT);
1315
1316 if (curproxy->logfac1 == -1) {
1317 curproxy->logsrv1 = *sa;
1318 curproxy->logfac1 = facility;
1319 curproxy->loglev1 = level;
1320 }
1321 else if (curproxy->logfac2 == -1) {
1322 curproxy->logsrv2 = *sa;
1323 curproxy->logfac2 = facility;
1324 curproxy->loglev2 = level;
1325 }
1326 else {
1327 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1328 return -1;
1329 }
1330 }
1331 else {
1332 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1333 file, linenum);
1334 return -1;
1335 }
1336 }
1337 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001338 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1339 return 0;
1340
Willy Tarreaubaaee002006-06-26 02:48:02 +02001341 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001342#ifdef CONFIG_HAP_CTTPROXY
1343 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1344 file, linenum, "source", "usesrc");
1345#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001346 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1347 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001348#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 return -1;
1350 }
1351
1352 curproxy->source_addr = *str2sa(args[1]);
1353 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001354 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001355#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001356 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1357 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1358 file, linenum, "usesrc");
1359 return -1;
1360 }
1361 if (!*args[3]) {
1362 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1363 file, linenum, "usesrc");
1364 return -1;
1365 }
1366
1367 if (!strcmp(args[3], "client")) {
1368 curproxy->options |= PR_O_TPXY_CLI;
1369 } else if (!strcmp(args[3], "clientip")) {
1370 curproxy->options |= PR_O_TPXY_CIP;
1371 } else {
1372 curproxy->options |= PR_O_TPXY_ADDR;
1373 curproxy->tproxy_addr = *str2sa(args[3]);
1374 }
1375 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001376#else /* no CTTPROXY support */
1377 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1378 file, linenum, "usesrc");
1379 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001380#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001381 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001382 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001383#ifdef CONFIG_HAP_CTTPROXY
1384 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1385 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1386 file, linenum, "usesrc", "source");
1387 return -1;
1388 }
1389#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1391 regex_t *preg;
1392 if (curproxy == &defproxy) {
1393 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1394 return -1;
1395 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001396 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1397 return 0;
1398
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 if (*(args[1]) == 0 || *(args[2]) == 0) {
1400 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1401 file, linenum, args[0]);
1402 return -1;
1403 }
1404
1405 preg = calloc(1, sizeof(regex_t));
1406 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1407 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1408 return -1;
1409 }
1410
1411 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1412 if (err) {
1413 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1414 file, linenum, *err);
1415 return -1;
1416 }
1417 }
1418 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1419 regex_t *preg;
1420 if (curproxy == &defproxy) {
1421 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1422 return -1;
1423 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001424 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1425 return 0;
1426
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427 if (*(args[1]) == 0) {
1428 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1429 return -1;
1430 }
1431
1432 preg = calloc(1, sizeof(regex_t));
1433 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1434 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1435 return -1;
1436 }
1437
1438 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1439 }
1440 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1441 regex_t *preg;
1442 if (curproxy == &defproxy) {
1443 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1444 return -1;
1445 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001446 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1447 return 0;
1448
Willy Tarreaubaaee002006-06-26 02:48:02 +02001449 if (*(args[1]) == 0) {
1450 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1451 return -1;
1452 }
1453
1454 preg = calloc(1, sizeof(regex_t));
1455 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1456 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1457 return -1;
1458 }
1459
1460 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1461 }
1462 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1463 regex_t *preg;
1464 if (curproxy == &defproxy) {
1465 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1466 return -1;
1467 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001468 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1469 return 0;
1470
Willy Tarreaubaaee002006-06-26 02:48:02 +02001471 if (*(args[1]) == 0) {
1472 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1473 return -1;
1474 }
1475
1476 preg = calloc(1, sizeof(regex_t));
1477 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1478 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1479 return -1;
1480 }
1481
1482 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1483 }
1484 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1485 regex_t *preg;
1486 if (curproxy == &defproxy) {
1487 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1488 return -1;
1489 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001490 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1491 return 0;
1492
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493 if (*(args[1]) == 0) {
1494 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1495 return -1;
1496 }
1497
1498 preg = calloc(1, sizeof(regex_t));
1499 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1500 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1501 return -1;
1502 }
1503
1504 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1505 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001506 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1507 regex_t *preg;
1508 if (curproxy == &defproxy) {
1509 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1510 return -1;
1511 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001512 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1513 return 0;
1514
Willy Tarreaub8750a82006-09-03 09:56:00 +02001515 if (*(args[1]) == 0) {
1516 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1517 return -1;
1518 }
1519
1520 preg = calloc(1, sizeof(regex_t));
1521 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1522 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1523 return -1;
1524 }
1525
1526 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1527 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001528 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1529 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001530 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001531 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1532 return -1;
1533 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001534 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1535 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001536
Willy Tarreau977b8e42006-12-29 14:19:17 +01001537 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001538 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1539 file, linenum, args[0]);
1540 return -1;
1541 }
1542
1543 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001544 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001545 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1546 }
1547
1548 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1549 }
1550 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1551 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001552 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001553 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1554 return -1;
1555 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001556 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1557 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001558
Willy Tarreau977b8e42006-12-29 14:19:17 +01001559 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001560 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1561 file, linenum, args[0]);
1562 return -1;
1563 }
1564
1565 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001566 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001567 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1568 }
1569
1570 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1573 regex_t *preg;
1574 if (curproxy == &defproxy) {
1575 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1576 return -1;
1577 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001578 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1579 return 0;
1580
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581 if (*(args[1]) == 0 || *(args[2]) == 0) {
1582 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1583 file, linenum, args[0]);
1584 return -1;
1585 }
1586
1587 preg = calloc(1, sizeof(regex_t));
1588 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1589 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1590 return -1;
1591 }
1592
1593 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1594 if (err) {
1595 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1596 file, linenum, *err);
1597 return -1;
1598 }
1599 }
1600 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1601 regex_t *preg;
1602 if (curproxy == &defproxy) {
1603 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1604 return -1;
1605 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001606 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1607 return 0;
1608
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609 if (*(args[1]) == 0) {
1610 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1611 return -1;
1612 }
1613
1614 preg = calloc(1, sizeof(regex_t));
1615 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1616 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1617 return -1;
1618 }
1619
1620 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1621 }
1622 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1623 regex_t *preg;
1624 if (curproxy == &defproxy) {
1625 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1626 return -1;
1627 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001628 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1629 return 0;
1630
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 if (*(args[1]) == 0) {
1632 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1633 return -1;
1634 }
1635
1636 preg = calloc(1, sizeof(regex_t));
1637 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1638 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1639 return -1;
1640 }
1641
1642 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1643 }
1644 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1645 regex_t *preg;
1646 if (curproxy == &defproxy) {
1647 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1648 return -1;
1649 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001650 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1651 return 0;
1652
Willy Tarreaubaaee002006-06-26 02:48:02 +02001653 if (*(args[1]) == 0) {
1654 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1655 return -1;
1656 }
1657
1658 preg = calloc(1, sizeof(regex_t));
1659 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1660 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1661 return -1;
1662 }
1663
1664 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1665 }
1666 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1667 regex_t *preg;
1668 if (curproxy == &defproxy) {
1669 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1670 return -1;
1671 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001672 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1673 return 0;
1674
Willy Tarreaubaaee002006-06-26 02:48:02 +02001675 if (*(args[1]) == 0) {
1676 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1677 return -1;
1678 }
1679
1680 preg = calloc(1, sizeof(regex_t));
1681 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1682 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1683 return -1;
1684 }
1685
1686 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1687 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001688 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1689 regex_t *preg;
1690 if (curproxy == &defproxy) {
1691 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1692 return -1;
1693 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001694 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1695 return 0;
1696
Willy Tarreaub8750a82006-09-03 09:56:00 +02001697 if (*(args[1]) == 0) {
1698 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1699 return -1;
1700 }
1701
1702 preg = calloc(1, sizeof(regex_t));
1703 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1704 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1705 return -1;
1706 }
1707
1708 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1709 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1711 if (curproxy == &defproxy) {
1712 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1713 return -1;
1714 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001715 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1716 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001717
1718 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
1719 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1720 return 0;
1721 }
1722
1723 if (*(args[1]) == 0) {
1724 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1725 return -1;
1726 }
1727
1728 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
1729 }
1730 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
1731 regex_t *preg;
1732
1733 if (*(args[1]) == 0 || *(args[2]) == 0) {
1734 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1735 file, linenum, args[0]);
1736 return -1;
1737 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001738 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1739 return 0;
1740
Willy Tarreaubaaee002006-06-26 02:48:02 +02001741 preg = calloc(1, sizeof(regex_t));
1742 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1743 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1744 return -1;
1745 }
1746
1747 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1748 if (err) {
1749 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1750 file, linenum, *err);
1751 return -1;
1752 }
1753 }
1754 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
1755 regex_t *preg;
1756 if (curproxy == &defproxy) {
1757 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1758 return -1;
1759 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001760 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1761 return 0;
1762
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763 if (*(args[1]) == 0) {
1764 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1765 return -1;
1766 }
1767
1768 preg = calloc(1, sizeof(regex_t));
1769 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1770 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1771 return -1;
1772 }
1773
1774 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
1775 if (err) {
1776 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1777 file, linenum, *err);
1778 return -1;
1779 }
1780 }
1781 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
1782 regex_t *preg;
1783 if (curproxy == &defproxy) {
1784 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1785 return -1;
1786 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001787 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1788 return 0;
1789
Willy Tarreaubaaee002006-06-26 02:48:02 +02001790 if (*(args[1]) == 0) {
1791 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1792 return -1;
1793 }
1794
1795 preg = calloc(1, sizeof(regex_t));
1796 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1797 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1798 return -1;
1799 }
1800
1801 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
1802 if (err) {
1803 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1804 file, linenum, *err);
1805 return -1;
1806 }
1807 }
1808 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
1809 regex_t *preg;
1810 if (curproxy == &defproxy) {
1811 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1812 return -1;
1813 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001814 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1815 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001816
1817 if (*(args[1]) == 0 || *(args[2]) == 0) {
1818 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1819 file, linenum, args[0]);
1820 return -1;
1821 }
1822
1823 preg = calloc(1, sizeof(regex_t));
1824 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1825 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1826 return -1;
1827 }
1828
1829 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1830 if (err) {
1831 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1832 file, linenum, *err);
1833 return -1;
1834 }
1835 }
1836 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
1837 regex_t *preg;
1838 if (curproxy == &defproxy) {
1839 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1840 return -1;
1841 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001842 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1843 return 0;
1844
Willy Tarreaubaaee002006-06-26 02:48:02 +02001845 if (*(args[1]) == 0) {
1846 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1847 return -1;
1848 }
1849
1850 preg = calloc(1, sizeof(regex_t));
1851 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1852 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1853 return -1;
1854 }
1855
1856 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
1857 if (err) {
1858 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1859 file, linenum, *err);
1860 return -1;
1861 }
1862 }
1863 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
1864 regex_t *preg;
1865 if (curproxy == &defproxy) {
1866 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1867 return -1;
1868 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001869 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1870 return 0;
1871
Willy Tarreaubaaee002006-06-26 02:48:02 +02001872 if (*(args[1]) == 0) {
1873 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1874 return -1;
1875 }
1876
1877 preg = calloc(1, sizeof(regex_t));
1878 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1879 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1880 return -1;
1881 }
1882
1883 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
1884 if (err) {
1885 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1886 file, linenum, *err);
1887 return -1;
1888 }
1889 }
1890 else if (!strcmp(args[0], "rspadd")) { /* add response header */
1891 if (curproxy == &defproxy) {
1892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1893 return -1;
1894 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001895 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1896 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001897
1898 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
1899 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1900 return 0;
1901 }
1902
1903 if (*(args[1]) == 0) {
1904 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1905 return -1;
1906 }
1907
1908 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
1909 }
1910 else if (!strcmp(args[0], "errorloc") ||
1911 !strcmp(args[0], "errorloc302") ||
1912 !strcmp(args[0], "errorloc303")) { /* error location */
1913 int errnum, errlen;
1914 char *err;
1915
1916 // if (curproxy == &defproxy) {
1917 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1918 // return -1;
1919 // }
1920
Willy Tarreau977b8e42006-12-29 14:19:17 +01001921 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
1922 return 0;
1923
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01001925 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 return -1;
1927 }
1928
1929 errnum = atol(args[1]);
1930 if (!strcmp(args[0], "errorloc303")) {
1931 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
1932 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
1933 } else {
1934 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
1935 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
1936 }
1937
Willy Tarreau0f772532006-12-23 20:51:41 +01001938 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
1939 if (http_err_codes[rc] == errnum) {
1940 if (curproxy->errmsg[rc].str)
1941 free(curproxy->errmsg[rc].str);
1942 curproxy->errmsg[rc].str = err;
1943 curproxy->errmsg[rc].len = errlen;
1944 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 }
Willy Tarreau0f772532006-12-23 20:51:41 +01001947
1948 if (rc >= HTTP_ERR_SIZE) {
1949 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
1950 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001951 free(err);
1952 }
1953 }
1954 else {
1955 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
1956 return -1;
1957 }
1958 return 0;
1959}
1960
1961
1962/*
1963 * This function reads and parses the configuration file given in the argument.
1964 * returns 0 if OK, -1 if error.
1965 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02001966int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001967{
1968 char thisline[256];
1969 char *line;
1970 FILE *f;
1971 int linenum = 0;
1972 char *end;
1973 char *args[MAX_LINE_ARGS];
1974 int arg;
1975 int cfgerr = 0;
Willy Tarreau80587432006-12-24 17:47:20 +01001976 int nbchk, mininter;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001977 int confsect = CFG_NONE;
1978
1979 struct proxy *curproxy = NULL;
1980 struct server *newsrv = NULL;
1981
1982 if ((f=fopen(file,"r")) == NULL)
1983 return -1;
1984
1985 init_default_instance();
1986
1987 while (fgets(line = thisline, sizeof(thisline), f) != NULL) {
1988 linenum++;
1989
1990 end = line + strlen(line);
1991
1992 /* skip leading spaces */
1993 while (isspace((int)*line))
1994 line++;
1995
1996 arg = 0;
1997 args[arg] = line;
1998
1999 while (*line && arg < MAX_LINE_ARGS) {
2000 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2001 * C equivalent value. Other combinations left unchanged (eg: \1).
2002 */
2003 if (*line == '\\') {
2004 int skip = 0;
2005 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2006 *line = line[1];
2007 skip = 1;
2008 }
2009 else if (line[1] == 'r') {
2010 *line = '\r';
2011 skip = 1;
2012 }
2013 else if (line[1] == 'n') {
2014 *line = '\n';
2015 skip = 1;
2016 }
2017 else if (line[1] == 't') {
2018 *line = '\t';
2019 skip = 1;
2020 }
2021 else if (line[1] == 'x') {
2022 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2023 unsigned char hex1, hex2;
2024 hex1 = toupper(line[2]) - '0';
2025 hex2 = toupper(line[3]) - '0';
2026 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2027 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2028 *line = (hex1<<4) + hex2;
2029 skip = 3;
2030 }
2031 else {
2032 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2033 return -1;
2034 }
2035 }
2036 if (skip) {
2037 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2038 end -= skip;
2039 }
2040 line++;
2041 }
2042 else if (*line == '#' || *line == '\n' || *line == '\r') {
2043 /* end of string, end of loop */
2044 *line = 0;
2045 break;
2046 }
2047 else if (isspace((int)*line)) {
2048 /* a non-escaped space is an argument separator */
2049 *line++ = 0;
2050 while (isspace((int)*line))
2051 line++;
2052 args[++arg] = line;
2053 }
2054 else {
2055 line++;
2056 }
2057 }
2058
2059 /* empty line */
2060 if (!**args)
2061 continue;
2062
2063 /* zero out remaining args */
2064 while (++arg < MAX_LINE_ARGS) {
2065 args[arg] = line;
2066 }
2067
Willy Tarreau977b8e42006-12-29 14:19:17 +01002068 if (!strcmp(args[0], "listen") ||
2069 !strcmp(args[0], "frontend") ||
2070 !strcmp(args[0], "backend") ||
2071 !strcmp(args[0], "ruleset") ||
2072 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002073 confsect = CFG_LISTEN;
2074 else if (!strcmp(args[0], "global")) /* global config */
2075 confsect = CFG_GLOBAL;
2076 /* else it's a section keyword */
2077
2078 switch (confsect) {
2079 case CFG_LISTEN:
2080 if (cfg_parse_listen(file, linenum, args) < 0)
2081 return -1;
2082 break;
2083 case CFG_GLOBAL:
2084 if (cfg_parse_global(file, linenum, args) < 0)
2085 return -1;
2086 break;
2087 default:
2088 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2089 return -1;
2090 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002091 }
2092 fclose(f);
2093
2094 /*
2095 * Now, check for the integrity of all that we have collected.
2096 */
2097
2098 /* will be needed further to delay some tasks */
2099 tv_now(&now);
2100
2101 if ((curproxy = proxy) == NULL) {
2102 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2103 file);
2104 return -1;
2105 }
2106
2107 while (curproxy != NULL) {
Willy Tarreau97a738f2006-12-17 18:02:30 +01002108 curproxy->fiprm = curproxy->beprm = curproxy;
2109
Willy Tarreaubaaee002006-06-26 02:48:02 +02002110 if (curproxy->state == PR_STSTOPPED) {
2111 curproxy = curproxy->next;
2112 continue;
2113 }
2114
Willy Tarreau977b8e42006-12-29 14:19:17 +01002115 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2116 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 +01002117 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002118 cfgerr++;
2119 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002120 else if (curproxy->cap & PR_CAP_BE &&
2121 ((curproxy->mode != PR_MODE_HEALTH) &&
2122 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
2123 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2124 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 +01002125 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002126 cfgerr++;
2127 }
2128 else if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
2129 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002130 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002131 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002132 cfgerr++;
2133 }
2134#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2135 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002136 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002137 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002138 cfgerr++;
2139 }
2140#endif
2141 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002142 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002143 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002144 }
2145 }
2146 else if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2147 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002148 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002149 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002150 }
2151 if ((newsrv = curproxy->srv) != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002152 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002153 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002154 }
2155 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002156 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002157 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002158 }
2159 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002160 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002161 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002162 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002163 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002164 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002165 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002166 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002167 }
2168 else if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
2169 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2170 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2171 file, curproxy->id);
2172 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002173 }
2174 }
2175
2176 /* if a default backend was specified, let's find it */
2177 if (curproxy->defbe.name) {
2178 struct proxy *target;
2179
2180 for (target = proxy; target != NULL; target = target->next) {
2181 if (strcmp(target->id, curproxy->defbe.name) == 0)
2182 break;
2183 }
2184 if (target == NULL) {
2185 Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n",
2186 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2187 cfgerr++;
2188 } else if (target == curproxy) {
2189 Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
2190 cfgerr++;
2191 } else if (!(target->cap & PR_CAP_BE)) {
2192 Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n",
2193 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2194 cfgerr++;
2195 } else if (target->mode != curproxy->mode) {
2196 Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
2197 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2198 cfgerr++;
2199 } else {
2200 free(curproxy->defbe.name);
2201 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002202 }
2203 }
2204
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002205 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002206 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2207 /* map jump target for ACT_SETBE in req_rep chain */
2208 struct hdr_exp *exp;
2209 struct proxy *target;
2210 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
2211 if (exp->action != ACT_SETBE)
2212 continue;
2213 for (target = proxy; target != NULL; target = target->next) {
2214 if (strcmp(target->id, exp->replace) == 0)
2215 break;
2216 }
2217 if (target == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002218 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002219 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaua496b602006-12-17 23:15:24 +01002220 cfgerr++;
2221 } else if (target == curproxy) {
2222 Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
2223 cfgerr++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002224 } else if (!(target->cap & PR_CAP_BE)) {
2225 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002226 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002227 cfgerr++;
2228 } else if (target->mode != PR_MODE_HTTP) {
2229 Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002230 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002231 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002232 } else {
2233 free((void *)exp->replace);
2234 exp->replace = (const char *)target;
2235 }
2236 }
2237 }
Willy Tarreau2738a142006-07-08 17:28:09 +02002238 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002239 (((curproxy->cap & PR_CAP_FE) && !curproxy->clitimeout) ||
2240 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) && (!curproxy->contimeout || !curproxy->srvtimeout)))) {
2241 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002242 " | While not properly invalid, you will certainly encounter various problems\n"
2243 " | with such a configuration. To fix this, please ensure that all following\n"
2244 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002245 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002246 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002247
2248 if (curproxy->options & PR_O_SSL3_CHK) {
2249 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2250 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2251 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2252 }
2253
Willy Tarreau86034312006-12-29 00:10:33 +01002254 /* for backwards compatibility with "listen" instances, if
2255 * fullconn is not set but maxconn is set, then maxconn
2256 * is used.
2257 */
2258 if (!curproxy->fullconn)
2259 curproxy->fullconn = curproxy->maxconn;
2260
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 /* first, we will invert the servers list order */
2262 newsrv = NULL;
2263 while (curproxy->srv) {
2264 struct server *next;
2265
2266 next = curproxy->srv->next;
2267 curproxy->srv->next = newsrv;
2268 newsrv = curproxy->srv;
2269 if (!next)
2270 break;
2271 curproxy->srv = next;
2272 }
2273
2274 /* now, newsrv == curproxy->srv */
2275 if (newsrv) {
2276 struct server *srv;
2277 int pgcd;
2278 int act, bck;
2279
2280 /* We will factor the weights to reduce the table,
2281 * using Euclide's largest common divisor algorithm
2282 */
2283 pgcd = newsrv->uweight + 1;
2284 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2285 int t, w;
2286
2287 w = srv->uweight + 1;
2288 while (w) {
2289 t = pgcd % w;
2290 pgcd = w;
2291 w = t;
2292 }
2293 }
2294
2295 act = bck = 0;
2296 for (srv = newsrv; srv; srv = srv->next) {
2297 srv->eweight = ((srv->uweight + 1) / pgcd) - 1;
2298 if (srv->state & SRV_BACKUP)
2299 bck += srv->eweight + 1;
2300 else
2301 act += srv->eweight + 1;
2302 }
2303
2304 /* this is the largest map we will ever need for this servers list */
2305 if (act < bck)
2306 act = bck;
2307
2308 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2309 /* recounts servers and their weights */
2310 recount_servers(curproxy);
2311 recalc_server_map(curproxy);
2312 }
2313
2314 if (curproxy->options & PR_O_LOGASAP)
2315 curproxy->to_log &= ~LW_BYTES;
2316
Willy Tarreaubaaee002006-06-26 02:48:02 +02002317 /*
2318 * If this server supports a maxconn parameter, it needs a dedicated
2319 * tasks to fill the emptied slots when a connection leaves.
2320 */
2321 newsrv = curproxy->srv;
2322 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002323 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002324 /* Only 'minconn' was specified, or it was higher than or equal
2325 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2326 * this will avoid further useless expensive computations.
2327 */
2328 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002329 } else if (newsrv->maxconn && !newsrv->minconn) {
2330 /* minconn was not specified, so we set it to maxconn */
2331 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002332 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2333 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002334 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002335 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002336 }
2337
2338 if (newsrv->maxconn > 0) {
2339 struct task *t;
2340
2341 if ((t = pool_alloc(task)) == NULL) {
2342 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2343 return -1;
2344 }
2345
Willy Tarreau964c9362007-01-07 00:38:00 +01002346 t->rqnext = NULL;
2347 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002348 t->state = TASK_IDLE;
2349 t->process = process_srv_queue;
2350 t->context = newsrv;
2351 newsrv->queue_mgt = t;
2352
2353 /* never run it unless specifically woken up */
2354 tv_eternity(&t->expire);
2355 task_queue(t);
2356 }
2357 newsrv = newsrv->next;
2358 }
2359
2360 /* now we'll start this proxy's health checks if any */
2361 /* 1- count the checkers to run simultaneously */
2362 nbchk = 0;
2363 mininter = 0;
2364 newsrv = curproxy->srv;
2365 while (newsrv != NULL) {
2366 if (newsrv->state & SRV_CHECKED) {
2367 if (!mininter || mininter > newsrv->inter)
2368 mininter = newsrv->inter;
2369 nbchk++;
2370 }
2371 newsrv = newsrv->next;
2372 }
2373
2374 /* 2- start them as far as possible from each others while respecting
2375 * their own intervals. For this, we will start them after their own
2376 * interval added to the min interval divided by the number of servers,
2377 * weighted by the server's position in the list.
2378 */
2379 if (nbchk > 0) {
2380 struct task *t;
2381 int srvpos;
2382
2383 newsrv = curproxy->srv;
2384 srvpos = 0;
2385 while (newsrv != NULL) {
2386 /* should this server be checked ? */
2387 if (newsrv->state & SRV_CHECKED) {
2388 if ((t = pool_alloc(task)) == NULL) {
2389 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2390 return -1;
2391 }
2392
Willy Tarreau964c9362007-01-07 00:38:00 +01002393 t->wq = NULL;
2394 t->rqnext = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 t->state = TASK_IDLE;
2396 t->process = process_chk;
2397 t->context = newsrv;
2398
2399 /* check this every ms */
2400 tv_delayfrom(&t->expire, &now,
2401 newsrv->inter + mininter * srvpos / nbchk);
2402 task_queue(t);
2403 //task_wakeup(&rq, t);
2404 srvpos++;
2405 }
2406 newsrv = newsrv->next;
2407 }
2408 }
2409
2410 curproxy = curproxy->next;
2411 }
2412 if (cfgerr > 0) {
2413 Alert("Errors found in configuration file, aborting.\n");
2414 return -1;
2415 }
2416 else
2417 return 0;
2418}
2419
2420
2421
2422/*
2423 * Local variables:
2424 * c-indent-level: 8
2425 * c-basic-offset: 8
2426 * End:
2427 */