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