blob: 38d894a7ddcc5cc6a689f2f1461a8113c6a8943b [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;
78} cfg_opts[] =
79{
80#ifdef TPROXY
81 { "transparent", PR_O_TRANSP, PR_CAP_FE },
82#endif
83 { "redispatch", PR_O_REDISP, PR_CAP_BE },
84 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE },
85 { "forwardfor", PR_O_FWDFOR, PR_CAP_FE | PR_CAP_BE },
86 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE },
87 { "logasap", PR_O_LOGASAP, PR_CAP_FE },
88 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE },
89 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE },
90 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE },
91 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE },
92 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE },
93 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE },
94 { "persist", PR_O_PERSIST, PR_CAP_BE },
95 { "forceclose", PR_O_FORCE_CLO | PR_O_HTTP_CLOSE, PR_CAP_BE },
96 { NULL, 0, 0 }
97};
98
Willy Tarreaubaaee002006-06-26 02:48:02 +020099
100static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
101int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
102int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
103
104/*
105 * converts <str> to a list of listeners which are dynamically allocated.
106 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
107 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
108 * - <port> is a numerical port from 1 to 65535 ;
109 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
110 * This can be repeated as many times as necessary, separated by a coma.
111 * The <tail> argument is a pointer to a current list which should be appended
112 * to the tail of the new list. The pointer to the new list is returned.
113 */
114static struct listener *str2listener(char *str, struct listener *tail)
115{
116 struct listener *l;
117 char *c, *next, *range, *dupstr;
118 int port, end;
119
120 next = dupstr = strdup(str);
121
122 while (next && *next) {
123 struct sockaddr_storage ss;
124
125 str = next;
126 /* 1) look for the end of the first address */
127 if ((next = strrchr(str, ',')) != NULL) {
128 *next++ = 0;
129 }
130
131 /* 2) look for the addr/port delimiter, it's the last colon. */
132 if ((range = strrchr(str, ':')) == NULL) {
133 Alert("Missing port number: '%s'\n", str);
134 goto fail;
135 }
136
137 *range++ = 0;
138
139 if (strrchr(str, ':') != NULL) {
140 /* IPv6 address contains ':' */
141 memset(&ss, 0, sizeof(ss));
142 ss.ss_family = AF_INET6;
143
144 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
145 Alert("Invalid server address: '%s'\n", str);
146 goto fail;
147 }
148 }
149 else {
150 memset(&ss, 0, sizeof(ss));
151 ss.ss_family = AF_INET;
152
153 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
154 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
155 }
156 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
157 struct hostent *he;
158
159 if ((he = gethostbyname(str)) == NULL) {
160 Alert("Invalid server name: '%s'\n", str);
161 goto fail;
162 }
163 else
164 ((struct sockaddr_in *)&ss)->sin_addr =
165 *(struct in_addr *) *(he->h_addr_list);
166 }
167 }
168
169 /* 3) look for the port-end delimiter */
170 if ((c = strchr(range, '-')) != NULL) {
171 *c++ = 0;
172 end = atol(c);
173 }
174 else {
175 end = atol(range);
176 }
177
178 port = atol(range);
179
180 if (port < 1 || port > 65535) {
181 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
182 goto fail;
183 }
184
185 if (end < 1 || end > 65535) {
186 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
187 goto fail;
188 }
189
190 for (; port <= end; port++) {
191 l = (struct listener *)calloc(1, sizeof(struct listener));
192 l->next = tail;
193 tail = l;
194
195 l->fd = -1;
196 l->addr = ss;
197 if (ss.ss_family == AF_INET6)
198 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
199 else
200 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
201
202 } /* end for(port) */
203 } /* end while(next) */
204 free(dupstr);
205 return tail;
206 fail:
207 free(dupstr);
208 return NULL;
209}
210
Willy Tarreau977b8e42006-12-29 14:19:17 +0100211/*
212 * Sends a warning if proxy <proxy> does not have at least one of the
213 * capabilities in <cap>. An optionnal <hint> may be added at the end
214 * of the warning to help the user. Returns 1 if a warning was emitted
215 * or 0 if the condition is valid.
216 */
217int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
218{
219 char *msg;
220
221 switch (cap) {
222 case PR_CAP_BE: msg = "no backend"; break;
223 case PR_CAP_FE: msg = "no frontend"; break;
224 case PR_CAP_RS: msg = "no ruleset"; break;
225 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
226 default: msg = "not enough"; break;
227 }
228
229 if (!(proxy->cap & cap)) {
230 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100231 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100232 return 1;
233 }
234 return 0;
235}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
237/*
238 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
239 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200240int cfg_parse_global(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241{
242
243 if (!strcmp(args[0], "global")) { /* new section */
244 /* no option, nothing special to do */
245 return 0;
246 }
247 else if (!strcmp(args[0], "daemon")) {
248 global.mode |= MODE_DAEMON;
249 }
250 else if (!strcmp(args[0], "debug")) {
251 global.mode |= MODE_DEBUG;
252 }
253 else if (!strcmp(args[0], "noepoll")) {
254 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
255 }
256 else if (!strcmp(args[0], "nopoll")) {
257 cfg_polling_mechanism &= ~POLL_USE_POLL;
258 }
259 else if (!strcmp(args[0], "quiet")) {
260 global.mode |= MODE_QUIET;
261 }
262 else if (!strcmp(args[0], "stats")) {
263 global.mode |= MODE_STATS;
264 }
265 else if (!strcmp(args[0], "uid")) {
266 if (global.uid != 0) {
267 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
268 return 0;
269 }
270 if (*(args[1]) == 0) {
271 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
272 return -1;
273 }
274 global.uid = atol(args[1]);
275 }
276 else if (!strcmp(args[0], "gid")) {
277 if (global.gid != 0) {
278 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
279 return 0;
280 }
281 if (*(args[1]) == 0) {
282 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
283 return -1;
284 }
285 global.gid = atol(args[1]);
286 }
287 else if (!strcmp(args[0], "nbproc")) {
288 if (global.nbproc != 0) {
289 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
290 return 0;
291 }
292 if (*(args[1]) == 0) {
293 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
294 return -1;
295 }
296 global.nbproc = atol(args[1]);
297 }
298 else if (!strcmp(args[0], "maxconn")) {
299 if (global.maxconn != 0) {
300 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
301 return 0;
302 }
303 if (*(args[1]) == 0) {
304 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
305 return -1;
306 }
307 global.maxconn = atol(args[1]);
308#ifdef SYSTEM_MAXCONN
309 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
310 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);
311 global.maxconn = DEFAULT_MAXCONN;
312 }
313#endif /* SYSTEM_MAXCONN */
314 }
315 else if (!strcmp(args[0], "ulimit-n")) {
316 if (global.rlimit_nofile != 0) {
317 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
318 return 0;
319 }
320 if (*(args[1]) == 0) {
321 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
322 return -1;
323 }
324 global.rlimit_nofile = atol(args[1]);
325 }
326 else if (!strcmp(args[0], "chroot")) {
327 if (global.chroot != NULL) {
328 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
329 return 0;
330 }
331 if (*(args[1]) == 0) {
332 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
333 return -1;
334 }
335 global.chroot = strdup(args[1]);
336 }
337 else if (!strcmp(args[0], "pidfile")) {
338 if (global.pidfile != NULL) {
339 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
340 return 0;
341 }
342 if (*(args[1]) == 0) {
343 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
344 return -1;
345 }
346 global.pidfile = strdup(args[1]);
347 }
348 else if (!strcmp(args[0], "log")) { /* syslog server address */
349 struct sockaddr_in *sa;
350 int facility, level;
351
352 if (*(args[1]) == 0 || *(args[2]) == 0) {
353 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
354 return -1;
355 }
356
357 facility = get_log_facility(args[2]);
358 if (facility < 0) {
359 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
360 exit(1);
361 }
362
363 level = 7; /* max syslog level = debug */
364 if (*(args[3])) {
365 level = get_log_level(args[3]);
366 if (level < 0) {
367 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
368 exit(1);
369 }
370 }
371
372 sa = str2sa(args[1]);
373 if (!sa->sin_port)
374 sa->sin_port = htons(SYSLOG_PORT);
375
376 if (global.logfac1 == -1) {
377 global.logsrv1 = *sa;
378 global.logfac1 = facility;
379 global.loglev1 = level;
380 }
381 else if (global.logfac2 == -1) {
382 global.logsrv2 = *sa;
383 global.logfac2 = facility;
384 global.loglev2 = level;
385 }
386 else {
387 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
388 return -1;
389 }
390
391 }
392 else {
393 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
394 return -1;
395 }
396 return 0;
397}
398
399
400static void init_default_instance()
401{
402 memset(&defproxy, 0, sizeof(defproxy));
403 defproxy.mode = PR_MODE_TCP;
404 defproxy.state = PR_STNEW;
405 defproxy.maxconn = cfg_maxpconn;
406 defproxy.conn_retries = CONN_RETRIES;
407 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
408}
409
410/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100411 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
412 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200413 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200414int cfg_parse_listen(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200415{
416 static struct proxy *curproxy = NULL;
417 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200418 const char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200419 int rc;
420
Willy Tarreau977b8e42006-12-29 14:19:17 +0100421 if (!strcmp(args[0], "listen"))
422 rc = PR_CAP_LISTEN;
423 else if (!strcmp(args[0], "frontend"))
424 rc = PR_CAP_FE | PR_CAP_RS;
425 else if (!strcmp(args[0], "backend"))
426 rc = PR_CAP_BE | PR_CAP_RS;
427 else if (!strcmp(args[0], "ruleset"))
428 rc = PR_CAP_RS;
429 else
430 rc = PR_CAP_NONE;
431
432 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200433 if (!*args[1]) {
434 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
435 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
436 file, linenum, args[0]);
437 return -1;
438 }
439
440 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
441 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
442 return -1;
443 }
444
445 curproxy->next = proxy;
446 proxy = curproxy;
447 LIST_INIT(&curproxy->pendconns);
448
449 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100450 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200451
452 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100453 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200454 curproxy->listen = str2listener(args[2], curproxy->listen);
455 if (!curproxy->listen)
456 return -1;
457 global.maxsock++;
458 }
459
460 /* set default values */
461 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 curproxy->options = defproxy.options;
463
Willy Tarreau977b8e42006-12-29 14:19:17 +0100464 if (curproxy->cap & PR_CAP_FE) {
465 curproxy->maxconn = defproxy.maxconn;
466
467 /* initialize error relocations */
468 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
469 if (defproxy.errmsg[rc].str)
470 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
471 }
472
473 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475
Willy Tarreau977b8e42006-12-29 14:19:17 +0100476 if (curproxy->cap & PR_CAP_BE) {
477 curproxy->fullconn = defproxy.fullconn;
478 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479
Willy Tarreau977b8e42006-12-29 14:19:17 +0100480 if (defproxy.check_req)
481 curproxy->check_req = strdup(defproxy.check_req);
482 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483
Willy Tarreau977b8e42006-12-29 14:19:17 +0100484 if (defproxy.cookie_name)
485 curproxy->cookie_name = strdup(defproxy.cookie_name);
486 curproxy->cookie_len = defproxy.cookie_len;
487 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200488
Willy Tarreau977b8e42006-12-29 14:19:17 +0100489 if (curproxy->cap & PR_CAP_RS) {
490 if (defproxy.capture_name)
491 curproxy->capture_name = strdup(defproxy.capture_name);
492 curproxy->capture_namelen = defproxy.capture_namelen;
493 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200495
Willy Tarreau977b8e42006-12-29 14:19:17 +0100496 if (curproxy->cap & PR_CAP_FE) {
497 curproxy->clitimeout = defproxy.clitimeout;
498 curproxy->uri_auth = defproxy.uri_auth;
499 curproxy->mon_net = defproxy.mon_net;
500 curproxy->mon_mask = defproxy.mon_mask;
501 if (defproxy.monitor_uri)
502 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
503 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100504 if (defproxy.defbe.name)
505 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100506 }
507
508 if (curproxy->cap & PR_CAP_BE) {
509 curproxy->contimeout = defproxy.contimeout;
510 curproxy->srvtimeout = defproxy.srvtimeout;
511 curproxy->source_addr = defproxy.source_addr;
512 }
513
Willy Tarreaubaaee002006-06-26 02:48:02 +0200514 curproxy->mode = defproxy.mode;
515 curproxy->logfac1 = defproxy.logfac1;
516 curproxy->logsrv1 = defproxy.logsrv1;
517 curproxy->loglev1 = defproxy.loglev1;
518 curproxy->logfac2 = defproxy.logfac2;
519 curproxy->logsrv2 = defproxy.logsrv2;
520 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200521 curproxy->grace = defproxy.grace;
Willy Tarreau1c47f852006-07-09 08:22:27 +0200522
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 return 0;
524 }
525 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
526 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100527 /* FIXME-20070101: we should do this too at the end of the
528 * config parsing to free all default values.
529 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530 if (defproxy.check_req) free(defproxy.check_req);
531 if (defproxy.cookie_name) free(defproxy.cookie_name);
532 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200533 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100534 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100535
536 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
537 if (defproxy.errmsg[rc].len)
538 free(defproxy.errmsg[rc].str);
539 }
540
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541 /* we cannot free uri_auth because it might already be used */
542 init_default_instance();
543 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100544 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200545 return 0;
546 }
547 else if (curproxy == NULL) {
548 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
549 return -1;
550 }
551
Willy Tarreau977b8e42006-12-29 14:19:17 +0100552
553 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200554 if (!strcmp(args[0], "bind")) { /* new listen addresses */
555 if (curproxy == &defproxy) {
556 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
557 return -1;
558 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100559 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
560 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200561
562 if (strchr(args[1], ':') == NULL) {
563 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
564 file, linenum, args[0]);
565 return -1;
566 }
567 curproxy->listen = str2listener(args[1], curproxy->listen);
568 if (!curproxy->listen)
569 return -1;
570 global.maxsock++;
571 return 0;
572 }
573 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
574 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
575 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
576 file, linenum, args[0]);
577 return -1;
578 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100579 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
580 return 0;
581
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582 /* flush useless bits */
583 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
584 return 0;
585 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200586 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100587 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
588 return 0;
589
Willy Tarreau1c47f852006-07-09 08:22:27 +0200590 if (!*args[1]) {
591 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
592 file, linenum, args[0]);
593 return -1;
594 }
595
596 if (curproxy->monitor_uri != NULL)
597 free(curproxy->monitor_uri);
598
599 curproxy->monitor_uri_len = strlen(args[1]) + 2; /* include leading and trailing spaces */
600 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
601 memcpy(curproxy->monitor_uri + 1, args[1], curproxy->monitor_uri_len - 2);
602 curproxy->monitor_uri[curproxy->monitor_uri_len-1] = curproxy->monitor_uri[0] = ' ';
603 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
604
605 return 0;
606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
608 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
609 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
610 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
611 else {
612 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
613 return -1;
614 }
615 }
616 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
617 curproxy->state = PR_STSTOPPED;
618 }
619 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
620 curproxy->state = PR_STNEW;
621 }
622 else if (!strcmp(args[0], "cookie")) { /* cookie name */
623 int cur_arg;
624 // if (curproxy == &defproxy) {
625 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
626 // return -1;
627 // }
628
Willy Tarreau977b8e42006-12-29 14:19:17 +0100629 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
630 return 0;
631
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632 if (curproxy->cookie_name != NULL) {
633 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
634 // file, linenum);
635 // return 0;
636 free(curproxy->cookie_name);
637 }
638
639 if (*(args[1]) == 0) {
640 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
641 file, linenum, args[0]);
642 return -1;
643 }
644 curproxy->cookie_name = strdup(args[1]);
645 curproxy->cookie_len = strlen(curproxy->cookie_name);
646
647 cur_arg = 2;
648 while (*(args[cur_arg])) {
649 if (!strcmp(args[cur_arg], "rewrite")) {
650 curproxy->options |= PR_O_COOK_RW;
651 }
652 else if (!strcmp(args[cur_arg], "indirect")) {
653 curproxy->options |= PR_O_COOK_IND;
654 }
655 else if (!strcmp(args[cur_arg], "insert")) {
656 curproxy->options |= PR_O_COOK_INS;
657 }
658 else if (!strcmp(args[cur_arg], "nocache")) {
659 curproxy->options |= PR_O_COOK_NOC;
660 }
661 else if (!strcmp(args[cur_arg], "postonly")) {
662 curproxy->options |= PR_O_COOK_POST;
663 }
664 else if (!strcmp(args[cur_arg], "prefix")) {
665 curproxy->options |= PR_O_COOK_PFX;
666 }
667 else {
668 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
669 file, linenum, args[0]);
670 return -1;
671 }
672 cur_arg++;
673 }
674 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
675 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
676 file, linenum);
677 return -1;
678 }
679
680 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
681 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
682 file, linenum);
683 return -1;
684 }
685 }/* end else if (!strcmp(args[0], "cookie")) */
686 else if (!strcmp(args[0], "appsession")) { /* cookie name */
687 // if (curproxy == &defproxy) {
688 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
689 // return -1;
690 // }
691
Willy Tarreau977b8e42006-12-29 14:19:17 +0100692 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
693 return 0;
694
Willy Tarreaubaaee002006-06-26 02:48:02 +0200695 if (curproxy->appsession_name != NULL) {
696 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
697 // file, linenum);
698 // return 0;
699 free(curproxy->appsession_name);
700 }
701
702 if (*(args[5]) == 0) {
703 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
704 file, linenum, args[0]);
705 return -1;
706 }
707 have_appsession = 1;
708 curproxy->appsession_name = strdup(args[1]);
709 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
710 curproxy->appsession_len = atoi(args[3]);
711 curproxy->appsession_timeout = atoi(args[5]);
712 rc = chtbl_init(&(curproxy->htbl_proxy), TBLSIZ, hashpjw, match_str, destroy);
713 if (rc) {
714 Alert("Error Init Appsession Hashtable.\n");
715 return -1;
716 }
717 } /* Url App Session */
718 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100719 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
720 return 0;
721
Willy Tarreaubaaee002006-06-26 02:48:02 +0200722 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
723 // if (curproxy == &defproxy) {
724 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
725 // return -1;
726 // }
727
728 if (curproxy->capture_name != NULL) {
729 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
730 // file, linenum, args[0]);
731 // return 0;
732 free(curproxy->capture_name);
733 }
734
735 if (*(args[4]) == 0) {
736 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
737 file, linenum, args[0]);
738 return -1;
739 }
740 curproxy->capture_name = strdup(args[2]);
741 curproxy->capture_namelen = strlen(curproxy->capture_name);
742 curproxy->capture_len = atol(args[4]);
743 if (curproxy->capture_len >= CAPTURE_LEN) {
744 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
745 file, linenum, CAPTURE_LEN - 1);
746 curproxy->capture_len = CAPTURE_LEN - 1;
747 }
748 curproxy->to_log |= LW_COOKIE;
749 }
750 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
751 struct cap_hdr *hdr;
752
753 if (curproxy == &defproxy) {
754 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
755 return -1;
756 }
757
758 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
759 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
760 file, linenum, args[0], args[1]);
761 return -1;
762 }
763
764 hdr = calloc(sizeof(struct cap_hdr), 1);
765 hdr->next = curproxy->req_cap;
766 hdr->name = strdup(args[3]);
767 hdr->namelen = strlen(args[3]);
768 hdr->len = atol(args[5]);
769 hdr->index = curproxy->nb_req_cap++;
770 curproxy->req_cap = hdr;
771 curproxy->to_log |= LW_REQHDR;
772 }
773 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
774 struct cap_hdr *hdr;
775
776 if (curproxy == &defproxy) {
777 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
778 return -1;
779 }
780
781 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
782 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
783 file, linenum, args[0], args[1]);
784 return -1;
785 }
786 hdr = calloc(sizeof(struct cap_hdr), 1);
787 hdr->next = curproxy->rsp_cap;
788 hdr->name = strdup(args[3]);
789 hdr->namelen = strlen(args[3]);
790 hdr->len = atol(args[5]);
791 hdr->index = curproxy->nb_rsp_cap++;
792 curproxy->rsp_cap = hdr;
793 curproxy->to_log |= LW_RSPHDR;
794 }
795 else {
796 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
797 file, linenum, args[0]);
798 return -1;
799 }
800 }
801 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
802 if (curproxy->contimeout != defproxy.contimeout) {
803 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
804 return 0;
805 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100806 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
807 return 0;
808
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 if (*(args[1]) == 0) {
810 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
811 file, linenum, args[0]);
812 return -1;
813 }
814 curproxy->contimeout = atol(args[1]);
815 }
816 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
817 if (curproxy->clitimeout != defproxy.clitimeout) {
818 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
819 file, linenum, args[0]);
820 return 0;
821 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100822 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
823 return 0;
824
Willy Tarreaubaaee002006-06-26 02:48:02 +0200825 if (*(args[1]) == 0) {
826 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
827 file, linenum, args[0]);
828 return -1;
829 }
830 curproxy->clitimeout = atol(args[1]);
831 }
832 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
833 if (curproxy->srvtimeout != defproxy.srvtimeout) {
834 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
835 return 0;
836 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100837 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
838 return 0;
839
Willy Tarreaubaaee002006-06-26 02:48:02 +0200840 if (*(args[1]) == 0) {
841 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
842 file, linenum, args[0]);
843 return -1;
844 }
845 curproxy->srvtimeout = atol(args[1]);
846 }
847 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100848 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
849 return 0;
850
Willy Tarreaubaaee002006-06-26 02:48:02 +0200851 if (*(args[1]) == 0) {
852 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
853 file, linenum, args[0]);
854 return -1;
855 }
856 curproxy->conn_retries = atol(args[1]);
857 }
858 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100859 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
860 return 0;
861
Willy Tarreaubaaee002006-06-26 02:48:02 +0200862 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
863 curproxy->uri_auth = NULL; /* we must detach from the default config */
864
865 if (*(args[1]) == 0) {
866 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
867 return -1;
868 } else if (!strcmp(args[1], "uri")) {
869 if (*(args[2]) == 0) {
870 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
871 return -1;
872 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
873 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
874 return -1;
875 }
876 } else if (!strcmp(args[1], "realm")) {
877 if (*(args[2]) == 0) {
878 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
879 return -1;
880 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
881 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
882 return -1;
883 }
884 } else if (!strcmp(args[1], "auth")) {
885 if (*(args[2]) == 0) {
886 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
887 return -1;
888 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
889 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
890 return -1;
891 }
892 } else if (!strcmp(args[1], "scope")) {
893 if (*(args[2]) == 0) {
894 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
895 return -1;
896 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
897 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
898 return -1;
899 }
900 } else if (!strcmp(args[1], "enable")) {
901 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
902 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
903 return -1;
904 }
905 } else {
906 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'uri', 'realm', 'auth' or 'enable').\n",
907 file, linenum, args[0]);
908 return -1;
909 }
910 }
911 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100912 int optnum;
913
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914 if (*(args[1]) == 0) {
915 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
916 return -1;
917 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100918
919 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
920 if (!strcmp(args[1], cfg_opts[optnum].name)) {
921 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
922 return 0;
923 curproxy->options |= cfg_opts[optnum].val;
924 return 0;
925 }
926 }
927
928 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 /* generate a complete HTTP log */
930 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
931 else if (!strcmp(args[1], "tcplog"))
932 /* generate a detailed TCP log */
933 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934 else if (!strcmp(args[1], "tcpka")) {
935 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +0100936 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
937 return 0;
938
939 if (curproxy->cap & PR_CAP_FE)
940 curproxy->options |= PR_O_TCP_CLI_KA;
941 if (curproxy->cap & PR_CAP_BE)
942 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 }
944 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100945 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
946 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947 /* use HTTP request to check servers' health */
948 if (curproxy->check_req != NULL) {
949 free(curproxy->check_req);
950 }
951 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +0200952 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953 if (!*args[2]) { /* no argument */
954 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
955 curproxy->check_len = strlen(DEF_CHECK_REQ);
956 } else if (!*args[3]) { /* one argument : URI */
957 int reqlen = strlen(args[2]) + strlen("OPTIONS / HTTP/1.0\r\n\r\n");
958 curproxy->check_req = (char *)malloc(reqlen);
959 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
960 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
961 } else { /* more arguments : METHOD URI [HTTP_VER] */
962 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
963 if (*args[4])
964 reqlen += strlen(args[4]);
965 else
966 reqlen += strlen("HTTP/1.0");
967
968 curproxy->check_req = (char *)malloc(reqlen);
969 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
970 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
971 }
Willy Tarreauf3c69202006-07-09 16:42:34 +0200972 }
973 else if (!strcmp(args[1], "ssl-hello-chk")) {
974 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +0100975 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
976 return 0;
977
Willy Tarreauf3c69202006-07-09 16:42:34 +0200978 if (curproxy->check_req != NULL) {
979 free(curproxy->check_req);
980 }
981 curproxy->options &= ~PR_O_HTTP_CHK;
982 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200983 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200984 else {
985 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
986 return -1;
987 }
988 return 0;
989 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100990 else if (!strcmp(args[0], "default_backend")) {
991 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
992 return 0;
993
994 if (*(args[1]) == 0) {
995 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
996 return -1;
997 }
998 if (curproxy->defbe.name)
999 free(curproxy->defbe.name);
1000 curproxy->defbe.name = strdup(args[1]);
1001 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001003 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1004 return 0;
1005
Willy Tarreaubaaee002006-06-26 02:48:02 +02001006 /* enable reconnections to dispatch */
1007 curproxy->options |= PR_O_REDISP;
1008 }
1009#ifdef TPROXY
1010 else if (!strcmp(args[0], "transparent")) {
1011 /* enable transparent proxy connections */
1012 curproxy->options |= PR_O_TRANSP;
1013 }
1014#endif
1015 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001016 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1017 return 0;
1018
Willy Tarreaubaaee002006-06-26 02:48:02 +02001019 if (*(args[1]) == 0) {
1020 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1021 return -1;
1022 }
1023 curproxy->maxconn = atol(args[1]);
1024 }
Willy Tarreau86034312006-12-29 00:10:33 +01001025 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001026 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1027 return 0;
1028
Willy Tarreau86034312006-12-29 00:10:33 +01001029 if (*(args[1]) == 0) {
1030 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1031 return -1;
1032 }
1033 curproxy->fullconn = atol(args[1]);
1034 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001035 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1036 if (*(args[1]) == 0) {
1037 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1038 return -1;
1039 }
1040 curproxy->grace = atol(args[1]);
1041 }
1042 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1043 if (curproxy == &defproxy) {
1044 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1045 return -1;
1046 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001047 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1048 return 0;
1049
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 if (strchr(args[1], ':') == NULL) {
1051 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1052 return -1;
1053 }
1054 curproxy->dispatch_addr = *str2sa(args[1]);
1055 }
1056 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001057 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1058 return 0;
1059
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 if (*(args[1])) {
1061 if (!strcmp(args[1], "roundrobin")) {
1062 curproxy->options |= PR_O_BALANCE_RR;
1063 }
1064 else if (!strcmp(args[1], "source")) {
1065 curproxy->options |= PR_O_BALANCE_SH;
1066 }
1067 else {
1068 Alert("parsing [%s:%d] : '%s' only supports 'roundrobin' and 'source' options.\n", file, linenum, args[0]);
1069 return -1;
1070 }
1071 }
1072 else /* if no option is set, use round-robin by default */
1073 curproxy->options |= PR_O_BALANCE_RR;
1074 }
1075 else if (!strcmp(args[0], "server")) { /* server address */
1076 int cur_arg;
1077 char *rport;
1078 char *raddr;
1079 short realport;
1080 int do_check;
1081
1082 if (curproxy == &defproxy) {
1083 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1084 return -1;
1085 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001086 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1087 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088
1089 if (!*args[2]) {
1090 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1091 file, linenum, args[0]);
1092 return -1;
1093 }
1094 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1095 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1096 return -1;
1097 }
1098
1099 /* the servers are linked backwards first */
1100 newsrv->next = curproxy->srv;
1101 curproxy->srv = newsrv;
1102 newsrv->proxy = curproxy;
1103
1104 LIST_INIT(&newsrv->pendconns);
1105 do_check = 0;
1106 newsrv->state = SRV_RUNNING; /* early server setup */
1107 newsrv->id = strdup(args[1]);
1108
1109 /* several ways to check the port component :
1110 * - IP => port=+0, relative
1111 * - IP: => port=+0, relative
1112 * - IP:N => port=N, absolute
1113 * - IP:+N => port=+N, relative
1114 * - IP:-N => port=-N, relative
1115 */
1116 raddr = strdup(args[2]);
1117 rport = strchr(raddr, ':');
1118 if (rport) {
1119 *rport++ = 0;
1120 realport = atol(rport);
1121 if (!isdigit((int)*rport))
1122 newsrv->state |= SRV_MAPPORTS;
1123 } else {
1124 realport = 0;
1125 newsrv->state |= SRV_MAPPORTS;
1126 }
1127
1128 newsrv->addr = *str2sa(raddr);
1129 newsrv->addr.sin_port = htons(realport);
1130 free(raddr);
1131
1132 newsrv->curfd = -1; /* no health-check in progress */
1133 newsrv->inter = DEF_CHKINTR;
1134 newsrv->rise = DEF_RISETIME;
1135 newsrv->fall = DEF_FALLTIME;
1136 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
1137 cur_arg = 3;
1138 while (*args[cur_arg]) {
1139 if (!strcmp(args[cur_arg], "cookie")) {
1140 newsrv->cookie = strdup(args[cur_arg + 1]);
1141 newsrv->cklen = strlen(args[cur_arg + 1]);
1142 cur_arg += 2;
1143 }
1144 else if (!strcmp(args[cur_arg], "rise")) {
1145 newsrv->rise = atol(args[cur_arg + 1]);
1146 newsrv->health = newsrv->rise;
1147 cur_arg += 2;
1148 }
1149 else if (!strcmp(args[cur_arg], "fall")) {
1150 newsrv->fall = atol(args[cur_arg + 1]);
1151 cur_arg += 2;
1152 }
1153 else if (!strcmp(args[cur_arg], "inter")) {
1154 newsrv->inter = atol(args[cur_arg + 1]);
1155 cur_arg += 2;
1156 }
1157 else if (!strcmp(args[cur_arg], "port")) {
1158 newsrv->check_port = atol(args[cur_arg + 1]);
1159 cur_arg += 2;
1160 }
1161 else if (!strcmp(args[cur_arg], "backup")) {
1162 newsrv->state |= SRV_BACKUP;
1163 cur_arg ++;
1164 }
1165 else if (!strcmp(args[cur_arg], "weight")) {
1166 int w;
1167 w = atol(args[cur_arg + 1]);
1168 if (w < 1 || w > 256) {
1169 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1170 file, linenum, newsrv->id, w);
1171 return -1;
1172 }
1173 newsrv->uweight = w - 1;
1174 cur_arg += 2;
1175 }
1176 else if (!strcmp(args[cur_arg], "minconn")) {
1177 newsrv->minconn = atol(args[cur_arg + 1]);
1178 cur_arg += 2;
1179 }
1180 else if (!strcmp(args[cur_arg], "maxconn")) {
1181 newsrv->maxconn = atol(args[cur_arg + 1]);
1182 cur_arg += 2;
1183 }
1184 else if (!strcmp(args[cur_arg], "check")) {
1185 global.maxsock++;
1186 do_check = 1;
1187 cur_arg += 1;
1188 }
1189 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1190 if (!*args[cur_arg + 1]) {
1191 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1192 file, linenum, "source");
1193 return -1;
1194 }
1195 newsrv->state |= SRV_BIND_SRC;
1196 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1197 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001198#ifdef CONFIG_HAP_CTTPROXY
1199 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
1200 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
1201 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1202 file, linenum, "usesrc");
1203 return -1;
1204 }
1205 if (!*args[cur_arg + 1]) {
1206 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1207 file, linenum, "usesrc");
1208 return -1;
1209 }
1210 if (!strcmp(args[cur_arg + 1], "client")) {
1211 newsrv->state |= SRV_TPROXY_CLI;
1212 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1213 newsrv->state |= SRV_TPROXY_CIP;
1214 } else {
1215 newsrv->state |= SRV_TPROXY_ADDR;
1216 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1217 }
1218 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1219 cur_arg += 2;
1220 }
1221#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001222 }
1223 else {
1224 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'port', 'source', 'minconn', 'maxconn' and 'weight'.\n",
1225 file, linenum, newsrv->id);
1226 return -1;
1227 }
1228 }
1229
1230 if (do_check) {
1231 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1232 newsrv->check_port = realport; /* by default */
1233 if (!newsrv->check_port) {
1234 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1235 file, linenum, newsrv->id);
1236 return -1;
1237 }
1238 newsrv->state |= SRV_CHECKED;
1239 }
1240
1241 if (newsrv->state & SRV_BACKUP)
1242 curproxy->srv_bck++;
1243 else
1244 curproxy->srv_act++;
1245 }
1246 else if (!strcmp(args[0], "log")) { /* syslog server address */
1247 struct sockaddr_in *sa;
1248 int facility;
1249
1250 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1251 curproxy->logfac1 = global.logfac1;
1252 curproxy->logsrv1 = global.logsrv1;
1253 curproxy->loglev1 = global.loglev1;
1254 curproxy->logfac2 = global.logfac2;
1255 curproxy->logsrv2 = global.logsrv2;
1256 curproxy->loglev2 = global.loglev2;
1257 }
1258 else if (*(args[1]) && *(args[2])) {
1259 int level;
1260
1261 facility = get_log_facility(args[2]);
1262 if (facility < 0) {
1263 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1264 exit(1);
1265 }
1266
1267 level = 7; /* max syslog level = debug */
1268 if (*(args[3])) {
1269 level = get_log_level(args[3]);
1270 if (level < 0) {
1271 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1272 exit(1);
1273 }
1274 }
1275
1276 sa = str2sa(args[1]);
1277 if (!sa->sin_port)
1278 sa->sin_port = htons(SYSLOG_PORT);
1279
1280 if (curproxy->logfac1 == -1) {
1281 curproxy->logsrv1 = *sa;
1282 curproxy->logfac1 = facility;
1283 curproxy->loglev1 = level;
1284 }
1285 else if (curproxy->logfac2 == -1) {
1286 curproxy->logsrv2 = *sa;
1287 curproxy->logfac2 = facility;
1288 curproxy->loglev2 = level;
1289 }
1290 else {
1291 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1292 return -1;
1293 }
1294 }
1295 else {
1296 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1297 file, linenum);
1298 return -1;
1299 }
1300 }
1301 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001302 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1303 return 0;
1304
Willy Tarreaubaaee002006-06-26 02:48:02 +02001305 if (!*args[1]) {
1306 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1307 file, linenum, "source");
1308 return -1;
1309 }
1310
1311 curproxy->source_addr = *str2sa(args[1]);
1312 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001313#ifdef CONFIG_HAP_CTTPROXY
1314 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
1315 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1316 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1317 file, linenum, "usesrc");
1318 return -1;
1319 }
1320 if (!*args[3]) {
1321 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1322 file, linenum, "usesrc");
1323 return -1;
1324 }
1325
1326 if (!strcmp(args[3], "client")) {
1327 curproxy->options |= PR_O_TPXY_CLI;
1328 } else if (!strcmp(args[3], "clientip")) {
1329 curproxy->options |= PR_O_TPXY_CIP;
1330 } else {
1331 curproxy->options |= PR_O_TPXY_ADDR;
1332 curproxy->tproxy_addr = *str2sa(args[3]);
1333 }
1334 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1335 }
1336#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001337 }
1338 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1339 regex_t *preg;
1340 if (curproxy == &defproxy) {
1341 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1342 return -1;
1343 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001344 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1345 return 0;
1346
Willy Tarreaubaaee002006-06-26 02:48:02 +02001347 if (*(args[1]) == 0 || *(args[2]) == 0) {
1348 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1349 file, linenum, args[0]);
1350 return -1;
1351 }
1352
1353 preg = calloc(1, sizeof(regex_t));
1354 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1355 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1356 return -1;
1357 }
1358
1359 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1360 if (err) {
1361 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1362 file, linenum, *err);
1363 return -1;
1364 }
1365 }
1366 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1367 regex_t *preg;
1368 if (curproxy == &defproxy) {
1369 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1370 return -1;
1371 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001372 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1373 return 0;
1374
Willy Tarreaubaaee002006-06-26 02:48:02 +02001375 if (*(args[1]) == 0) {
1376 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1377 return -1;
1378 }
1379
1380 preg = calloc(1, sizeof(regex_t));
1381 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1382 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1383 return -1;
1384 }
1385
1386 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1387 }
1388 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1389 regex_t *preg;
1390 if (curproxy == &defproxy) {
1391 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1392 return -1;
1393 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001394 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1395 return 0;
1396
Willy Tarreaubaaee002006-06-26 02:48:02 +02001397 if (*(args[1]) == 0) {
1398 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1399 return -1;
1400 }
1401
1402 preg = calloc(1, sizeof(regex_t));
1403 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1404 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1405 return -1;
1406 }
1407
1408 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1409 }
1410 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1411 regex_t *preg;
1412 if (curproxy == &defproxy) {
1413 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1414 return -1;
1415 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001416 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1417 return 0;
1418
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419 if (*(args[1]) == 0) {
1420 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1421 return -1;
1422 }
1423
1424 preg = calloc(1, sizeof(regex_t));
1425 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1426 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1427 return -1;
1428 }
1429
1430 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1431 }
1432 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1433 regex_t *preg;
1434 if (curproxy == &defproxy) {
1435 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1436 return -1;
1437 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001438 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1439 return 0;
1440
Willy Tarreaubaaee002006-06-26 02:48:02 +02001441 if (*(args[1]) == 0) {
1442 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1443 return -1;
1444 }
1445
1446 preg = calloc(1, sizeof(regex_t));
1447 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1448 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1449 return -1;
1450 }
1451
1452 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1453 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001454 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1455 regex_t *preg;
1456 if (curproxy == &defproxy) {
1457 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1458 return -1;
1459 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001460 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1461 return 0;
1462
Willy Tarreaub8750a82006-09-03 09:56:00 +02001463 if (*(args[1]) == 0) {
1464 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1465 return -1;
1466 }
1467
1468 preg = calloc(1, sizeof(regex_t));
1469 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1470 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1471 return -1;
1472 }
1473
1474 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1475 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001476 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1477 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001478 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001479 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1480 return -1;
1481 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001482 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1483 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001484
Willy Tarreau977b8e42006-12-29 14:19:17 +01001485 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001486 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1487 file, linenum, args[0]);
1488 return -1;
1489 }
1490
1491 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001492 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001493 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1494 }
1495
1496 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1497 }
1498 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1499 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001500 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001501 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1502 return -1;
1503 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001504 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1505 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001506
Willy Tarreau977b8e42006-12-29 14:19:17 +01001507 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001508 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1509 file, linenum, args[0]);
1510 return -1;
1511 }
1512
1513 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001514 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001515 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1516 }
1517
1518 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1519 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001520 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1521 regex_t *preg;
1522 if (curproxy == &defproxy) {
1523 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1524 return -1;
1525 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001526 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1527 return 0;
1528
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529 if (*(args[1]) == 0 || *(args[2]) == 0) {
1530 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1531 file, linenum, args[0]);
1532 return -1;
1533 }
1534
1535 preg = calloc(1, sizeof(regex_t));
1536 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1537 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1538 return -1;
1539 }
1540
1541 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1542 if (err) {
1543 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1544 file, linenum, *err);
1545 return -1;
1546 }
1547 }
1548 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1549 regex_t *preg;
1550 if (curproxy == &defproxy) {
1551 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1552 return -1;
1553 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001554 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1555 return 0;
1556
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557 if (*(args[1]) == 0) {
1558 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1559 return -1;
1560 }
1561
1562 preg = calloc(1, sizeof(regex_t));
1563 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1564 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1565 return -1;
1566 }
1567
1568 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1569 }
1570 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1571 regex_t *preg;
1572 if (curproxy == &defproxy) {
1573 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1574 return -1;
1575 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001576 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1577 return 0;
1578
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 if (*(args[1]) == 0) {
1580 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1581 return -1;
1582 }
1583
1584 preg = calloc(1, sizeof(regex_t));
1585 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1586 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1587 return -1;
1588 }
1589
1590 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1591 }
1592 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1593 regex_t *preg;
1594 if (curproxy == &defproxy) {
1595 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1596 return -1;
1597 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001598 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1599 return 0;
1600
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 if (*(args[1]) == 0) {
1602 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1603 return -1;
1604 }
1605
1606 preg = calloc(1, sizeof(regex_t));
1607 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1608 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1609 return -1;
1610 }
1611
1612 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1613 }
1614 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1615 regex_t *preg;
1616 if (curproxy == &defproxy) {
1617 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1618 return -1;
1619 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001620 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1621 return 0;
1622
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 if (*(args[1]) == 0) {
1624 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1625 return -1;
1626 }
1627
1628 preg = calloc(1, sizeof(regex_t));
1629 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1630 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1631 return -1;
1632 }
1633
1634 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1635 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001636 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1637 regex_t *preg;
1638 if (curproxy == &defproxy) {
1639 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1640 return -1;
1641 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001642 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1643 return 0;
1644
Willy Tarreaub8750a82006-09-03 09:56:00 +02001645 if (*(args[1]) == 0) {
1646 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1647 return -1;
1648 }
1649
1650 preg = calloc(1, sizeof(regex_t));
1651 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1652 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1653 return -1;
1654 }
1655
1656 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1659 if (curproxy == &defproxy) {
1660 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1661 return -1;
1662 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001663 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1664 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001665
1666 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
1667 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1668 return 0;
1669 }
1670
1671 if (*(args[1]) == 0) {
1672 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1673 return -1;
1674 }
1675
1676 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
1677 }
1678 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
1679 regex_t *preg;
1680
1681 if (*(args[1]) == 0 || *(args[2]) == 0) {
1682 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1683 file, linenum, args[0]);
1684 return -1;
1685 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001686 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1687 return 0;
1688
Willy Tarreaubaaee002006-06-26 02:48:02 +02001689 preg = calloc(1, sizeof(regex_t));
1690 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1691 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1692 return -1;
1693 }
1694
1695 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1696 if (err) {
1697 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1698 file, linenum, *err);
1699 return -1;
1700 }
1701 }
1702 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
1703 regex_t *preg;
1704 if (curproxy == &defproxy) {
1705 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1706 return -1;
1707 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001708 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1709 return 0;
1710
Willy Tarreaubaaee002006-06-26 02:48:02 +02001711 if (*(args[1]) == 0) {
1712 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1713 return -1;
1714 }
1715
1716 preg = calloc(1, sizeof(regex_t));
1717 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1718 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1719 return -1;
1720 }
1721
1722 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
1723 if (err) {
1724 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1725 file, linenum, *err);
1726 return -1;
1727 }
1728 }
1729 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
1730 regex_t *preg;
1731 if (curproxy == &defproxy) {
1732 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1733 return -1;
1734 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001735 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1736 return 0;
1737
Willy Tarreaubaaee002006-06-26 02:48:02 +02001738 if (*(args[1]) == 0) {
1739 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1740 return -1;
1741 }
1742
1743 preg = calloc(1, sizeof(regex_t));
1744 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1745 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1746 return -1;
1747 }
1748
1749 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
1750 if (err) {
1751 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1752 file, linenum, *err);
1753 return -1;
1754 }
1755 }
1756 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
1757 regex_t *preg;
1758 if (curproxy == &defproxy) {
1759 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1760 return -1;
1761 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001762 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1763 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001764
1765 if (*(args[1]) == 0 || *(args[2]) == 0) {
1766 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1767 file, linenum, args[0]);
1768 return -1;
1769 }
1770
1771 preg = calloc(1, sizeof(regex_t));
1772 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1773 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1774 return -1;
1775 }
1776
1777 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1778 if (err) {
1779 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1780 file, linenum, *err);
1781 return -1;
1782 }
1783 }
1784 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
1785 regex_t *preg;
1786 if (curproxy == &defproxy) {
1787 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1788 return -1;
1789 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001790 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1791 return 0;
1792
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793 if (*(args[1]) == 0) {
1794 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1795 return -1;
1796 }
1797
1798 preg = calloc(1, sizeof(regex_t));
1799 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1800 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1801 return -1;
1802 }
1803
1804 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
1805 if (err) {
1806 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1807 file, linenum, *err);
1808 return -1;
1809 }
1810 }
1811 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
1812 regex_t *preg;
1813 if (curproxy == &defproxy) {
1814 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1815 return -1;
1816 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001817 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1818 return 0;
1819
Willy Tarreaubaaee002006-06-26 02:48:02 +02001820 if (*(args[1]) == 0) {
1821 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1822 return -1;
1823 }
1824
1825 preg = calloc(1, sizeof(regex_t));
1826 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1827 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1828 return -1;
1829 }
1830
1831 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
1832 if (err) {
1833 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1834 file, linenum, *err);
1835 return -1;
1836 }
1837 }
1838 else if (!strcmp(args[0], "rspadd")) { /* add response header */
1839 if (curproxy == &defproxy) {
1840 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1841 return -1;
1842 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001843 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1844 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001845
1846 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
1847 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1848 return 0;
1849 }
1850
1851 if (*(args[1]) == 0) {
1852 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1853 return -1;
1854 }
1855
1856 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
1857 }
1858 else if (!strcmp(args[0], "errorloc") ||
1859 !strcmp(args[0], "errorloc302") ||
1860 !strcmp(args[0], "errorloc303")) { /* error location */
1861 int errnum, errlen;
1862 char *err;
1863
1864 // if (curproxy == &defproxy) {
1865 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1866 // return -1;
1867 // }
1868
Willy Tarreau977b8e42006-12-29 14:19:17 +01001869 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
1870 return 0;
1871
Willy Tarreaubaaee002006-06-26 02:48:02 +02001872 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01001873 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001874 return -1;
1875 }
1876
1877 errnum = atol(args[1]);
1878 if (!strcmp(args[0], "errorloc303")) {
1879 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
1880 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
1881 } else {
1882 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
1883 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
1884 }
1885
Willy Tarreau0f772532006-12-23 20:51:41 +01001886 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
1887 if (http_err_codes[rc] == errnum) {
1888 if (curproxy->errmsg[rc].str)
1889 free(curproxy->errmsg[rc].str);
1890 curproxy->errmsg[rc].str = err;
1891 curproxy->errmsg[rc].len = errlen;
1892 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894 }
Willy Tarreau0f772532006-12-23 20:51:41 +01001895
1896 if (rc >= HTTP_ERR_SIZE) {
1897 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
1898 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001899 free(err);
1900 }
1901 }
1902 else {
1903 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
1904 return -1;
1905 }
1906 return 0;
1907}
1908
1909
1910/*
1911 * This function reads and parses the configuration file given in the argument.
1912 * returns 0 if OK, -1 if error.
1913 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02001914int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915{
1916 char thisline[256];
1917 char *line;
1918 FILE *f;
1919 int linenum = 0;
1920 char *end;
1921 char *args[MAX_LINE_ARGS];
1922 int arg;
1923 int cfgerr = 0;
Willy Tarreau80587432006-12-24 17:47:20 +01001924 int nbchk, mininter;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 int confsect = CFG_NONE;
1926
1927 struct proxy *curproxy = NULL;
1928 struct server *newsrv = NULL;
1929
1930 if ((f=fopen(file,"r")) == NULL)
1931 return -1;
1932
1933 init_default_instance();
1934
1935 while (fgets(line = thisline, sizeof(thisline), f) != NULL) {
1936 linenum++;
1937
1938 end = line + strlen(line);
1939
1940 /* skip leading spaces */
1941 while (isspace((int)*line))
1942 line++;
1943
1944 arg = 0;
1945 args[arg] = line;
1946
1947 while (*line && arg < MAX_LINE_ARGS) {
1948 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
1949 * C equivalent value. Other combinations left unchanged (eg: \1).
1950 */
1951 if (*line == '\\') {
1952 int skip = 0;
1953 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
1954 *line = line[1];
1955 skip = 1;
1956 }
1957 else if (line[1] == 'r') {
1958 *line = '\r';
1959 skip = 1;
1960 }
1961 else if (line[1] == 'n') {
1962 *line = '\n';
1963 skip = 1;
1964 }
1965 else if (line[1] == 't') {
1966 *line = '\t';
1967 skip = 1;
1968 }
1969 else if (line[1] == 'x') {
1970 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
1971 unsigned char hex1, hex2;
1972 hex1 = toupper(line[2]) - '0';
1973 hex2 = toupper(line[3]) - '0';
1974 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
1975 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
1976 *line = (hex1<<4) + hex2;
1977 skip = 3;
1978 }
1979 else {
1980 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
1981 return -1;
1982 }
1983 }
1984 if (skip) {
1985 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
1986 end -= skip;
1987 }
1988 line++;
1989 }
1990 else if (*line == '#' || *line == '\n' || *line == '\r') {
1991 /* end of string, end of loop */
1992 *line = 0;
1993 break;
1994 }
1995 else if (isspace((int)*line)) {
1996 /* a non-escaped space is an argument separator */
1997 *line++ = 0;
1998 while (isspace((int)*line))
1999 line++;
2000 args[++arg] = line;
2001 }
2002 else {
2003 line++;
2004 }
2005 }
2006
2007 /* empty line */
2008 if (!**args)
2009 continue;
2010
2011 /* zero out remaining args */
2012 while (++arg < MAX_LINE_ARGS) {
2013 args[arg] = line;
2014 }
2015
Willy Tarreau977b8e42006-12-29 14:19:17 +01002016 if (!strcmp(args[0], "listen") ||
2017 !strcmp(args[0], "frontend") ||
2018 !strcmp(args[0], "backend") ||
2019 !strcmp(args[0], "ruleset") ||
2020 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002021 confsect = CFG_LISTEN;
2022 else if (!strcmp(args[0], "global")) /* global config */
2023 confsect = CFG_GLOBAL;
2024 /* else it's a section keyword */
2025
2026 switch (confsect) {
2027 case CFG_LISTEN:
2028 if (cfg_parse_listen(file, linenum, args) < 0)
2029 return -1;
2030 break;
2031 case CFG_GLOBAL:
2032 if (cfg_parse_global(file, linenum, args) < 0)
2033 return -1;
2034 break;
2035 default:
2036 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2037 return -1;
2038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002039 }
2040 fclose(f);
2041
2042 /*
2043 * Now, check for the integrity of all that we have collected.
2044 */
2045
2046 /* will be needed further to delay some tasks */
2047 tv_now(&now);
2048
2049 if ((curproxy = proxy) == NULL) {
2050 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2051 file);
2052 return -1;
2053 }
2054
2055 while (curproxy != NULL) {
Willy Tarreau97a738f2006-12-17 18:02:30 +01002056 curproxy->fiprm = curproxy->beprm = curproxy;
2057
Willy Tarreaubaaee002006-06-26 02:48:02 +02002058 if (curproxy->state == PR_STSTOPPED) {
2059 curproxy = curproxy->next;
2060 continue;
2061 }
2062
Willy Tarreau977b8e42006-12-29 14:19:17 +01002063 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2064 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 +01002065 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066 cfgerr++;
2067 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002068 else if (curproxy->cap & PR_CAP_BE &&
2069 ((curproxy->mode != PR_MODE_HEALTH) &&
2070 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
2071 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2072 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 +01002073 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 cfgerr++;
2075 }
2076 else if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
2077 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002078 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002079 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002080 cfgerr++;
2081 }
2082#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2083 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002084 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002085 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002086 cfgerr++;
2087 }
2088#endif
2089 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002090 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002091 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002092 }
2093 }
2094 else if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2095 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002096 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002097 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002098 }
2099 if ((newsrv = curproxy->srv) != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002100 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002101 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002102 }
2103 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002104 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002105 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 }
2107 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002108 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002109 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002110 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002111 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002112 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002113 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002114 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002115 }
2116 else if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
2117 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2118 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2119 file, curproxy->id);
2120 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002121 }
2122 }
2123
2124 /* if a default backend was specified, let's find it */
2125 if (curproxy->defbe.name) {
2126 struct proxy *target;
2127
2128 for (target = proxy; target != NULL; target = target->next) {
2129 if (strcmp(target->id, curproxy->defbe.name) == 0)
2130 break;
2131 }
2132 if (target == NULL) {
2133 Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n",
2134 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2135 cfgerr++;
2136 } else if (target == curproxy) {
2137 Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
2138 cfgerr++;
2139 } else if (!(target->cap & PR_CAP_BE)) {
2140 Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n",
2141 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2142 cfgerr++;
2143 } else if (target->mode != curproxy->mode) {
2144 Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
2145 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2146 cfgerr++;
2147 } else {
2148 free(curproxy->defbe.name);
2149 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002150 }
2151 }
2152
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002153 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002154 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2155 /* map jump target for ACT_SETBE in req_rep chain */
2156 struct hdr_exp *exp;
2157 struct proxy *target;
2158 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
2159 if (exp->action != ACT_SETBE)
2160 continue;
2161 for (target = proxy; target != NULL; target = target->next) {
2162 if (strcmp(target->id, exp->replace) == 0)
2163 break;
2164 }
2165 if (target == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002166 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002167 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaua496b602006-12-17 23:15:24 +01002168 cfgerr++;
2169 } else if (target == curproxy) {
2170 Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
2171 cfgerr++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002172 } else if (!(target->cap & PR_CAP_BE)) {
2173 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002174 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002175 cfgerr++;
2176 } else if (target->mode != PR_MODE_HTTP) {
2177 Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002178 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002179 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002180 } else {
2181 free((void *)exp->replace);
2182 exp->replace = (const char *)target;
2183 }
2184 }
2185 }
Willy Tarreau2738a142006-07-08 17:28:09 +02002186 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002187 (((curproxy->cap & PR_CAP_FE) && !curproxy->clitimeout) ||
2188 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) && (!curproxy->contimeout || !curproxy->srvtimeout)))) {
2189 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002190 " | While not properly invalid, you will certainly encounter various problems\n"
2191 " | with such a configuration. To fix this, please ensure that all following\n"
2192 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002193 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002194 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002195
2196 if (curproxy->options & PR_O_SSL3_CHK) {
2197 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2198 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2199 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2200 }
2201
Willy Tarreau86034312006-12-29 00:10:33 +01002202 /* for backwards compatibility with "listen" instances, if
2203 * fullconn is not set but maxconn is set, then maxconn
2204 * is used.
2205 */
2206 if (!curproxy->fullconn)
2207 curproxy->fullconn = curproxy->maxconn;
2208
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 /* first, we will invert the servers list order */
2210 newsrv = NULL;
2211 while (curproxy->srv) {
2212 struct server *next;
2213
2214 next = curproxy->srv->next;
2215 curproxy->srv->next = newsrv;
2216 newsrv = curproxy->srv;
2217 if (!next)
2218 break;
2219 curproxy->srv = next;
2220 }
2221
2222 /* now, newsrv == curproxy->srv */
2223 if (newsrv) {
2224 struct server *srv;
2225 int pgcd;
2226 int act, bck;
2227
2228 /* We will factor the weights to reduce the table,
2229 * using Euclide's largest common divisor algorithm
2230 */
2231 pgcd = newsrv->uweight + 1;
2232 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2233 int t, w;
2234
2235 w = srv->uweight + 1;
2236 while (w) {
2237 t = pgcd % w;
2238 pgcd = w;
2239 w = t;
2240 }
2241 }
2242
2243 act = bck = 0;
2244 for (srv = newsrv; srv; srv = srv->next) {
2245 srv->eweight = ((srv->uweight + 1) / pgcd) - 1;
2246 if (srv->state & SRV_BACKUP)
2247 bck += srv->eweight + 1;
2248 else
2249 act += srv->eweight + 1;
2250 }
2251
2252 /* this is the largest map we will ever need for this servers list */
2253 if (act < bck)
2254 act = bck;
2255
2256 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2257 /* recounts servers and their weights */
2258 recount_servers(curproxy);
2259 recalc_server_map(curproxy);
2260 }
2261
2262 if (curproxy->options & PR_O_LOGASAP)
2263 curproxy->to_log &= ~LW_BYTES;
2264
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 /*
2266 * If this server supports a maxconn parameter, it needs a dedicated
2267 * tasks to fill the emptied slots when a connection leaves.
2268 */
2269 newsrv = curproxy->srv;
2270 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002271 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 /* Only 'minconn' was specified, or it was higher than or equal
2273 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2274 * this will avoid further useless expensive computations.
2275 */
2276 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002277 } else if (newsrv->maxconn && !newsrv->minconn) {
2278 /* minconn was not specified, so we set it to maxconn */
2279 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002280 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2281 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002282 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002283 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284 }
2285
2286 if (newsrv->maxconn > 0) {
2287 struct task *t;
2288
2289 if ((t = pool_alloc(task)) == NULL) {
2290 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2291 return -1;
2292 }
2293
2294 t->next = t->prev = t->rqnext = NULL; /* task not in run queue yet */
2295 t->wq = LIST_HEAD(wait_queue[1]); /* already assigned to the eternity queue */
2296 t->state = TASK_IDLE;
2297 t->process = process_srv_queue;
2298 t->context = newsrv;
2299 newsrv->queue_mgt = t;
2300
2301 /* never run it unless specifically woken up */
2302 tv_eternity(&t->expire);
2303 task_queue(t);
2304 }
2305 newsrv = newsrv->next;
2306 }
2307
2308 /* now we'll start this proxy's health checks if any */
2309 /* 1- count the checkers to run simultaneously */
2310 nbchk = 0;
2311 mininter = 0;
2312 newsrv = curproxy->srv;
2313 while (newsrv != NULL) {
2314 if (newsrv->state & SRV_CHECKED) {
2315 if (!mininter || mininter > newsrv->inter)
2316 mininter = newsrv->inter;
2317 nbchk++;
2318 }
2319 newsrv = newsrv->next;
2320 }
2321
2322 /* 2- start them as far as possible from each others while respecting
2323 * their own intervals. For this, we will start them after their own
2324 * interval added to the min interval divided by the number of servers,
2325 * weighted by the server's position in the list.
2326 */
2327 if (nbchk > 0) {
2328 struct task *t;
2329 int srvpos;
2330
2331 newsrv = curproxy->srv;
2332 srvpos = 0;
2333 while (newsrv != NULL) {
2334 /* should this server be checked ? */
2335 if (newsrv->state & SRV_CHECKED) {
2336 if ((t = pool_alloc(task)) == NULL) {
2337 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2338 return -1;
2339 }
2340
2341 t->next = t->prev = t->rqnext = NULL; /* task not in run queue yet */
2342 t->wq = LIST_HEAD(wait_queue[0]); /* but already has a wait queue assigned */
2343 t->state = TASK_IDLE;
2344 t->process = process_chk;
2345 t->context = newsrv;
2346
2347 /* check this every ms */
2348 tv_delayfrom(&t->expire, &now,
2349 newsrv->inter + mininter * srvpos / nbchk);
2350 task_queue(t);
2351 //task_wakeup(&rq, t);
2352 srvpos++;
2353 }
2354 newsrv = newsrv->next;
2355 }
2356 }
2357
2358 curproxy = curproxy->next;
2359 }
2360 if (cfgerr > 0) {
2361 Alert("Errors found in configuration file, aborting.\n");
2362 return -1;
2363 }
2364 else
2365 return 0;
2366}
2367
2368
2369
2370/*
2371 * Local variables:
2372 * c-indent-level: 8
2373 * c-basic-offset: 8
2374 * End:
2375 */