blob: b385781b39ff50a5932b4166a445d9d4914534bf [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
604 curproxy->monitor_uri_len = strlen(args[1]) + 2; /* include leading and trailing spaces */
605 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
606 memcpy(curproxy->monitor_uri + 1, args[1], curproxy->monitor_uri_len - 2);
607 curproxy->monitor_uri[curproxy->monitor_uri_len-1] = curproxy->monitor_uri[0] = ' ';
608 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
609
610 return 0;
611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
613 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
614 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
615 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
616 else {
617 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
618 return -1;
619 }
620 }
621 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
622 curproxy->state = PR_STSTOPPED;
623 }
624 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
625 curproxy->state = PR_STNEW;
626 }
627 else if (!strcmp(args[0], "cookie")) { /* cookie name */
628 int cur_arg;
629 // if (curproxy == &defproxy) {
630 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
631 // return -1;
632 // }
633
Willy Tarreau977b8e42006-12-29 14:19:17 +0100634 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
635 return 0;
636
Willy Tarreaubaaee002006-06-26 02:48:02 +0200637 if (curproxy->cookie_name != NULL) {
638 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
639 // file, linenum);
640 // return 0;
641 free(curproxy->cookie_name);
642 }
643
644 if (*(args[1]) == 0) {
645 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
646 file, linenum, args[0]);
647 return -1;
648 }
649 curproxy->cookie_name = strdup(args[1]);
650 curproxy->cookie_len = strlen(curproxy->cookie_name);
651
652 cur_arg = 2;
653 while (*(args[cur_arg])) {
654 if (!strcmp(args[cur_arg], "rewrite")) {
655 curproxy->options |= PR_O_COOK_RW;
656 }
657 else if (!strcmp(args[cur_arg], "indirect")) {
658 curproxy->options |= PR_O_COOK_IND;
659 }
660 else if (!strcmp(args[cur_arg], "insert")) {
661 curproxy->options |= PR_O_COOK_INS;
662 }
663 else if (!strcmp(args[cur_arg], "nocache")) {
664 curproxy->options |= PR_O_COOK_NOC;
665 }
666 else if (!strcmp(args[cur_arg], "postonly")) {
667 curproxy->options |= PR_O_COOK_POST;
668 }
669 else if (!strcmp(args[cur_arg], "prefix")) {
670 curproxy->options |= PR_O_COOK_PFX;
671 }
672 else {
673 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
674 file, linenum, args[0]);
675 return -1;
676 }
677 cur_arg++;
678 }
679 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
680 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
681 file, linenum);
682 return -1;
683 }
684
685 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
686 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
687 file, linenum);
688 return -1;
689 }
690 }/* end else if (!strcmp(args[0], "cookie")) */
691 else if (!strcmp(args[0], "appsession")) { /* cookie name */
692 // if (curproxy == &defproxy) {
693 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
694 // return -1;
695 // }
696
Willy Tarreau977b8e42006-12-29 14:19:17 +0100697 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
698 return 0;
699
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700 if (curproxy->appsession_name != NULL) {
701 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
702 // file, linenum);
703 // return 0;
704 free(curproxy->appsession_name);
705 }
706
707 if (*(args[5]) == 0) {
708 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
709 file, linenum, args[0]);
710 return -1;
711 }
712 have_appsession = 1;
713 curproxy->appsession_name = strdup(args[1]);
714 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
715 curproxy->appsession_len = atoi(args[3]);
716 curproxy->appsession_timeout = atoi(args[5]);
717 rc = chtbl_init(&(curproxy->htbl_proxy), TBLSIZ, hashpjw, match_str, destroy);
718 if (rc) {
719 Alert("Error Init Appsession Hashtable.\n");
720 return -1;
721 }
722 } /* Url App Session */
723 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100724 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
725 return 0;
726
Willy Tarreaubaaee002006-06-26 02:48:02 +0200727 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
728 // if (curproxy == &defproxy) {
729 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
730 // return -1;
731 // }
732
733 if (curproxy->capture_name != NULL) {
734 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
735 // file, linenum, args[0]);
736 // return 0;
737 free(curproxy->capture_name);
738 }
739
740 if (*(args[4]) == 0) {
741 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
742 file, linenum, args[0]);
743 return -1;
744 }
745 curproxy->capture_name = strdup(args[2]);
746 curproxy->capture_namelen = strlen(curproxy->capture_name);
747 curproxy->capture_len = atol(args[4]);
748 if (curproxy->capture_len >= CAPTURE_LEN) {
749 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
750 file, linenum, CAPTURE_LEN - 1);
751 curproxy->capture_len = CAPTURE_LEN - 1;
752 }
753 curproxy->to_log |= LW_COOKIE;
754 }
755 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
756 struct cap_hdr *hdr;
757
758 if (curproxy == &defproxy) {
759 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
760 return -1;
761 }
762
763 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
764 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
765 file, linenum, args[0], args[1]);
766 return -1;
767 }
768
769 hdr = calloc(sizeof(struct cap_hdr), 1);
770 hdr->next = curproxy->req_cap;
771 hdr->name = strdup(args[3]);
772 hdr->namelen = strlen(args[3]);
773 hdr->len = atol(args[5]);
774 hdr->index = curproxy->nb_req_cap++;
775 curproxy->req_cap = hdr;
776 curproxy->to_log |= LW_REQHDR;
777 }
778 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
779 struct cap_hdr *hdr;
780
781 if (curproxy == &defproxy) {
782 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
783 return -1;
784 }
785
786 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
787 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
788 file, linenum, args[0], args[1]);
789 return -1;
790 }
791 hdr = calloc(sizeof(struct cap_hdr), 1);
792 hdr->next = curproxy->rsp_cap;
793 hdr->name = strdup(args[3]);
794 hdr->namelen = strlen(args[3]);
795 hdr->len = atol(args[5]);
796 hdr->index = curproxy->nb_rsp_cap++;
797 curproxy->rsp_cap = hdr;
798 curproxy->to_log |= LW_RSPHDR;
799 }
800 else {
801 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
802 file, linenum, args[0]);
803 return -1;
804 }
805 }
806 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
807 if (curproxy->contimeout != defproxy.contimeout) {
808 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
809 return 0;
810 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100811 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
812 return 0;
813
Willy Tarreaubaaee002006-06-26 02:48:02 +0200814 if (*(args[1]) == 0) {
815 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
816 file, linenum, args[0]);
817 return -1;
818 }
819 curproxy->contimeout = atol(args[1]);
820 }
821 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
822 if (curproxy->clitimeout != defproxy.clitimeout) {
823 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
824 file, linenum, args[0]);
825 return 0;
826 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100827 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
828 return 0;
829
Willy Tarreaubaaee002006-06-26 02:48:02 +0200830 if (*(args[1]) == 0) {
831 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
832 file, linenum, args[0]);
833 return -1;
834 }
835 curproxy->clitimeout = atol(args[1]);
836 }
837 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
838 if (curproxy->srvtimeout != defproxy.srvtimeout) {
839 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
840 return 0;
841 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100842 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
843 return 0;
844
Willy Tarreaubaaee002006-06-26 02:48:02 +0200845 if (*(args[1]) == 0) {
846 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
847 file, linenum, args[0]);
848 return -1;
849 }
850 curproxy->srvtimeout = atol(args[1]);
851 }
852 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100853 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
854 return 0;
855
Willy Tarreaubaaee002006-06-26 02:48:02 +0200856 if (*(args[1]) == 0) {
857 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
858 file, linenum, args[0]);
859 return -1;
860 }
861 curproxy->conn_retries = atol(args[1]);
862 }
863 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100864 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
865 return 0;
866
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
868 curproxy->uri_auth = NULL; /* we must detach from the default config */
869
870 if (*(args[1]) == 0) {
871 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
872 return -1;
873 } else if (!strcmp(args[1], "uri")) {
874 if (*(args[2]) == 0) {
875 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
876 return -1;
877 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
878 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
879 return -1;
880 }
881 } else if (!strcmp(args[1], "realm")) {
882 if (*(args[2]) == 0) {
883 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
884 return -1;
885 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
886 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
887 return -1;
888 }
889 } else if (!strcmp(args[1], "auth")) {
890 if (*(args[2]) == 0) {
891 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
892 return -1;
893 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
894 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
895 return -1;
896 }
897 } else if (!strcmp(args[1], "scope")) {
898 if (*(args[2]) == 0) {
899 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
900 return -1;
901 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
902 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
903 return -1;
904 }
905 } else if (!strcmp(args[1], "enable")) {
906 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
907 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
908 return -1;
909 }
910 } else {
911 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'uri', 'realm', 'auth' or 'enable').\n",
912 file, linenum, args[0]);
913 return -1;
914 }
915 }
916 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100917 int optnum;
918
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 if (*(args[1]) == 0) {
920 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
921 return -1;
922 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100923
924 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
925 if (!strcmp(args[1], cfg_opts[optnum].name)) {
926 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
927 return 0;
928 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100929 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +0100930 return 0;
931 }
932 }
933
934 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 /* generate a complete HTTP log */
936 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
937 else if (!strcmp(args[1], "tcplog"))
938 /* generate a detailed TCP log */
939 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940 else if (!strcmp(args[1], "tcpka")) {
941 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +0100942 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
943 return 0;
944
945 if (curproxy->cap & PR_CAP_FE)
946 curproxy->options |= PR_O_TCP_CLI_KA;
947 if (curproxy->cap & PR_CAP_BE)
948 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949 }
950 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100951 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
952 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953 /* use HTTP request to check servers' health */
954 if (curproxy->check_req != NULL) {
955 free(curproxy->check_req);
956 }
957 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +0200958 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 if (!*args[2]) { /* no argument */
960 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
961 curproxy->check_len = strlen(DEF_CHECK_REQ);
962 } else if (!*args[3]) { /* one argument : URI */
963 int reqlen = strlen(args[2]) + strlen("OPTIONS / HTTP/1.0\r\n\r\n");
964 curproxy->check_req = (char *)malloc(reqlen);
965 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
966 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
967 } else { /* more arguments : METHOD URI [HTTP_VER] */
968 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
969 if (*args[4])
970 reqlen += strlen(args[4]);
971 else
972 reqlen += strlen("HTTP/1.0");
973
974 curproxy->check_req = (char *)malloc(reqlen);
975 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
976 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
977 }
Willy Tarreauf3c69202006-07-09 16:42:34 +0200978 }
979 else if (!strcmp(args[1], "ssl-hello-chk")) {
980 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +0100981 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
982 return 0;
983
Willy Tarreauf3c69202006-07-09 16:42:34 +0200984 if (curproxy->check_req != NULL) {
985 free(curproxy->check_req);
986 }
987 curproxy->options &= ~PR_O_HTTP_CHK;
988 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200989 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200990 else {
991 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
992 return -1;
993 }
994 return 0;
995 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100996 else if (!strcmp(args[0], "default_backend")) {
997 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
998 return 0;
999
1000 if (*(args[1]) == 0) {
1001 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1002 return -1;
1003 }
1004 if (curproxy->defbe.name)
1005 free(curproxy->defbe.name);
1006 curproxy->defbe.name = strdup(args[1]);
1007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001008 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001009 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1010 return 0;
1011
Willy Tarreaubaaee002006-06-26 02:48:02 +02001012 /* enable reconnections to dispatch */
1013 curproxy->options |= PR_O_REDISP;
1014 }
1015#ifdef TPROXY
1016 else if (!strcmp(args[0], "transparent")) {
1017 /* enable transparent proxy connections */
1018 curproxy->options |= PR_O_TRANSP;
1019 }
1020#endif
1021 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001022 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1023 return 0;
1024
Willy Tarreaubaaee002006-06-26 02:48:02 +02001025 if (*(args[1]) == 0) {
1026 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1027 return -1;
1028 }
1029 curproxy->maxconn = atol(args[1]);
1030 }
Willy Tarreau86034312006-12-29 00:10:33 +01001031 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001032 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1033 return 0;
1034
Willy Tarreau86034312006-12-29 00:10:33 +01001035 if (*(args[1]) == 0) {
1036 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1037 return -1;
1038 }
1039 curproxy->fullconn = atol(args[1]);
1040 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001041 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1042 if (*(args[1]) == 0) {
1043 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1044 return -1;
1045 }
1046 curproxy->grace = atol(args[1]);
1047 }
1048 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1049 if (curproxy == &defproxy) {
1050 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1051 return -1;
1052 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001053 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1054 return 0;
1055
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 if (strchr(args[1], ':') == NULL) {
1057 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1058 return -1;
1059 }
1060 curproxy->dispatch_addr = *str2sa(args[1]);
1061 }
1062 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001063 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1064 return 0;
1065
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066 if (*(args[1])) {
1067 if (!strcmp(args[1], "roundrobin")) {
1068 curproxy->options |= PR_O_BALANCE_RR;
1069 }
1070 else if (!strcmp(args[1], "source")) {
1071 curproxy->options |= PR_O_BALANCE_SH;
1072 }
1073 else {
1074 Alert("parsing [%s:%d] : '%s' only supports 'roundrobin' and 'source' options.\n", file, linenum, args[0]);
1075 return -1;
1076 }
1077 }
1078 else /* if no option is set, use round-robin by default */
1079 curproxy->options |= PR_O_BALANCE_RR;
1080 }
1081 else if (!strcmp(args[0], "server")) { /* server address */
1082 int cur_arg;
1083 char *rport;
1084 char *raddr;
1085 short realport;
1086 int do_check;
1087
1088 if (curproxy == &defproxy) {
1089 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1090 return -1;
1091 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001092 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1093 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094
1095 if (!*args[2]) {
1096 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1097 file, linenum, args[0]);
1098 return -1;
1099 }
1100 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1101 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1102 return -1;
1103 }
1104
1105 /* the servers are linked backwards first */
1106 newsrv->next = curproxy->srv;
1107 curproxy->srv = newsrv;
1108 newsrv->proxy = curproxy;
1109
1110 LIST_INIT(&newsrv->pendconns);
1111 do_check = 0;
1112 newsrv->state = SRV_RUNNING; /* early server setup */
1113 newsrv->id = strdup(args[1]);
1114
1115 /* several ways to check the port component :
1116 * - IP => port=+0, relative
1117 * - IP: => port=+0, relative
1118 * - IP:N => port=N, absolute
1119 * - IP:+N => port=+N, relative
1120 * - IP:-N => port=-N, relative
1121 */
1122 raddr = strdup(args[2]);
1123 rport = strchr(raddr, ':');
1124 if (rport) {
1125 *rport++ = 0;
1126 realport = atol(rport);
1127 if (!isdigit((int)*rport))
1128 newsrv->state |= SRV_MAPPORTS;
1129 } else {
1130 realport = 0;
1131 newsrv->state |= SRV_MAPPORTS;
1132 }
1133
1134 newsrv->addr = *str2sa(raddr);
1135 newsrv->addr.sin_port = htons(realport);
1136 free(raddr);
1137
1138 newsrv->curfd = -1; /* no health-check in progress */
1139 newsrv->inter = DEF_CHKINTR;
1140 newsrv->rise = DEF_RISETIME;
1141 newsrv->fall = DEF_FALLTIME;
1142 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
1143 cur_arg = 3;
1144 while (*args[cur_arg]) {
1145 if (!strcmp(args[cur_arg], "cookie")) {
1146 newsrv->cookie = strdup(args[cur_arg + 1]);
1147 newsrv->cklen = strlen(args[cur_arg + 1]);
1148 cur_arg += 2;
1149 }
1150 else if (!strcmp(args[cur_arg], "rise")) {
1151 newsrv->rise = atol(args[cur_arg + 1]);
1152 newsrv->health = newsrv->rise;
1153 cur_arg += 2;
1154 }
1155 else if (!strcmp(args[cur_arg], "fall")) {
1156 newsrv->fall = atol(args[cur_arg + 1]);
1157 cur_arg += 2;
1158 }
1159 else if (!strcmp(args[cur_arg], "inter")) {
1160 newsrv->inter = atol(args[cur_arg + 1]);
1161 cur_arg += 2;
1162 }
1163 else if (!strcmp(args[cur_arg], "port")) {
1164 newsrv->check_port = atol(args[cur_arg + 1]);
1165 cur_arg += 2;
1166 }
1167 else if (!strcmp(args[cur_arg], "backup")) {
1168 newsrv->state |= SRV_BACKUP;
1169 cur_arg ++;
1170 }
1171 else if (!strcmp(args[cur_arg], "weight")) {
1172 int w;
1173 w = atol(args[cur_arg + 1]);
1174 if (w < 1 || w > 256) {
1175 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1176 file, linenum, newsrv->id, w);
1177 return -1;
1178 }
1179 newsrv->uweight = w - 1;
1180 cur_arg += 2;
1181 }
1182 else if (!strcmp(args[cur_arg], "minconn")) {
1183 newsrv->minconn = atol(args[cur_arg + 1]);
1184 cur_arg += 2;
1185 }
1186 else if (!strcmp(args[cur_arg], "maxconn")) {
1187 newsrv->maxconn = atol(args[cur_arg + 1]);
1188 cur_arg += 2;
1189 }
1190 else if (!strcmp(args[cur_arg], "check")) {
1191 global.maxsock++;
1192 do_check = 1;
1193 cur_arg += 1;
1194 }
1195 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1196 if (!*args[cur_arg + 1]) {
1197 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1198 file, linenum, "source");
1199 return -1;
1200 }
1201 newsrv->state |= SRV_BIND_SRC;
1202 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1203 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001204#ifdef CONFIG_HAP_CTTPROXY
1205 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
1206 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
1207 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1208 file, linenum, "usesrc");
1209 return -1;
1210 }
1211 if (!*args[cur_arg + 1]) {
1212 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1213 file, linenum, "usesrc");
1214 return -1;
1215 }
1216 if (!strcmp(args[cur_arg + 1], "client")) {
1217 newsrv->state |= SRV_TPROXY_CLI;
1218 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1219 newsrv->state |= SRV_TPROXY_CIP;
1220 } else {
1221 newsrv->state |= SRV_TPROXY_ADDR;
1222 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1223 }
1224 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1225 cur_arg += 2;
1226 }
1227#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 }
1229 else {
1230 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'port', 'source', 'minconn', 'maxconn' and 'weight'.\n",
1231 file, linenum, newsrv->id);
1232 return -1;
1233 }
1234 }
1235
1236 if (do_check) {
1237 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1238 newsrv->check_port = realport; /* by default */
1239 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001240 /* not yet valid, because no port was set on
1241 * the server either. We'll check if we have
1242 * a known port on the first listener.
1243 */
1244 struct listener *l;
1245 l = curproxy->listen;
1246 if (l) {
1247 int port;
1248 port = (l->addr.ss_family == AF_INET6)
1249 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1250 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1251 newsrv->check_port = port;
1252 }
1253 }
1254 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001255 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1256 file, linenum, newsrv->id);
1257 return -1;
1258 }
1259 newsrv->state |= SRV_CHECKED;
1260 }
1261
1262 if (newsrv->state & SRV_BACKUP)
1263 curproxy->srv_bck++;
1264 else
1265 curproxy->srv_act++;
1266 }
1267 else if (!strcmp(args[0], "log")) { /* syslog server address */
1268 struct sockaddr_in *sa;
1269 int facility;
1270
1271 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1272 curproxy->logfac1 = global.logfac1;
1273 curproxy->logsrv1 = global.logsrv1;
1274 curproxy->loglev1 = global.loglev1;
1275 curproxy->logfac2 = global.logfac2;
1276 curproxy->logsrv2 = global.logsrv2;
1277 curproxy->loglev2 = global.loglev2;
1278 }
1279 else if (*(args[1]) && *(args[2])) {
1280 int level;
1281
1282 facility = get_log_facility(args[2]);
1283 if (facility < 0) {
1284 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1285 exit(1);
1286 }
1287
1288 level = 7; /* max syslog level = debug */
1289 if (*(args[3])) {
1290 level = get_log_level(args[3]);
1291 if (level < 0) {
1292 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1293 exit(1);
1294 }
1295 }
1296
1297 sa = str2sa(args[1]);
1298 if (!sa->sin_port)
1299 sa->sin_port = htons(SYSLOG_PORT);
1300
1301 if (curproxy->logfac1 == -1) {
1302 curproxy->logsrv1 = *sa;
1303 curproxy->logfac1 = facility;
1304 curproxy->loglev1 = level;
1305 }
1306 else if (curproxy->logfac2 == -1) {
1307 curproxy->logsrv2 = *sa;
1308 curproxy->logfac2 = facility;
1309 curproxy->loglev2 = level;
1310 }
1311 else {
1312 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1313 return -1;
1314 }
1315 }
1316 else {
1317 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1318 file, linenum);
1319 return -1;
1320 }
1321 }
1322 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001323 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1324 return 0;
1325
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326 if (!*args[1]) {
1327 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1328 file, linenum, "source");
1329 return -1;
1330 }
1331
1332 curproxy->source_addr = *str2sa(args[1]);
1333 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001334#ifdef CONFIG_HAP_CTTPROXY
1335 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
1336 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1337 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1338 file, linenum, "usesrc");
1339 return -1;
1340 }
1341 if (!*args[3]) {
1342 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1343 file, linenum, "usesrc");
1344 return -1;
1345 }
1346
1347 if (!strcmp(args[3], "client")) {
1348 curproxy->options |= PR_O_TPXY_CLI;
1349 } else if (!strcmp(args[3], "clientip")) {
1350 curproxy->options |= PR_O_TPXY_CIP;
1351 } else {
1352 curproxy->options |= PR_O_TPXY_ADDR;
1353 curproxy->tproxy_addr = *str2sa(args[3]);
1354 }
1355 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1356 }
1357#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 }
1359 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1360 regex_t *preg;
1361 if (curproxy == &defproxy) {
1362 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1363 return -1;
1364 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001365 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1366 return 0;
1367
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368 if (*(args[1]) == 0 || *(args[2]) == 0) {
1369 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1370 file, linenum, args[0]);
1371 return -1;
1372 }
1373
1374 preg = calloc(1, sizeof(regex_t));
1375 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1376 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1377 return -1;
1378 }
1379
1380 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1381 if (err) {
1382 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1383 file, linenum, *err);
1384 return -1;
1385 }
1386 }
1387 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1388 regex_t *preg;
1389 if (curproxy == &defproxy) {
1390 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1391 return -1;
1392 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001393 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1394 return 0;
1395
Willy Tarreaubaaee002006-06-26 02:48:02 +02001396 if (*(args[1]) == 0) {
1397 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1398 return -1;
1399 }
1400
1401 preg = calloc(1, sizeof(regex_t));
1402 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1403 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1404 return -1;
1405 }
1406
1407 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1408 }
1409 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1410 regex_t *preg;
1411 if (curproxy == &defproxy) {
1412 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1413 return -1;
1414 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001415 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1416 return 0;
1417
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418 if (*(args[1]) == 0) {
1419 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1420 return -1;
1421 }
1422
1423 preg = calloc(1, sizeof(regex_t));
1424 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1425 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1426 return -1;
1427 }
1428
1429 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1430 }
1431 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1432 regex_t *preg;
1433 if (curproxy == &defproxy) {
1434 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1435 return -1;
1436 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001437 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1438 return 0;
1439
Willy Tarreaubaaee002006-06-26 02:48:02 +02001440 if (*(args[1]) == 0) {
1441 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1442 return -1;
1443 }
1444
1445 preg = calloc(1, sizeof(regex_t));
1446 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1447 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1448 return -1;
1449 }
1450
1451 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1452 }
1453 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1454 regex_t *preg;
1455 if (curproxy == &defproxy) {
1456 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1457 return -1;
1458 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001459 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1460 return 0;
1461
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462 if (*(args[1]) == 0) {
1463 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1464 return -1;
1465 }
1466
1467 preg = calloc(1, sizeof(regex_t));
1468 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1469 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1470 return -1;
1471 }
1472
1473 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1474 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001475 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1476 regex_t *preg;
1477 if (curproxy == &defproxy) {
1478 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1479 return -1;
1480 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001481 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1482 return 0;
1483
Willy Tarreaub8750a82006-09-03 09:56:00 +02001484 if (*(args[1]) == 0) {
1485 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1486 return -1;
1487 }
1488
1489 preg = calloc(1, sizeof(regex_t));
1490 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1491 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1492 return -1;
1493 }
1494
1495 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1496 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001497 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1498 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001499 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001500 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1501 return -1;
1502 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001503 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1504 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001505
Willy Tarreau977b8e42006-12-29 14:19:17 +01001506 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001507 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1508 file, linenum, args[0]);
1509 return -1;
1510 }
1511
1512 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001513 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001514 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1515 }
1516
1517 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1518 }
1519 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1520 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001521 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001522 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1523 return -1;
1524 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001525 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1526 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001527
Willy Tarreau977b8e42006-12-29 14:19:17 +01001528 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001529 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1530 file, linenum, args[0]);
1531 return -1;
1532 }
1533
1534 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001535 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001536 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1537 }
1538
1539 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1540 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001541 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1542 regex_t *preg;
1543 if (curproxy == &defproxy) {
1544 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1545 return -1;
1546 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001547 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1548 return 0;
1549
Willy Tarreaubaaee002006-06-26 02:48:02 +02001550 if (*(args[1]) == 0 || *(args[2]) == 0) {
1551 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1552 file, linenum, args[0]);
1553 return -1;
1554 }
1555
1556 preg = calloc(1, sizeof(regex_t));
1557 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1558 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1559 return -1;
1560 }
1561
1562 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1563 if (err) {
1564 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1565 file, linenum, *err);
1566 return -1;
1567 }
1568 }
1569 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1570 regex_t *preg;
1571 if (curproxy == &defproxy) {
1572 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1573 return -1;
1574 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001575 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1576 return 0;
1577
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 if (*(args[1]) == 0) {
1579 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1580 return -1;
1581 }
1582
1583 preg = calloc(1, sizeof(regex_t));
1584 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1585 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1586 return -1;
1587 }
1588
1589 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1590 }
1591 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1592 regex_t *preg;
1593 if (curproxy == &defproxy) {
1594 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1595 return -1;
1596 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001597 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1598 return 0;
1599
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600 if (*(args[1]) == 0) {
1601 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1602 return -1;
1603 }
1604
1605 preg = calloc(1, sizeof(regex_t));
1606 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1607 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1608 return -1;
1609 }
1610
1611 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1612 }
1613 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1614 regex_t *preg;
1615 if (curproxy == &defproxy) {
1616 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1617 return -1;
1618 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001619 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1620 return 0;
1621
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622 if (*(args[1]) == 0) {
1623 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1624 return -1;
1625 }
1626
1627 preg = calloc(1, sizeof(regex_t));
1628 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1629 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1630 return -1;
1631 }
1632
1633 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1634 }
1635 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1636 regex_t *preg;
1637 if (curproxy == &defproxy) {
1638 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1639 return -1;
1640 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001641 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1642 return 0;
1643
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644 if (*(args[1]) == 0) {
1645 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1646 return -1;
1647 }
1648
1649 preg = calloc(1, sizeof(regex_t));
1650 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1651 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1652 return -1;
1653 }
1654
1655 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1656 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001657 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1658 regex_t *preg;
1659 if (curproxy == &defproxy) {
1660 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1661 return -1;
1662 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001663 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1664 return 0;
1665
Willy Tarreaub8750a82006-09-03 09:56:00 +02001666 if (*(args[1]) == 0) {
1667 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1668 return -1;
1669 }
1670
1671 preg = calloc(1, sizeof(regex_t));
1672 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1673 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1674 return -1;
1675 }
1676
1677 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001679 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1680 if (curproxy == &defproxy) {
1681 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1682 return -1;
1683 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001684 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1685 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686
1687 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
1688 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1689 return 0;
1690 }
1691
1692 if (*(args[1]) == 0) {
1693 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1694 return -1;
1695 }
1696
1697 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
1698 }
1699 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
1700 regex_t *preg;
1701
1702 if (*(args[1]) == 0 || *(args[2]) == 0) {
1703 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1704 file, linenum, args[0]);
1705 return -1;
1706 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001707 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1708 return 0;
1709
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710 preg = calloc(1, sizeof(regex_t));
1711 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1712 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1713 return -1;
1714 }
1715
1716 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1717 if (err) {
1718 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1719 file, linenum, *err);
1720 return -1;
1721 }
1722 }
1723 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
1724 regex_t *preg;
1725 if (curproxy == &defproxy) {
1726 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1727 return -1;
1728 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001729 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1730 return 0;
1731
Willy Tarreaubaaee002006-06-26 02:48:02 +02001732 if (*(args[1]) == 0) {
1733 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1734 return -1;
1735 }
1736
1737 preg = calloc(1, sizeof(regex_t));
1738 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1739 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1740 return -1;
1741 }
1742
1743 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
1744 if (err) {
1745 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1746 file, linenum, *err);
1747 return -1;
1748 }
1749 }
1750 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
1751 regex_t *preg;
1752 if (curproxy == &defproxy) {
1753 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1754 return -1;
1755 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001756 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1757 return 0;
1758
Willy Tarreaubaaee002006-06-26 02:48:02 +02001759 if (*(args[1]) == 0) {
1760 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1761 return -1;
1762 }
1763
1764 preg = calloc(1, sizeof(regex_t));
1765 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1766 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1767 return -1;
1768 }
1769
1770 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
1771 if (err) {
1772 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1773 file, linenum, *err);
1774 return -1;
1775 }
1776 }
1777 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
1778 regex_t *preg;
1779 if (curproxy == &defproxy) {
1780 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1781 return -1;
1782 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001783 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1784 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001785
1786 if (*(args[1]) == 0 || *(args[2]) == 0) {
1787 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1788 file, linenum, args[0]);
1789 return -1;
1790 }
1791
1792 preg = calloc(1, sizeof(regex_t));
1793 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1794 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1795 return -1;
1796 }
1797
1798 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1799 if (err) {
1800 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1801 file, linenum, *err);
1802 return -1;
1803 }
1804 }
1805 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
1806 regex_t *preg;
1807 if (curproxy == &defproxy) {
1808 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1809 return -1;
1810 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001811 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1812 return 0;
1813
Willy Tarreaubaaee002006-06-26 02:48:02 +02001814 if (*(args[1]) == 0) {
1815 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1816 return -1;
1817 }
1818
1819 preg = calloc(1, sizeof(regex_t));
1820 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1821 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1822 return -1;
1823 }
1824
1825 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
1826 if (err) {
1827 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1828 file, linenum, *err);
1829 return -1;
1830 }
1831 }
1832 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
1833 regex_t *preg;
1834 if (curproxy == &defproxy) {
1835 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1836 return -1;
1837 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001838 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1839 return 0;
1840
Willy Tarreaubaaee002006-06-26 02:48:02 +02001841 if (*(args[1]) == 0) {
1842 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1843 return -1;
1844 }
1845
1846 preg = calloc(1, sizeof(regex_t));
1847 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1848 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1849 return -1;
1850 }
1851
1852 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
1853 if (err) {
1854 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1855 file, linenum, *err);
1856 return -1;
1857 }
1858 }
1859 else if (!strcmp(args[0], "rspadd")) { /* add response header */
1860 if (curproxy == &defproxy) {
1861 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1862 return -1;
1863 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001864 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1865 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001866
1867 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
1868 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1869 return 0;
1870 }
1871
1872 if (*(args[1]) == 0) {
1873 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1874 return -1;
1875 }
1876
1877 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
1878 }
1879 else if (!strcmp(args[0], "errorloc") ||
1880 !strcmp(args[0], "errorloc302") ||
1881 !strcmp(args[0], "errorloc303")) { /* error location */
1882 int errnum, errlen;
1883 char *err;
1884
1885 // if (curproxy == &defproxy) {
1886 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1887 // return -1;
1888 // }
1889
Willy Tarreau977b8e42006-12-29 14:19:17 +01001890 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
1891 return 0;
1892
Willy Tarreaubaaee002006-06-26 02:48:02 +02001893 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01001894 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001895 return -1;
1896 }
1897
1898 errnum = atol(args[1]);
1899 if (!strcmp(args[0], "errorloc303")) {
1900 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
1901 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
1902 } else {
1903 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
1904 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
1905 }
1906
Willy Tarreau0f772532006-12-23 20:51:41 +01001907 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
1908 if (http_err_codes[rc] == errnum) {
1909 if (curproxy->errmsg[rc].str)
1910 free(curproxy->errmsg[rc].str);
1911 curproxy->errmsg[rc].str = err;
1912 curproxy->errmsg[rc].len = errlen;
1913 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 }
Willy Tarreau0f772532006-12-23 20:51:41 +01001916
1917 if (rc >= HTTP_ERR_SIZE) {
1918 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
1919 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 free(err);
1921 }
1922 }
1923 else {
1924 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
1925 return -1;
1926 }
1927 return 0;
1928}
1929
1930
1931/*
1932 * This function reads and parses the configuration file given in the argument.
1933 * returns 0 if OK, -1 if error.
1934 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02001935int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936{
1937 char thisline[256];
1938 char *line;
1939 FILE *f;
1940 int linenum = 0;
1941 char *end;
1942 char *args[MAX_LINE_ARGS];
1943 int arg;
1944 int cfgerr = 0;
Willy Tarreau80587432006-12-24 17:47:20 +01001945 int nbchk, mininter;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 int confsect = CFG_NONE;
1947
1948 struct proxy *curproxy = NULL;
1949 struct server *newsrv = NULL;
1950
1951 if ((f=fopen(file,"r")) == NULL)
1952 return -1;
1953
1954 init_default_instance();
1955
1956 while (fgets(line = thisline, sizeof(thisline), f) != NULL) {
1957 linenum++;
1958
1959 end = line + strlen(line);
1960
1961 /* skip leading spaces */
1962 while (isspace((int)*line))
1963 line++;
1964
1965 arg = 0;
1966 args[arg] = line;
1967
1968 while (*line && arg < MAX_LINE_ARGS) {
1969 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
1970 * C equivalent value. Other combinations left unchanged (eg: \1).
1971 */
1972 if (*line == '\\') {
1973 int skip = 0;
1974 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
1975 *line = line[1];
1976 skip = 1;
1977 }
1978 else if (line[1] == 'r') {
1979 *line = '\r';
1980 skip = 1;
1981 }
1982 else if (line[1] == 'n') {
1983 *line = '\n';
1984 skip = 1;
1985 }
1986 else if (line[1] == 't') {
1987 *line = '\t';
1988 skip = 1;
1989 }
1990 else if (line[1] == 'x') {
1991 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
1992 unsigned char hex1, hex2;
1993 hex1 = toupper(line[2]) - '0';
1994 hex2 = toupper(line[3]) - '0';
1995 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
1996 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
1997 *line = (hex1<<4) + hex2;
1998 skip = 3;
1999 }
2000 else {
2001 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2002 return -1;
2003 }
2004 }
2005 if (skip) {
2006 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2007 end -= skip;
2008 }
2009 line++;
2010 }
2011 else if (*line == '#' || *line == '\n' || *line == '\r') {
2012 /* end of string, end of loop */
2013 *line = 0;
2014 break;
2015 }
2016 else if (isspace((int)*line)) {
2017 /* a non-escaped space is an argument separator */
2018 *line++ = 0;
2019 while (isspace((int)*line))
2020 line++;
2021 args[++arg] = line;
2022 }
2023 else {
2024 line++;
2025 }
2026 }
2027
2028 /* empty line */
2029 if (!**args)
2030 continue;
2031
2032 /* zero out remaining args */
2033 while (++arg < MAX_LINE_ARGS) {
2034 args[arg] = line;
2035 }
2036
Willy Tarreau977b8e42006-12-29 14:19:17 +01002037 if (!strcmp(args[0], "listen") ||
2038 !strcmp(args[0], "frontend") ||
2039 !strcmp(args[0], "backend") ||
2040 !strcmp(args[0], "ruleset") ||
2041 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002042 confsect = CFG_LISTEN;
2043 else if (!strcmp(args[0], "global")) /* global config */
2044 confsect = CFG_GLOBAL;
2045 /* else it's a section keyword */
2046
2047 switch (confsect) {
2048 case CFG_LISTEN:
2049 if (cfg_parse_listen(file, linenum, args) < 0)
2050 return -1;
2051 break;
2052 case CFG_GLOBAL:
2053 if (cfg_parse_global(file, linenum, args) < 0)
2054 return -1;
2055 break;
2056 default:
2057 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2058 return -1;
2059 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002060 }
2061 fclose(f);
2062
2063 /*
2064 * Now, check for the integrity of all that we have collected.
2065 */
2066
2067 /* will be needed further to delay some tasks */
2068 tv_now(&now);
2069
2070 if ((curproxy = proxy) == NULL) {
2071 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2072 file);
2073 return -1;
2074 }
2075
2076 while (curproxy != NULL) {
Willy Tarreau97a738f2006-12-17 18:02:30 +01002077 curproxy->fiprm = curproxy->beprm = curproxy;
2078
Willy Tarreaubaaee002006-06-26 02:48:02 +02002079 if (curproxy->state == PR_STSTOPPED) {
2080 curproxy = curproxy->next;
2081 continue;
2082 }
2083
Willy Tarreau977b8e42006-12-29 14:19:17 +01002084 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2085 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 +01002086 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002087 cfgerr++;
2088 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002089 else if (curproxy->cap & PR_CAP_BE &&
2090 ((curproxy->mode != PR_MODE_HEALTH) &&
2091 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
2092 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2093 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 +01002094 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 cfgerr++;
2096 }
2097 else if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
2098 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002099 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002100 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002101 cfgerr++;
2102 }
2103#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2104 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002105 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002106 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002107 cfgerr++;
2108 }
2109#endif
2110 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002111 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002112 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002113 }
2114 }
2115 else if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2116 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002117 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002118 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002119 }
2120 if ((newsrv = curproxy->srv) != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002121 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002122 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002123 }
2124 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002125 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002126 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002127 }
2128 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002129 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002130 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002131 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002132 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002133 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002134 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002136 }
2137 else if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
2138 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2139 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2140 file, curproxy->id);
2141 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002142 }
2143 }
2144
2145 /* if a default backend was specified, let's find it */
2146 if (curproxy->defbe.name) {
2147 struct proxy *target;
2148
2149 for (target = proxy; target != NULL; target = target->next) {
2150 if (strcmp(target->id, curproxy->defbe.name) == 0)
2151 break;
2152 }
2153 if (target == NULL) {
2154 Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n",
2155 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2156 cfgerr++;
2157 } else if (target == curproxy) {
2158 Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
2159 cfgerr++;
2160 } else if (!(target->cap & PR_CAP_BE)) {
2161 Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n",
2162 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2163 cfgerr++;
2164 } else if (target->mode != curproxy->mode) {
2165 Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
2166 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2167 cfgerr++;
2168 } else {
2169 free(curproxy->defbe.name);
2170 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171 }
2172 }
2173
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002174 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002175 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2176 /* map jump target for ACT_SETBE in req_rep chain */
2177 struct hdr_exp *exp;
2178 struct proxy *target;
2179 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
2180 if (exp->action != ACT_SETBE)
2181 continue;
2182 for (target = proxy; target != NULL; target = target->next) {
2183 if (strcmp(target->id, exp->replace) == 0)
2184 break;
2185 }
2186 if (target == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002187 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002188 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaua496b602006-12-17 23:15:24 +01002189 cfgerr++;
2190 } else if (target == curproxy) {
2191 Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
2192 cfgerr++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002193 } else if (!(target->cap & PR_CAP_BE)) {
2194 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002195 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002196 cfgerr++;
2197 } else if (target->mode != PR_MODE_HTTP) {
2198 Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002199 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002200 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002201 } else {
2202 free((void *)exp->replace);
2203 exp->replace = (const char *)target;
2204 }
2205 }
2206 }
Willy Tarreau2738a142006-07-08 17:28:09 +02002207 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau977b8e42006-12-29 14:19:17 +01002208 (((curproxy->cap & PR_CAP_FE) && !curproxy->clitimeout) ||
2209 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) && (!curproxy->contimeout || !curproxy->srvtimeout)))) {
2210 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002211 " | While not properly invalid, you will certainly encounter various problems\n"
2212 " | with such a configuration. To fix this, please ensure that all following\n"
2213 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002214 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002215 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002216
2217 if (curproxy->options & PR_O_SSL3_CHK) {
2218 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2219 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2220 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2221 }
2222
Willy Tarreau86034312006-12-29 00:10:33 +01002223 /* for backwards compatibility with "listen" instances, if
2224 * fullconn is not set but maxconn is set, then maxconn
2225 * is used.
2226 */
2227 if (!curproxy->fullconn)
2228 curproxy->fullconn = curproxy->maxconn;
2229
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230 /* first, we will invert the servers list order */
2231 newsrv = NULL;
2232 while (curproxy->srv) {
2233 struct server *next;
2234
2235 next = curproxy->srv->next;
2236 curproxy->srv->next = newsrv;
2237 newsrv = curproxy->srv;
2238 if (!next)
2239 break;
2240 curproxy->srv = next;
2241 }
2242
2243 /* now, newsrv == curproxy->srv */
2244 if (newsrv) {
2245 struct server *srv;
2246 int pgcd;
2247 int act, bck;
2248
2249 /* We will factor the weights to reduce the table,
2250 * using Euclide's largest common divisor algorithm
2251 */
2252 pgcd = newsrv->uweight + 1;
2253 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2254 int t, w;
2255
2256 w = srv->uweight + 1;
2257 while (w) {
2258 t = pgcd % w;
2259 pgcd = w;
2260 w = t;
2261 }
2262 }
2263
2264 act = bck = 0;
2265 for (srv = newsrv; srv; srv = srv->next) {
2266 srv->eweight = ((srv->uweight + 1) / pgcd) - 1;
2267 if (srv->state & SRV_BACKUP)
2268 bck += srv->eweight + 1;
2269 else
2270 act += srv->eweight + 1;
2271 }
2272
2273 /* this is the largest map we will ever need for this servers list */
2274 if (act < bck)
2275 act = bck;
2276
2277 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2278 /* recounts servers and their weights */
2279 recount_servers(curproxy);
2280 recalc_server_map(curproxy);
2281 }
2282
2283 if (curproxy->options & PR_O_LOGASAP)
2284 curproxy->to_log &= ~LW_BYTES;
2285
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 /*
2287 * If this server supports a maxconn parameter, it needs a dedicated
2288 * tasks to fill the emptied slots when a connection leaves.
2289 */
2290 newsrv = curproxy->srv;
2291 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002292 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002293 /* Only 'minconn' was specified, or it was higher than or equal
2294 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2295 * this will avoid further useless expensive computations.
2296 */
2297 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002298 } else if (newsrv->maxconn && !newsrv->minconn) {
2299 /* minconn was not specified, so we set it to maxconn */
2300 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002301 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2302 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002303 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002304 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002305 }
2306
2307 if (newsrv->maxconn > 0) {
2308 struct task *t;
2309
2310 if ((t = pool_alloc(task)) == NULL) {
2311 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2312 return -1;
2313 }
2314
Willy Tarreau964c9362007-01-07 00:38:00 +01002315 t->rqnext = NULL;
2316 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002317 t->state = TASK_IDLE;
2318 t->process = process_srv_queue;
2319 t->context = newsrv;
2320 newsrv->queue_mgt = t;
2321
2322 /* never run it unless specifically woken up */
2323 tv_eternity(&t->expire);
2324 task_queue(t);
2325 }
2326 newsrv = newsrv->next;
2327 }
2328
2329 /* now we'll start this proxy's health checks if any */
2330 /* 1- count the checkers to run simultaneously */
2331 nbchk = 0;
2332 mininter = 0;
2333 newsrv = curproxy->srv;
2334 while (newsrv != NULL) {
2335 if (newsrv->state & SRV_CHECKED) {
2336 if (!mininter || mininter > newsrv->inter)
2337 mininter = newsrv->inter;
2338 nbchk++;
2339 }
2340 newsrv = newsrv->next;
2341 }
2342
2343 /* 2- start them as far as possible from each others while respecting
2344 * their own intervals. For this, we will start them after their own
2345 * interval added to the min interval divided by the number of servers,
2346 * weighted by the server's position in the list.
2347 */
2348 if (nbchk > 0) {
2349 struct task *t;
2350 int srvpos;
2351
2352 newsrv = curproxy->srv;
2353 srvpos = 0;
2354 while (newsrv != NULL) {
2355 /* should this server be checked ? */
2356 if (newsrv->state & SRV_CHECKED) {
2357 if ((t = pool_alloc(task)) == NULL) {
2358 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2359 return -1;
2360 }
2361
Willy Tarreau964c9362007-01-07 00:38:00 +01002362 t->wq = NULL;
2363 t->rqnext = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 t->state = TASK_IDLE;
2365 t->process = process_chk;
2366 t->context = newsrv;
2367
2368 /* check this every ms */
2369 tv_delayfrom(&t->expire, &now,
2370 newsrv->inter + mininter * srvpos / nbchk);
2371 task_queue(t);
2372 //task_wakeup(&rq, t);
2373 srvpos++;
2374 }
2375 newsrv = newsrv->next;
2376 }
2377 }
2378
2379 curproxy = curproxy->next;
2380 }
2381 if (cfgerr > 0) {
2382 Alert("Errors found in configuration file, aborting.\n");
2383 return -1;
2384 }
2385 else
2386 return 0;
2387}
2388
2389
2390
2391/*
2392 * Local variables:
2393 * c-indent-level: 8
2394 * c-basic-offset: 8
2395 * End:
2396 */