blob: 69f11e0c53b8e4d6bf33453c97c99332e25c5c24 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau0b4ed902007-03-26 00:18:40 +02004 * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020021
Willy Tarreau2dd0d472006-06-29 17:53:05 +020022#include <common/cfgparse.h>
23#include <common/config.h>
24#include <common/memory.h>
25#include <common/standard.h>
26#include <common/time.h>
27#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020028
29#include <types/capture.h>
30#include <types/global.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010031#include <types/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020032#include <types/polling.h>
33#include <types/proxy.h>
34#include <types/queue.h>
35
Willy Tarreaueb0c6142007-05-07 00:53:22 +020036#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010038#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039#include <proto/checks.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010040#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/log.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010042#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/server.h>
44#include <proto/task.h>
45
46
Willy Tarreauf3c69202006-07-09 16:42:34 +020047/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
48 * ssl-hello-chk option to ensure that the remote server speaks SSL.
49 *
50 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
51 */
52const char sslv3_client_hello_pkt[] = {
53 "\x16" /* ContentType : 0x16 = Hanshake */
54 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
55 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
56 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
57 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
58 "\x03\x00" /* Hello Version : 0x0300 = v3 */
59 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
60 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
61 "\x00" /* Session ID length : empty (no session ID) */
62 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
63 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
64 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
65 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
66 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
67 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
68 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
69 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
70 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
71 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
72 "\x00\x38" "\x00\x39" "\x00\x3A"
73 "\x01" /* Compression Length : 0x01 = 1 byte for types */
74 "\x00" /* Compression Type : 0x00 = NULL compression */
75};
76
Willy Tarreau13943ab2006-12-31 00:24:10 +010077/* some of the most common options which are also the easiest to handle */
78static const struct {
79 const char *name;
80 unsigned int val;
81 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010082 unsigned int checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +010083} cfg_opts[] =
84{
85#ifdef TPROXY
86 { "transparent", PR_O_TRANSP, PR_CAP_FE },
87#endif
Willy Tarreau4fee4e92007-01-06 21:09:17 +010088 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
89 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010090 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
91 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
92 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
93 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
94 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
95 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
96 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
97 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
98 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
99 { "forceclose", PR_O_FORCE_CLO | PR_O_HTTP_CLOSE, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100100#ifdef CONFIG_HAP_TCPSPLICE
101 { "tcpsplice", PR_O_TCPSPLICE , PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
102#endif
103
Willy Tarreau13943ab2006-12-31 00:24:10 +0100104 { NULL, 0, 0 }
105};
106
Willy Tarreaubaaee002006-06-26 02:48:02 +0200107
108static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
109int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
110int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
111
112/*
113 * converts <str> to a list of listeners which are dynamically allocated.
114 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
115 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
116 * - <port> is a numerical port from 1 to 65535 ;
117 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
118 * This can be repeated as many times as necessary, separated by a coma.
119 * The <tail> argument is a pointer to a current list which should be appended
120 * to the tail of the new list. The pointer to the new list is returned.
121 */
122static struct listener *str2listener(char *str, struct listener *tail)
123{
124 struct listener *l;
125 char *c, *next, *range, *dupstr;
126 int port, end;
127
128 next = dupstr = strdup(str);
129
130 while (next && *next) {
131 struct sockaddr_storage ss;
132
133 str = next;
134 /* 1) look for the end of the first address */
135 if ((next = strrchr(str, ',')) != NULL) {
136 *next++ = 0;
137 }
138
139 /* 2) look for the addr/port delimiter, it's the last colon. */
140 if ((range = strrchr(str, ':')) == NULL) {
141 Alert("Missing port number: '%s'\n", str);
142 goto fail;
143 }
144
145 *range++ = 0;
146
147 if (strrchr(str, ':') != NULL) {
148 /* IPv6 address contains ':' */
149 memset(&ss, 0, sizeof(ss));
150 ss.ss_family = AF_INET6;
151
152 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
153 Alert("Invalid server address: '%s'\n", str);
154 goto fail;
155 }
156 }
157 else {
158 memset(&ss, 0, sizeof(ss));
159 ss.ss_family = AF_INET;
160
161 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
162 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
163 }
164 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
165 struct hostent *he;
166
167 if ((he = gethostbyname(str)) == NULL) {
168 Alert("Invalid server name: '%s'\n", str);
169 goto fail;
170 }
171 else
172 ((struct sockaddr_in *)&ss)->sin_addr =
173 *(struct in_addr *) *(he->h_addr_list);
174 }
175 }
176
177 /* 3) look for the port-end delimiter */
178 if ((c = strchr(range, '-')) != NULL) {
179 *c++ = 0;
180 end = atol(c);
181 }
182 else {
183 end = atol(range);
184 }
185
186 port = atol(range);
187
188 if (port < 1 || port > 65535) {
189 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
190 goto fail;
191 }
192
193 if (end < 1 || end > 65535) {
194 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
195 goto fail;
196 }
197
198 for (; port <= end; port++) {
199 l = (struct listener *)calloc(1, sizeof(struct listener));
200 l->next = tail;
201 tail = l;
202
203 l->fd = -1;
204 l->addr = ss;
205 if (ss.ss_family == AF_INET6)
206 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
207 else
208 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
209
210 } /* end for(port) */
211 } /* end while(next) */
212 free(dupstr);
213 return tail;
214 fail:
215 free(dupstr);
216 return NULL;
217}
218
Willy Tarreau977b8e42006-12-29 14:19:17 +0100219/*
220 * Sends a warning if proxy <proxy> does not have at least one of the
221 * capabilities in <cap>. An optionnal <hint> may be added at the end
222 * of the warning to help the user. Returns 1 if a warning was emitted
223 * or 0 if the condition is valid.
224 */
225int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
226{
227 char *msg;
228
229 switch (cap) {
230 case PR_CAP_BE: msg = "no backend"; break;
231 case PR_CAP_FE: msg = "no frontend"; break;
232 case PR_CAP_RS: msg = "no ruleset"; break;
233 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
234 default: msg = "not enough"; break;
235 }
236
237 if (!(proxy->cap & cap)) {
238 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100239 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100240 return 1;
241 }
242 return 0;
243}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
245/*
246 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
247 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200248int cfg_parse_global(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249{
250
251 if (!strcmp(args[0], "global")) { /* new section */
252 /* no option, nothing special to do */
253 return 0;
254 }
255 else if (!strcmp(args[0], "daemon")) {
256 global.mode |= MODE_DAEMON;
257 }
258 else if (!strcmp(args[0], "debug")) {
259 global.mode |= MODE_DEBUG;
260 }
261 else if (!strcmp(args[0], "noepoll")) {
262 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
263 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200264 else if (!strcmp(args[0], "nosepoll")) {
265 cfg_polling_mechanism &= ~POLL_USE_SEPOLL;
266 }
267 else if (!strcmp(args[0], "nokqueue")) {
268 cfg_polling_mechanism &= ~POLL_USE_KQUEUE;
269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270 else if (!strcmp(args[0], "nopoll")) {
271 cfg_polling_mechanism &= ~POLL_USE_POLL;
272 }
273 else if (!strcmp(args[0], "quiet")) {
274 global.mode |= MODE_QUIET;
275 }
276 else if (!strcmp(args[0], "stats")) {
277 global.mode |= MODE_STATS;
278 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200279 else if (!strcmp(args[0], "tune.maxpollevents")) {
280 if (global.tune.maxpollevents != 0) {
281 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
282 return 0;
283 }
284 if (*(args[1]) == 0) {
285 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
286 return -1;
287 }
288 global.tune.maxpollevents = atol(args[1]);
289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 else if (!strcmp(args[0], "uid")) {
291 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200292 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 return 0;
294 }
295 if (*(args[1]) == 0) {
296 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
297 return -1;
298 }
299 global.uid = atol(args[1]);
300 }
301 else if (!strcmp(args[0], "gid")) {
302 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200303 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304 return 0;
305 }
306 if (*(args[1]) == 0) {
307 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
308 return -1;
309 }
310 global.gid = atol(args[1]);
311 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200312 /* user/group name handling */
313 else if (!strcmp(args[0], "user")) {
314 struct passwd *ha_user;
315 if (global.uid != 0) {
316 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
317 return 0;
318 }
319 errno = 0;
320 ha_user = getpwnam(args[1]);
321 if (ha_user != NULL) {
322 global.uid = (int)ha_user->pw_uid;
323 }
324 else {
325 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
326 exit(1);
327 }
328 }
329 else if (!strcmp(args[0], "group")) {
330 struct group *ha_group;
331 if (global.gid != 0) {
332 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
333 return 0;
334 }
335 errno = 0;
336 ha_group = getgrnam(args[1]);
337 if (ha_group != NULL) {
338 global.gid = (int)ha_group->gr_gid;
339 }
340 else {
341 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
342 exit(1);
343 }
344 }
345 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200346 else if (!strcmp(args[0], "nbproc")) {
347 if (global.nbproc != 0) {
348 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
349 return 0;
350 }
351 if (*(args[1]) == 0) {
352 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
353 return -1;
354 }
355 global.nbproc = atol(args[1]);
356 }
357 else if (!strcmp(args[0], "maxconn")) {
358 if (global.maxconn != 0) {
359 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
360 return 0;
361 }
362 if (*(args[1]) == 0) {
363 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
364 return -1;
365 }
366 global.maxconn = atol(args[1]);
367#ifdef SYSTEM_MAXCONN
368 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
369 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);
370 global.maxconn = DEFAULT_MAXCONN;
371 }
372#endif /* SYSTEM_MAXCONN */
373 }
374 else if (!strcmp(args[0], "ulimit-n")) {
375 if (global.rlimit_nofile != 0) {
376 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
377 return 0;
378 }
379 if (*(args[1]) == 0) {
380 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
381 return -1;
382 }
383 global.rlimit_nofile = atol(args[1]);
384 }
385 else if (!strcmp(args[0], "chroot")) {
386 if (global.chroot != NULL) {
387 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
388 return 0;
389 }
390 if (*(args[1]) == 0) {
391 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
392 return -1;
393 }
394 global.chroot = strdup(args[1]);
395 }
396 else if (!strcmp(args[0], "pidfile")) {
397 if (global.pidfile != NULL) {
398 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
399 return 0;
400 }
401 if (*(args[1]) == 0) {
402 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
403 return -1;
404 }
405 global.pidfile = strdup(args[1]);
406 }
407 else if (!strcmp(args[0], "log")) { /* syslog server address */
408 struct sockaddr_in *sa;
409 int facility, level;
410
411 if (*(args[1]) == 0 || *(args[2]) == 0) {
412 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
413 return -1;
414 }
415
416 facility = get_log_facility(args[2]);
417 if (facility < 0) {
418 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
419 exit(1);
420 }
421
422 level = 7; /* max syslog level = debug */
423 if (*(args[3])) {
424 level = get_log_level(args[3]);
425 if (level < 0) {
426 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
427 exit(1);
428 }
429 }
430
431 sa = str2sa(args[1]);
432 if (!sa->sin_port)
433 sa->sin_port = htons(SYSLOG_PORT);
434
435 if (global.logfac1 == -1) {
436 global.logsrv1 = *sa;
437 global.logfac1 = facility;
438 global.loglev1 = level;
439 }
440 else if (global.logfac2 == -1) {
441 global.logsrv2 = *sa;
442 global.logfac2 = facility;
443 global.loglev2 = level;
444 }
445 else {
446 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
447 return -1;
448 }
449
450 }
451 else {
452 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
453 return -1;
454 }
455 return 0;
456}
457
458
459static void init_default_instance()
460{
461 memset(&defproxy, 0, sizeof(defproxy));
462 defproxy.mode = PR_MODE_TCP;
463 defproxy.state = PR_STNEW;
464 defproxy.maxconn = cfg_maxpconn;
465 defproxy.conn_retries = CONN_RETRIES;
466 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
467}
468
469/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100470 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
471 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200472 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200473int cfg_parse_listen(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200474{
475 static struct proxy *curproxy = NULL;
476 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200477 const char *err;
Willy Tarreauee991362007-05-14 14:37:50 +0200478 int rc, val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479
Willy Tarreau977b8e42006-12-29 14:19:17 +0100480 if (!strcmp(args[0], "listen"))
481 rc = PR_CAP_LISTEN;
482 else if (!strcmp(args[0], "frontend"))
483 rc = PR_CAP_FE | PR_CAP_RS;
484 else if (!strcmp(args[0], "backend"))
485 rc = PR_CAP_BE | PR_CAP_RS;
486 else if (!strcmp(args[0], "ruleset"))
487 rc = PR_CAP_RS;
488 else
489 rc = PR_CAP_NONE;
490
491 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200492 if (!*args[1]) {
493 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
494 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
495 file, linenum, args[0]);
496 return -1;
497 }
498
499 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
500 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
501 return -1;
502 }
503
504 curproxy->next = proxy;
505 proxy = curproxy;
506 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200507 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200508 LIST_INIT(&curproxy->block_cond);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509
Willy Tarreauee991362007-05-14 14:37:50 +0200510 /* Timeouts are defined as -1, so we cannot use the zeroed area
511 * as a default value.
512 */
513 tv_eternity(&curproxy->clitimeout);
514 tv_eternity(&curproxy->srvtimeout);
515 tv_eternity(&curproxy->contimeout);
516 tv_eternity(&curproxy->appsession_timeout);
517
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100519 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520
521 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100522 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 curproxy->listen = str2listener(args[2], curproxy->listen);
524 if (!curproxy->listen)
525 return -1;
526 global.maxsock++;
527 }
528
529 /* set default values */
530 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200531 curproxy->options = defproxy.options;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200532 curproxy->except_net = defproxy.except_net;
533 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200534
Willy Tarreau977b8e42006-12-29 14:19:17 +0100535 if (curproxy->cap & PR_CAP_FE) {
536 curproxy->maxconn = defproxy.maxconn;
537
538 /* initialize error relocations */
539 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
540 if (defproxy.errmsg[rc].str)
541 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
542 }
543
544 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
545 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546
Willy Tarreau977b8e42006-12-29 14:19:17 +0100547 if (curproxy->cap & PR_CAP_BE) {
548 curproxy->fullconn = defproxy.fullconn;
549 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200550
Willy Tarreau977b8e42006-12-29 14:19:17 +0100551 if (defproxy.check_req)
552 curproxy->check_req = strdup(defproxy.check_req);
553 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200554
Willy Tarreau977b8e42006-12-29 14:19:17 +0100555 if (defproxy.cookie_name)
556 curproxy->cookie_name = strdup(defproxy.cookie_name);
557 curproxy->cookie_len = defproxy.cookie_len;
558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200559
Willy Tarreau977b8e42006-12-29 14:19:17 +0100560 if (curproxy->cap & PR_CAP_RS) {
561 if (defproxy.capture_name)
562 curproxy->capture_name = strdup(defproxy.capture_name);
563 curproxy->capture_namelen = defproxy.capture_namelen;
564 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566
Willy Tarreau977b8e42006-12-29 14:19:17 +0100567 if (curproxy->cap & PR_CAP_FE) {
568 curproxy->clitimeout = defproxy.clitimeout;
569 curproxy->uri_auth = defproxy.uri_auth;
570 curproxy->mon_net = defproxy.mon_net;
571 curproxy->mon_mask = defproxy.mon_mask;
572 if (defproxy.monitor_uri)
573 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
574 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100575 if (defproxy.defbe.name)
576 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100577 }
578
579 if (curproxy->cap & PR_CAP_BE) {
580 curproxy->contimeout = defproxy.contimeout;
581 curproxy->srvtimeout = defproxy.srvtimeout;
582 curproxy->source_addr = defproxy.source_addr;
583 }
584
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585 curproxy->mode = defproxy.mode;
586 curproxy->logfac1 = defproxy.logfac1;
587 curproxy->logsrv1 = defproxy.logsrv1;
588 curproxy->loglev1 = defproxy.loglev1;
589 curproxy->logfac2 = defproxy.logfac2;
590 curproxy->logsrv2 = defproxy.logsrv2;
591 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200592 curproxy->grace = defproxy.grace;
Willy Tarreau1c47f852006-07-09 08:22:27 +0200593
Willy Tarreaubaaee002006-06-26 02:48:02 +0200594 return 0;
595 }
596 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
597 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100598 /* FIXME-20070101: we should do this too at the end of the
599 * config parsing to free all default values.
600 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 if (defproxy.check_req) free(defproxy.check_req);
602 if (defproxy.cookie_name) free(defproxy.cookie_name);
603 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200604 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100605 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100606
607 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
608 if (defproxy.errmsg[rc].len)
609 free(defproxy.errmsg[rc].str);
610 }
611
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 /* we cannot free uri_auth because it might already be used */
613 init_default_instance();
614 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100615 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616 return 0;
617 }
618 else if (curproxy == NULL) {
619 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
620 return -1;
621 }
622
Willy Tarreau977b8e42006-12-29 14:19:17 +0100623
624 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200625 if (!strcmp(args[0], "bind")) { /* new listen addresses */
626 if (curproxy == &defproxy) {
627 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
628 return -1;
629 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100630 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
631 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632
633 if (strchr(args[1], ':') == NULL) {
634 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
635 file, linenum, args[0]);
636 return -1;
637 }
638 curproxy->listen = str2listener(args[1], curproxy->listen);
639 if (!curproxy->listen)
640 return -1;
641 global.maxsock++;
642 return 0;
643 }
644 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
645 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
646 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
647 file, linenum, args[0]);
648 return -1;
649 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100650 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
651 return 0;
652
Willy Tarreaubaaee002006-06-26 02:48:02 +0200653 /* flush useless bits */
654 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
655 return 0;
656 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200657 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100658 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
659 return 0;
660
Willy Tarreau1c47f852006-07-09 08:22:27 +0200661 if (!*args[1]) {
662 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
663 file, linenum, args[0]);
664 return -1;
665 }
666
667 if (curproxy->monitor_uri != NULL)
668 free(curproxy->monitor_uri);
669
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100670 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200671 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100672 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200673 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
674
675 return 0;
676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
678 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
679 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
680 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
681 else {
682 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
683 return -1;
684 }
685 }
686 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
687 curproxy->state = PR_STSTOPPED;
688 }
689 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
690 curproxy->state = PR_STNEW;
691 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200692 else if (!strcmp(args[0], "acl")) { /* add an ACL */
693 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
694 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
695 file, linenum, args[1]);
696 return -1;
697 }
698 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200699 else if (!strcmp(args[0], "cookie")) { /* cookie name */
700 int cur_arg;
701 // if (curproxy == &defproxy) {
702 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
703 // return -1;
704 // }
705
Willy Tarreau977b8e42006-12-29 14:19:17 +0100706 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
707 return 0;
708
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709 if (curproxy->cookie_name != NULL) {
710 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
711 // file, linenum);
712 // return 0;
713 free(curproxy->cookie_name);
714 }
715
716 if (*(args[1]) == 0) {
717 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
718 file, linenum, args[0]);
719 return -1;
720 }
721 curproxy->cookie_name = strdup(args[1]);
722 curproxy->cookie_len = strlen(curproxy->cookie_name);
723
724 cur_arg = 2;
725 while (*(args[cur_arg])) {
726 if (!strcmp(args[cur_arg], "rewrite")) {
727 curproxy->options |= PR_O_COOK_RW;
728 }
729 else if (!strcmp(args[cur_arg], "indirect")) {
730 curproxy->options |= PR_O_COOK_IND;
731 }
732 else if (!strcmp(args[cur_arg], "insert")) {
733 curproxy->options |= PR_O_COOK_INS;
734 }
735 else if (!strcmp(args[cur_arg], "nocache")) {
736 curproxy->options |= PR_O_COOK_NOC;
737 }
738 else if (!strcmp(args[cur_arg], "postonly")) {
739 curproxy->options |= PR_O_COOK_POST;
740 }
741 else if (!strcmp(args[cur_arg], "prefix")) {
742 curproxy->options |= PR_O_COOK_PFX;
743 }
744 else {
745 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
746 file, linenum, args[0]);
747 return -1;
748 }
749 cur_arg++;
750 }
751 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
752 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
753 file, linenum);
754 return -1;
755 }
756
757 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
758 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
759 file, linenum);
760 return -1;
761 }
762 }/* end else if (!strcmp(args[0], "cookie")) */
763 else if (!strcmp(args[0], "appsession")) { /* cookie name */
764 // if (curproxy == &defproxy) {
765 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
766 // return -1;
767 // }
768
Willy Tarreau977b8e42006-12-29 14:19:17 +0100769 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
770 return 0;
771
Willy Tarreaubaaee002006-06-26 02:48:02 +0200772 if (curproxy->appsession_name != NULL) {
773 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
774 // file, linenum);
775 // return 0;
776 free(curproxy->appsession_name);
777 }
778
779 if (*(args[5]) == 0) {
780 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
781 file, linenum, args[0]);
782 return -1;
783 }
784 have_appsession = 1;
785 curproxy->appsession_name = strdup(args[1]);
786 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
787 curproxy->appsession_len = atoi(args[3]);
Willy Tarreauee991362007-05-14 14:37:50 +0200788 val = atoi(args[5]);
789 if (val > 0)
790 __tv_from_ms(&curproxy->appsession_timeout, val);
791 else
792 tv_eternity(&curproxy->appsession_timeout);
793
Willy Tarreaubaaee002006-06-26 02:48:02 +0200794 rc = chtbl_init(&(curproxy->htbl_proxy), TBLSIZ, hashpjw, match_str, destroy);
795 if (rc) {
796 Alert("Error Init Appsession Hashtable.\n");
797 return -1;
798 }
799 } /* Url App Session */
800 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100801 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
802 return 0;
803
Willy Tarreaubaaee002006-06-26 02:48:02 +0200804 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
805 // if (curproxy == &defproxy) {
806 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
807 // return -1;
808 // }
809
810 if (curproxy->capture_name != NULL) {
811 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
812 // file, linenum, args[0]);
813 // return 0;
814 free(curproxy->capture_name);
815 }
816
817 if (*(args[4]) == 0) {
818 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
819 file, linenum, args[0]);
820 return -1;
821 }
822 curproxy->capture_name = strdup(args[2]);
823 curproxy->capture_namelen = strlen(curproxy->capture_name);
824 curproxy->capture_len = atol(args[4]);
825 if (curproxy->capture_len >= CAPTURE_LEN) {
826 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
827 file, linenum, CAPTURE_LEN - 1);
828 curproxy->capture_len = CAPTURE_LEN - 1;
829 }
830 curproxy->to_log |= LW_COOKIE;
831 }
832 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
833 struct cap_hdr *hdr;
834
835 if (curproxy == &defproxy) {
836 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
837 return -1;
838 }
839
840 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
841 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
842 file, linenum, args[0], args[1]);
843 return -1;
844 }
845
846 hdr = calloc(sizeof(struct cap_hdr), 1);
847 hdr->next = curproxy->req_cap;
848 hdr->name = strdup(args[3]);
849 hdr->namelen = strlen(args[3]);
850 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200851 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200852 hdr->index = curproxy->nb_req_cap++;
853 curproxy->req_cap = hdr;
854 curproxy->to_log |= LW_REQHDR;
855 }
856 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
857 struct cap_hdr *hdr;
858
859 if (curproxy == &defproxy) {
860 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
861 return -1;
862 }
863
864 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
865 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
866 file, linenum, args[0], args[1]);
867 return -1;
868 }
869 hdr = calloc(sizeof(struct cap_hdr), 1);
870 hdr->next = curproxy->rsp_cap;
871 hdr->name = strdup(args[3]);
872 hdr->namelen = strlen(args[3]);
873 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200874 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200875 hdr->index = curproxy->nb_rsp_cap++;
876 curproxy->rsp_cap = hdr;
877 curproxy->to_log |= LW_RSPHDR;
878 }
879 else {
880 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
881 file, linenum, args[0]);
882 return -1;
883 }
884 }
885 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200886 if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
888 return 0;
889 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100890 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
891 return 0;
892
Willy Tarreaubaaee002006-06-26 02:48:02 +0200893 if (*(args[1]) == 0) {
894 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
895 file, linenum, args[0]);
896 return -1;
897 }
Willy Tarreauee991362007-05-14 14:37:50 +0200898 val = atoi(args[1]);
899 if (val > 0)
900 __tv_from_ms(&curproxy->contimeout, val);
901 else
902 tv_eternity(&curproxy->contimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200903 }
904 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200905 if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
907 file, linenum, args[0]);
908 return 0;
909 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100910 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
911 return 0;
912
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913 if (*(args[1]) == 0) {
914 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
915 file, linenum, args[0]);
916 return -1;
917 }
Willy Tarreauee991362007-05-14 14:37:50 +0200918 val = atoi(args[1]);
919 if (val > 0)
920 __tv_from_ms(&curproxy->clitimeout, val);
921 else
922 tv_eternity(&curproxy->clitimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 }
924 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200925 if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
927 return 0;
928 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100929 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
930 return 0;
931
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 if (*(args[1]) == 0) {
933 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
934 file, linenum, args[0]);
935 return -1;
936 }
Willy Tarreauee991362007-05-14 14:37:50 +0200937 val = atoi(args[1]);
938 if (val > 0)
939 __tv_from_ms(&curproxy->srvtimeout, val);
940 else
941 tv_eternity(&curproxy->srvtimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
943 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100944 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
945 return 0;
946
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947 if (*(args[1]) == 0) {
948 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
949 file, linenum, args[0]);
950 return -1;
951 }
952 curproxy->conn_retries = atol(args[1]);
953 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200954 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
955 int pol = ACL_COND_NONE;
956 struct acl_cond *cond;
957
958 if (!strcmp(args[1], "if"))
959 pol = ACL_COND_IF;
960 else if (!strcmp(args[1], "unless"))
961 pol = ACL_COND_UNLESS;
962
963 if (pol == ACL_COND_NONE) {
964 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
965 file, linenum, args[0]);
966 return -1;
967 }
968
969 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
970 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
971 file, linenum);
972 return -1;
973 }
974 LIST_ADDQ(&curproxy->block_cond, &cond->list);
975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200976 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100977 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
978 return 0;
979
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
981 curproxy->uri_auth = NULL; /* we must detach from the default config */
982
983 if (*(args[1]) == 0) {
984 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
985 return -1;
986 } else if (!strcmp(args[1], "uri")) {
987 if (*(args[2]) == 0) {
988 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
989 return -1;
990 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
991 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
992 return -1;
993 }
994 } else if (!strcmp(args[1], "realm")) {
995 if (*(args[2]) == 0) {
996 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
997 return -1;
998 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
999 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1000 return -1;
1001 }
1002 } else if (!strcmp(args[1], "auth")) {
1003 if (*(args[2]) == 0) {
1004 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1005 return -1;
1006 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1007 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1008 return -1;
1009 }
1010 } else if (!strcmp(args[1], "scope")) {
1011 if (*(args[2]) == 0) {
1012 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1013 return -1;
1014 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1015 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1016 return -1;
1017 }
1018 } else if (!strcmp(args[1], "enable")) {
1019 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1020 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1021 return -1;
1022 }
1023 } else {
1024 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'uri', 'realm', 'auth' or 'enable').\n",
1025 file, linenum, args[0]);
1026 return -1;
1027 }
1028 }
1029 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001030 int optnum;
1031
Willy Tarreaubaaee002006-06-26 02:48:02 +02001032 if (*(args[1]) == 0) {
1033 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
1034 return -1;
1035 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001036
1037 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1038 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1039 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1040 return 0;
1041 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001042 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001043 return 0;
1044 }
1045 }
1046
1047 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048 /* generate a complete HTTP log */
1049 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1050 else if (!strcmp(args[1], "tcplog"))
1051 /* generate a detailed TCP log */
1052 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 else if (!strcmp(args[1], "tcpka")) {
1054 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001055 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1056 return 0;
1057
1058 if (curproxy->cap & PR_CAP_FE)
1059 curproxy->options |= PR_O_TCP_CLI_KA;
1060 if (curproxy->cap & PR_CAP_BE)
1061 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062 }
1063 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001064 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1065 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066 /* use HTTP request to check servers' health */
1067 if (curproxy->check_req != NULL) {
1068 free(curproxy->check_req);
1069 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001070 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001071 curproxy->options &= ~PR_O_SMTP_CHK;
1072 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 if (!*args[2]) { /* no argument */
1074 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1075 curproxy->check_len = strlen(DEF_CHECK_REQ);
1076 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001077 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078 curproxy->check_req = (char *)malloc(reqlen);
1079 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1080 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1081 } else { /* more arguments : METHOD URI [HTTP_VER] */
1082 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1083 if (*args[4])
1084 reqlen += strlen(args[4]);
1085 else
1086 reqlen += strlen("HTTP/1.0");
1087
1088 curproxy->check_req = (char *)malloc(reqlen);
1089 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1090 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1091 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001092 }
1093 else if (!strcmp(args[1], "ssl-hello-chk")) {
1094 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001095 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1096 return 0;
1097
Willy Tarreauf3c69202006-07-09 16:42:34 +02001098 if (curproxy->check_req != NULL) {
1099 free(curproxy->check_req);
1100 }
1101 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001102 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001103 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104 }
Willy Tarreau23677902007-05-08 23:50:35 +02001105 else if (!strcmp(args[1], "smtpchk")) {
1106 /* use SMTP request to check servers' health */
1107 if (curproxy->check_req != NULL) {
1108 free(curproxy->check_req);
1109 }
1110 curproxy->options &= ~PR_O_HTTP_CHK;
1111 curproxy->options &= ~PR_O_SSL3_CHK;
1112 curproxy->options |= PR_O_SMTP_CHK;
1113
1114 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1115 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1116 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1117 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1118 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1119 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1120 curproxy->check_req = (char *)malloc(reqlen);
1121 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1122 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1123 } else {
1124 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1125 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1126 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1127 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1128 }
1129 }
1130 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001131 else if (!strcmp(args[1], "forwardfor")) {
1132 /* insert x-forwarded-for field, but not for the
1133 * IP address listed as an except.
1134 */
1135 if (*(args[2])) {
1136 if (!strcmp(args[2], "except")) {
1137 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1138 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1139 file, linenum, args[0]);
1140 return -1;
1141 }
1142 /* flush useless bits */
1143 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1144 } else {
1145 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1146 file, linenum, args[0]);
1147 return -1;
1148 }
1149 }
1150 curproxy->options |= PR_O_FWDFOR;
1151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001152 else {
1153 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1154 return -1;
1155 }
1156 return 0;
1157 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001158 else if (!strcmp(args[0], "default_backend")) {
1159 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1160 return 0;
1161
1162 if (*(args[1]) == 0) {
1163 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1164 return -1;
1165 }
1166 if (curproxy->defbe.name)
1167 free(curproxy->defbe.name);
1168 curproxy->defbe.name = strdup(args[1]);
1169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001170 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001171 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1172 return 0;
1173
Willy Tarreaubaaee002006-06-26 02:48:02 +02001174 /* enable reconnections to dispatch */
1175 curproxy->options |= PR_O_REDISP;
1176 }
1177#ifdef TPROXY
1178 else if (!strcmp(args[0], "transparent")) {
1179 /* enable transparent proxy connections */
1180 curproxy->options |= PR_O_TRANSP;
1181 }
1182#endif
1183 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001184 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1185 return 0;
1186
Willy Tarreaubaaee002006-06-26 02:48:02 +02001187 if (*(args[1]) == 0) {
1188 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1189 return -1;
1190 }
1191 curproxy->maxconn = atol(args[1]);
1192 }
Willy Tarreau86034312006-12-29 00:10:33 +01001193 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001194 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1195 return 0;
1196
Willy Tarreau86034312006-12-29 00:10:33 +01001197 if (*(args[1]) == 0) {
1198 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1199 return -1;
1200 }
1201 curproxy->fullconn = atol(args[1]);
1202 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1204 if (*(args[1]) == 0) {
1205 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1206 return -1;
1207 }
1208 curproxy->grace = atol(args[1]);
1209 }
1210 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1211 if (curproxy == &defproxy) {
1212 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1213 return -1;
1214 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001215 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1216 return 0;
1217
Willy Tarreaubaaee002006-06-26 02:48:02 +02001218 if (strchr(args[1], ':') == NULL) {
1219 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1220 return -1;
1221 }
1222 curproxy->dispatch_addr = *str2sa(args[1]);
1223 }
1224 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001225 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1226 return 0;
1227
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 if (*(args[1])) {
1229 if (!strcmp(args[1], "roundrobin")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001230 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001231 curproxy->options |= PR_O_BALANCE_RR;
1232 }
1233 else if (!strcmp(args[1], "source")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001234 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001235 curproxy->options |= PR_O_BALANCE_SH;
1236 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001237 else if (!strcmp(args[1], "uri")) {
1238 curproxy->options &= ~PR_O_BALANCE;
1239 curproxy->options |= PR_O_BALANCE_UH;
1240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001241 else {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001242 Alert("parsing [%s:%d] : '%s' only supports 'roundrobin', 'source' and 'uri' options.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001243 return -1;
1244 }
1245 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001246 else {/* if no option is set, use round-robin by default */
1247 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001248 curproxy->options |= PR_O_BALANCE_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001250 }
1251 else if (!strcmp(args[0], "server")) { /* server address */
1252 int cur_arg;
1253 char *rport;
1254 char *raddr;
1255 short realport;
1256 int do_check;
1257
1258 if (curproxy == &defproxy) {
1259 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1260 return -1;
1261 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001262 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1263 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001264
1265 if (!*args[2]) {
1266 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1267 file, linenum, args[0]);
1268 return -1;
1269 }
1270 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1271 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1272 return -1;
1273 }
1274
1275 /* the servers are linked backwards first */
1276 newsrv->next = curproxy->srv;
1277 curproxy->srv = newsrv;
1278 newsrv->proxy = curproxy;
1279
1280 LIST_INIT(&newsrv->pendconns);
1281 do_check = 0;
1282 newsrv->state = SRV_RUNNING; /* early server setup */
1283 newsrv->id = strdup(args[1]);
1284
1285 /* several ways to check the port component :
1286 * - IP => port=+0, relative
1287 * - IP: => port=+0, relative
1288 * - IP:N => port=N, absolute
1289 * - IP:+N => port=+N, relative
1290 * - IP:-N => port=-N, relative
1291 */
1292 raddr = strdup(args[2]);
1293 rport = strchr(raddr, ':');
1294 if (rport) {
1295 *rport++ = 0;
1296 realport = atol(rport);
1297 if (!isdigit((int)*rport))
1298 newsrv->state |= SRV_MAPPORTS;
1299 } else {
1300 realport = 0;
1301 newsrv->state |= SRV_MAPPORTS;
1302 }
1303
1304 newsrv->addr = *str2sa(raddr);
1305 newsrv->addr.sin_port = htons(realport);
1306 free(raddr);
1307
1308 newsrv->curfd = -1; /* no health-check in progress */
1309 newsrv->inter = DEF_CHKINTR;
1310 newsrv->rise = DEF_RISETIME;
1311 newsrv->fall = DEF_FALLTIME;
1312 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001313 newsrv->uweight = 1;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001314
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315 cur_arg = 3;
1316 while (*args[cur_arg]) {
1317 if (!strcmp(args[cur_arg], "cookie")) {
1318 newsrv->cookie = strdup(args[cur_arg + 1]);
1319 newsrv->cklen = strlen(args[cur_arg + 1]);
1320 cur_arg += 2;
1321 }
1322 else if (!strcmp(args[cur_arg], "rise")) {
1323 newsrv->rise = atol(args[cur_arg + 1]);
1324 newsrv->health = newsrv->rise;
1325 cur_arg += 2;
1326 }
1327 else if (!strcmp(args[cur_arg], "fall")) {
1328 newsrv->fall = atol(args[cur_arg + 1]);
1329 cur_arg += 2;
1330 }
1331 else if (!strcmp(args[cur_arg], "inter")) {
1332 newsrv->inter = atol(args[cur_arg + 1]);
1333 cur_arg += 2;
1334 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001335 else if (!strcmp(args[cur_arg], "addr")) {
1336 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001337 cur_arg += 2;
1338 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001339 else if (!strcmp(args[cur_arg], "port")) {
1340 newsrv->check_port = atol(args[cur_arg + 1]);
1341 cur_arg += 2;
1342 }
1343 else if (!strcmp(args[cur_arg], "backup")) {
1344 newsrv->state |= SRV_BACKUP;
1345 cur_arg ++;
1346 }
1347 else if (!strcmp(args[cur_arg], "weight")) {
1348 int w;
1349 w = atol(args[cur_arg + 1]);
1350 if (w < 1 || w > 256) {
1351 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1352 file, linenum, newsrv->id, w);
1353 return -1;
1354 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001355 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001356 cur_arg += 2;
1357 }
1358 else if (!strcmp(args[cur_arg], "minconn")) {
1359 newsrv->minconn = atol(args[cur_arg + 1]);
1360 cur_arg += 2;
1361 }
1362 else if (!strcmp(args[cur_arg], "maxconn")) {
1363 newsrv->maxconn = atol(args[cur_arg + 1]);
1364 cur_arg += 2;
1365 }
1366 else if (!strcmp(args[cur_arg], "check")) {
1367 global.maxsock++;
1368 do_check = 1;
1369 cur_arg += 1;
1370 }
1371 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1372 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001373#ifdef CONFIG_HAP_CTTPROXY
1374 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1375 file, linenum, "source", "usesrc");
1376#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001377 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1378 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001379#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 return -1;
1381 }
1382 newsrv->state |= SRV_BIND_SRC;
1383 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1384 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001385 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001386#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001387 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001388 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1389 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001390 return -1;
1391 }
1392 if (!*args[cur_arg + 1]) {
1393 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1394 file, linenum, "usesrc");
1395 return -1;
1396 }
1397 if (!strcmp(args[cur_arg + 1], "client")) {
1398 newsrv->state |= SRV_TPROXY_CLI;
1399 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1400 newsrv->state |= SRV_TPROXY_CIP;
1401 } else {
1402 newsrv->state |= SRV_TPROXY_ADDR;
1403 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1404 }
1405 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1406 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001407#else /* no CTTPROXY support */
1408 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1409 file, linenum, "usesrc");
1410 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001411#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001413 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001414#ifdef CONFIG_HAP_CTTPROXY
1415 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1416 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1417 file, linenum, "usesrc", "source");
1418 return -1;
1419 }
1420#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 else {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001422 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn' and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001423 file, linenum, newsrv->id);
1424 return -1;
1425 }
1426 }
1427
1428 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001429 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1430 newsrv->check_port = newsrv->check_addr.sin_port;
1431
Willy Tarreaubaaee002006-06-26 02:48:02 +02001432 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1433 newsrv->check_port = realport; /* by default */
1434 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001435 /* not yet valid, because no port was set on
1436 * the server either. We'll check if we have
1437 * a known port on the first listener.
1438 */
1439 struct listener *l;
1440 l = curproxy->listen;
1441 if (l) {
1442 int port;
1443 port = (l->addr.ss_family == AF_INET6)
1444 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1445 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1446 newsrv->check_port = port;
1447 }
1448 }
1449 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1451 file, linenum, newsrv->id);
1452 return -1;
1453 }
1454 newsrv->state |= SRV_CHECKED;
1455 }
1456
1457 if (newsrv->state & SRV_BACKUP)
1458 curproxy->srv_bck++;
1459 else
1460 curproxy->srv_act++;
1461 }
1462 else if (!strcmp(args[0], "log")) { /* syslog server address */
1463 struct sockaddr_in *sa;
1464 int facility;
1465
1466 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1467 curproxy->logfac1 = global.logfac1;
1468 curproxy->logsrv1 = global.logsrv1;
1469 curproxy->loglev1 = global.loglev1;
1470 curproxy->logfac2 = global.logfac2;
1471 curproxy->logsrv2 = global.logsrv2;
1472 curproxy->loglev2 = global.loglev2;
1473 }
1474 else if (*(args[1]) && *(args[2])) {
1475 int level;
1476
1477 facility = get_log_facility(args[2]);
1478 if (facility < 0) {
1479 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1480 exit(1);
1481 }
1482
1483 level = 7; /* max syslog level = debug */
1484 if (*(args[3])) {
1485 level = get_log_level(args[3]);
1486 if (level < 0) {
1487 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1488 exit(1);
1489 }
1490 }
1491
1492 sa = str2sa(args[1]);
1493 if (!sa->sin_port)
1494 sa->sin_port = htons(SYSLOG_PORT);
1495
1496 if (curproxy->logfac1 == -1) {
1497 curproxy->logsrv1 = *sa;
1498 curproxy->logfac1 = facility;
1499 curproxy->loglev1 = level;
1500 }
1501 else if (curproxy->logfac2 == -1) {
1502 curproxy->logsrv2 = *sa;
1503 curproxy->logfac2 = facility;
1504 curproxy->loglev2 = level;
1505 }
1506 else {
1507 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1508 return -1;
1509 }
1510 }
1511 else {
1512 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1513 file, linenum);
1514 return -1;
1515 }
1516 }
1517 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001518 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1519 return 0;
1520
Willy Tarreaubaaee002006-06-26 02:48:02 +02001521 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001522#ifdef CONFIG_HAP_CTTPROXY
1523 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1524 file, linenum, "source", "usesrc");
1525#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001526 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1527 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001528#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529 return -1;
1530 }
1531
1532 curproxy->source_addr = *str2sa(args[1]);
1533 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001534 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001535#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001536 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1537 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1538 file, linenum, "usesrc");
1539 return -1;
1540 }
1541 if (!*args[3]) {
1542 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1543 file, linenum, "usesrc");
1544 return -1;
1545 }
1546
1547 if (!strcmp(args[3], "client")) {
1548 curproxy->options |= PR_O_TPXY_CLI;
1549 } else if (!strcmp(args[3], "clientip")) {
1550 curproxy->options |= PR_O_TPXY_CIP;
1551 } else {
1552 curproxy->options |= PR_O_TPXY_ADDR;
1553 curproxy->tproxy_addr = *str2sa(args[3]);
1554 }
1555 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001556#else /* no CTTPROXY support */
1557 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1558 file, linenum, "usesrc");
1559 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001560#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001561 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001563#ifdef CONFIG_HAP_CTTPROXY
1564 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1565 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1566 file, linenum, "usesrc", "source");
1567 return -1;
1568 }
1569#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1571 regex_t *preg;
1572 if (curproxy == &defproxy) {
1573 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1574 return -1;
1575 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001576 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1577 return 0;
1578
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 if (*(args[1]) == 0 || *(args[2]) == 0) {
1580 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1581 file, linenum, args[0]);
1582 return -1;
1583 }
1584
1585 preg = calloc(1, sizeof(regex_t));
1586 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1587 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1588 return -1;
1589 }
1590
1591 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1592 if (err) {
1593 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1594 file, linenum, *err);
1595 return -1;
1596 }
1597 }
1598 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1599 regex_t *preg;
1600 if (curproxy == &defproxy) {
1601 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1602 return -1;
1603 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001604 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1605 return 0;
1606
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607 if (*(args[1]) == 0) {
1608 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1609 return -1;
1610 }
1611
1612 preg = calloc(1, sizeof(regex_t));
1613 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1614 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1615 return -1;
1616 }
1617
1618 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1619 }
1620 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1621 regex_t *preg;
1622 if (curproxy == &defproxy) {
1623 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1624 return -1;
1625 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001626 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1627 return 0;
1628
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 if (*(args[1]) == 0) {
1630 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1631 return -1;
1632 }
1633
1634 preg = calloc(1, sizeof(regex_t));
1635 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1636 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1637 return -1;
1638 }
1639
1640 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1641 }
1642 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1643 regex_t *preg;
1644 if (curproxy == &defproxy) {
1645 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1646 return -1;
1647 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001648 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1649 return 0;
1650
Willy Tarreaubaaee002006-06-26 02:48:02 +02001651 if (*(args[1]) == 0) {
1652 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1653 return -1;
1654 }
1655
1656 preg = calloc(1, sizeof(regex_t));
1657 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1658 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1659 return -1;
1660 }
1661
1662 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1663 }
1664 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1665 regex_t *preg;
1666 if (curproxy == &defproxy) {
1667 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1668 return -1;
1669 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001670 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1671 return 0;
1672
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 if (*(args[1]) == 0) {
1674 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1675 return -1;
1676 }
1677
1678 preg = calloc(1, sizeof(regex_t));
1679 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1680 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1681 return -1;
1682 }
1683
1684 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1685 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001686 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1687 regex_t *preg;
1688 if (curproxy == &defproxy) {
1689 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1690 return -1;
1691 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001692 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1693 return 0;
1694
Willy Tarreaub8750a82006-09-03 09:56:00 +02001695 if (*(args[1]) == 0) {
1696 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1697 return -1;
1698 }
1699
1700 preg = calloc(1, sizeof(regex_t));
1701 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1702 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1703 return -1;
1704 }
1705
1706 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1707 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001708 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1709 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001710 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001711 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1712 return -1;
1713 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001714 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1715 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001716
Willy Tarreau977b8e42006-12-29 14:19:17 +01001717 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001718 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1719 file, linenum, args[0]);
1720 return -1;
1721 }
1722
1723 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001724 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001725 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1726 }
1727
1728 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1729 }
1730 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1731 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001732 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001733 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1734 return -1;
1735 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001736 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1737 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001738
Willy Tarreau977b8e42006-12-29 14:19:17 +01001739 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001740 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1741 file, linenum, args[0]);
1742 return -1;
1743 }
1744
1745 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001746 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001747 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1748 }
1749
1750 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1753 regex_t *preg;
1754 if (curproxy == &defproxy) {
1755 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1756 return -1;
1757 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001758 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1759 return 0;
1760
Willy Tarreaubaaee002006-06-26 02:48:02 +02001761 if (*(args[1]) == 0 || *(args[2]) == 0) {
1762 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1763 file, linenum, args[0]);
1764 return -1;
1765 }
1766
1767 preg = calloc(1, sizeof(regex_t));
1768 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1769 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1770 return -1;
1771 }
1772
1773 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1774 if (err) {
1775 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1776 file, linenum, *err);
1777 return -1;
1778 }
1779 }
1780 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1781 regex_t *preg;
1782 if (curproxy == &defproxy) {
1783 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1784 return -1;
1785 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001786 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1787 return 0;
1788
Willy Tarreaubaaee002006-06-26 02:48:02 +02001789 if (*(args[1]) == 0) {
1790 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1791 return -1;
1792 }
1793
1794 preg = calloc(1, sizeof(regex_t));
1795 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1796 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1797 return -1;
1798 }
1799
1800 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1801 }
1802 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1803 regex_t *preg;
1804 if (curproxy == &defproxy) {
1805 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1806 return -1;
1807 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001808 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1809 return 0;
1810
Willy Tarreaubaaee002006-06-26 02:48:02 +02001811 if (*(args[1]) == 0) {
1812 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1813 return -1;
1814 }
1815
1816 preg = calloc(1, sizeof(regex_t));
1817 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1818 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1819 return -1;
1820 }
1821
1822 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1823 }
1824 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1825 regex_t *preg;
1826 if (curproxy == &defproxy) {
1827 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1828 return -1;
1829 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001830 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1831 return 0;
1832
Willy Tarreaubaaee002006-06-26 02:48:02 +02001833 if (*(args[1]) == 0) {
1834 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1835 return -1;
1836 }
1837
1838 preg = calloc(1, sizeof(regex_t));
1839 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1840 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1841 return -1;
1842 }
1843
1844 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1845 }
1846 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1847 regex_t *preg;
1848 if (curproxy == &defproxy) {
1849 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1850 return -1;
1851 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001852 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1853 return 0;
1854
Willy Tarreaubaaee002006-06-26 02:48:02 +02001855 if (*(args[1]) == 0) {
1856 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1857 return -1;
1858 }
1859
1860 preg = calloc(1, sizeof(regex_t));
1861 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1862 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1863 return -1;
1864 }
1865
1866 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1867 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001868 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1869 regex_t *preg;
1870 if (curproxy == &defproxy) {
1871 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1872 return -1;
1873 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001874 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1875 return 0;
1876
Willy Tarreaub8750a82006-09-03 09:56:00 +02001877 if (*(args[1]) == 0) {
1878 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1879 return -1;
1880 }
1881
1882 preg = calloc(1, sizeof(regex_t));
1883 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1884 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1885 return -1;
1886 }
1887
1888 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1891 if (curproxy == &defproxy) {
1892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1893 return -1;
1894 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001895 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1896 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001897
1898 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
1899 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1900 return 0;
1901 }
1902
1903 if (*(args[1]) == 0) {
1904 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1905 return -1;
1906 }
1907
1908 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
1909 }
1910 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
1911 regex_t *preg;
1912
1913 if (*(args[1]) == 0 || *(args[2]) == 0) {
1914 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1915 file, linenum, args[0]);
1916 return -1;
1917 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001918 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1919 return 0;
1920
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 preg = calloc(1, sizeof(regex_t));
1922 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1923 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1924 return -1;
1925 }
1926
1927 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1928 if (err) {
1929 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1930 file, linenum, *err);
1931 return -1;
1932 }
1933 }
1934 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
1935 regex_t *preg;
1936 if (curproxy == &defproxy) {
1937 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1938 return -1;
1939 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001940 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1941 return 0;
1942
Willy Tarreaubaaee002006-06-26 02:48:02 +02001943 if (*(args[1]) == 0) {
1944 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1945 return -1;
1946 }
1947
1948 preg = calloc(1, sizeof(regex_t));
1949 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1950 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1951 return -1;
1952 }
1953
1954 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
1955 if (err) {
1956 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1957 file, linenum, *err);
1958 return -1;
1959 }
1960 }
1961 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
1962 regex_t *preg;
1963 if (curproxy == &defproxy) {
1964 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1965 return -1;
1966 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001967 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1968 return 0;
1969
Willy Tarreaubaaee002006-06-26 02:48:02 +02001970 if (*(args[1]) == 0) {
1971 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1972 return -1;
1973 }
1974
1975 preg = calloc(1, sizeof(regex_t));
1976 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1977 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1978 return -1;
1979 }
1980
1981 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
1982 if (err) {
1983 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1984 file, linenum, *err);
1985 return -1;
1986 }
1987 }
1988 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
1989 regex_t *preg;
1990 if (curproxy == &defproxy) {
1991 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1992 return -1;
1993 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001994 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1995 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001996
1997 if (*(args[1]) == 0 || *(args[2]) == 0) {
1998 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1999 file, linenum, args[0]);
2000 return -1;
2001 }
2002
2003 preg = calloc(1, sizeof(regex_t));
2004 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2005 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2006 return -1;
2007 }
2008
2009 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2010 if (err) {
2011 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2012 file, linenum, *err);
2013 return -1;
2014 }
2015 }
2016 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2017 regex_t *preg;
2018 if (curproxy == &defproxy) {
2019 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2020 return -1;
2021 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002022 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2023 return 0;
2024
Willy Tarreaubaaee002006-06-26 02:48:02 +02002025 if (*(args[1]) == 0) {
2026 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2027 return -1;
2028 }
2029
2030 preg = calloc(1, sizeof(regex_t));
2031 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2032 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2033 return -1;
2034 }
2035
2036 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2037 if (err) {
2038 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2039 file, linenum, *err);
2040 return -1;
2041 }
2042 }
2043 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2044 regex_t *preg;
2045 if (curproxy == &defproxy) {
2046 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2047 return -1;
2048 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002049 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2050 return 0;
2051
Willy Tarreaubaaee002006-06-26 02:48:02 +02002052 if (*(args[1]) == 0) {
2053 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2054 return -1;
2055 }
2056
2057 preg = calloc(1, sizeof(regex_t));
2058 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2059 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2060 return -1;
2061 }
2062
2063 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2064 if (err) {
2065 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2066 file, linenum, *err);
2067 return -1;
2068 }
2069 }
2070 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2071 if (curproxy == &defproxy) {
2072 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2073 return -1;
2074 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002075 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2076 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002077
2078 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2079 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2080 return 0;
2081 }
2082
2083 if (*(args[1]) == 0) {
2084 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2085 return -1;
2086 }
2087
2088 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2089 }
2090 else if (!strcmp(args[0], "errorloc") ||
2091 !strcmp(args[0], "errorloc302") ||
2092 !strcmp(args[0], "errorloc303")) { /* error location */
2093 int errnum, errlen;
2094 char *err;
2095
2096 // if (curproxy == &defproxy) {
2097 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2098 // return -1;
2099 // }
2100
Willy Tarreau977b8e42006-12-29 14:19:17 +01002101 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2102 return 0;
2103
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002105 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 return -1;
2107 }
2108
2109 errnum = atol(args[1]);
2110 if (!strcmp(args[0], "errorloc303")) {
2111 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2112 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2113 } else {
2114 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2115 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2116 }
2117
Willy Tarreau0f772532006-12-23 20:51:41 +01002118 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2119 if (http_err_codes[rc] == errnum) {
2120 if (curproxy->errmsg[rc].str)
2121 free(curproxy->errmsg[rc].str);
2122 curproxy->errmsg[rc].str = err;
2123 curproxy->errmsg[rc].len = errlen;
2124 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002126 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002127
2128 if (rc >= HTTP_ERR_SIZE) {
2129 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2130 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002131 free(err);
2132 }
2133 }
2134 else {
2135 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2136 return -1;
2137 }
2138 return 0;
2139}
2140
2141
2142/*
2143 * This function reads and parses the configuration file given in the argument.
2144 * returns 0 if OK, -1 if error.
2145 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002146int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002147{
2148 char thisline[256];
2149 char *line;
2150 FILE *f;
2151 int linenum = 0;
2152 char *end;
Willy Tarreau540abe42007-05-02 20:50:16 +02002153 char *args[MAX_LINE_ARGS + 1];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002154 int arg;
2155 int cfgerr = 0;
Willy Tarreau80587432006-12-24 17:47:20 +01002156 int nbchk, mininter;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002157 int confsect = CFG_NONE;
2158
2159 struct proxy *curproxy = NULL;
2160 struct server *newsrv = NULL;
2161
2162 if ((f=fopen(file,"r")) == NULL)
2163 return -1;
2164
2165 init_default_instance();
2166
2167 while (fgets(line = thisline, sizeof(thisline), f) != NULL) {
2168 linenum++;
2169
2170 end = line + strlen(line);
2171
2172 /* skip leading spaces */
2173 while (isspace((int)*line))
2174 line++;
2175
2176 arg = 0;
2177 args[arg] = line;
2178
2179 while (*line && arg < MAX_LINE_ARGS) {
2180 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2181 * C equivalent value. Other combinations left unchanged (eg: \1).
2182 */
2183 if (*line == '\\') {
2184 int skip = 0;
2185 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2186 *line = line[1];
2187 skip = 1;
2188 }
2189 else if (line[1] == 'r') {
2190 *line = '\r';
2191 skip = 1;
2192 }
2193 else if (line[1] == 'n') {
2194 *line = '\n';
2195 skip = 1;
2196 }
2197 else if (line[1] == 't') {
2198 *line = '\t';
2199 skip = 1;
2200 }
2201 else if (line[1] == 'x') {
2202 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2203 unsigned char hex1, hex2;
2204 hex1 = toupper(line[2]) - '0';
2205 hex2 = toupper(line[3]) - '0';
2206 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2207 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2208 *line = (hex1<<4) + hex2;
2209 skip = 3;
2210 }
2211 else {
2212 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2213 return -1;
2214 }
2215 }
2216 if (skip) {
2217 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2218 end -= skip;
2219 }
2220 line++;
2221 }
2222 else if (*line == '#' || *line == '\n' || *line == '\r') {
2223 /* end of string, end of loop */
2224 *line = 0;
2225 break;
2226 }
2227 else if (isspace((int)*line)) {
2228 /* a non-escaped space is an argument separator */
2229 *line++ = 0;
2230 while (isspace((int)*line))
2231 line++;
2232 args[++arg] = line;
2233 }
2234 else {
2235 line++;
2236 }
2237 }
2238
2239 /* empty line */
2240 if (!**args)
2241 continue;
2242
Willy Tarreau540abe42007-05-02 20:50:16 +02002243 /* zero out remaining args and ensure that at least one entry
2244 * is zeroed out.
2245 */
2246 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247 args[arg] = line;
2248 }
2249
Willy Tarreau977b8e42006-12-29 14:19:17 +01002250 if (!strcmp(args[0], "listen") ||
2251 !strcmp(args[0], "frontend") ||
2252 !strcmp(args[0], "backend") ||
2253 !strcmp(args[0], "ruleset") ||
2254 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 confsect = CFG_LISTEN;
2256 else if (!strcmp(args[0], "global")) /* global config */
2257 confsect = CFG_GLOBAL;
2258 /* else it's a section keyword */
2259
2260 switch (confsect) {
2261 case CFG_LISTEN:
2262 if (cfg_parse_listen(file, linenum, args) < 0)
2263 return -1;
2264 break;
2265 case CFG_GLOBAL:
2266 if (cfg_parse_global(file, linenum, args) < 0)
2267 return -1;
2268 break;
2269 default:
2270 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2271 return -1;
2272 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002273 }
2274 fclose(f);
2275
2276 /*
2277 * Now, check for the integrity of all that we have collected.
2278 */
2279
2280 /* will be needed further to delay some tasks */
2281 tv_now(&now);
2282
2283 if ((curproxy = proxy) == NULL) {
2284 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2285 file);
2286 return -1;
2287 }
2288
2289 while (curproxy != NULL) {
2290 if (curproxy->state == PR_STSTOPPED) {
2291 curproxy = curproxy->next;
2292 continue;
2293 }
2294
Willy Tarreau977b8e42006-12-29 14:19:17 +01002295 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2296 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 +01002297 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 cfgerr++;
2299 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002300 else if (curproxy->cap & PR_CAP_BE &&
2301 ((curproxy->mode != PR_MODE_HEALTH) &&
2302 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
2303 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2304 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 +01002305 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 cfgerr++;
2307 }
2308 else if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
2309 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002310 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002311 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 cfgerr++;
2313 }
2314#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2315 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002316 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002317 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002318 cfgerr++;
2319 }
2320#endif
2321 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002322 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002323 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002324 }
2325 }
2326 else if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2327 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002328 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002329 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 }
2331 if ((newsrv = curproxy->srv) != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002332 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002333 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 }
2335 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002336 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002337 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002338 }
2339 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002340 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002341 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002343 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002344 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002345 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002346 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002347 if (curproxy->options & PR_O_BALANCE_UH) {
2348 curproxy->options &= ~PR_O_BALANCE;
2349 curproxy->options |= PR_O_BALANCE_RR;
2350
2351 Warning("parsing %s : URI hash will be ignored for %s '%s'. Falling back to round robin.\n",
2352 file, proxy_type_str(curproxy), curproxy->id);
2353 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 }
2355 else if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
2356 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2357 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2358 file, curproxy->id);
2359 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002360 }
2361 }
2362
2363 /* if a default backend was specified, let's find it */
2364 if (curproxy->defbe.name) {
2365 struct proxy *target;
2366
2367 for (target = proxy; target != NULL; target = target->next) {
2368 if (strcmp(target->id, curproxy->defbe.name) == 0)
2369 break;
2370 }
2371 if (target == NULL) {
2372 Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n",
2373 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2374 cfgerr++;
2375 } else if (target == curproxy) {
2376 Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
2377 cfgerr++;
2378 } else if (!(target->cap & PR_CAP_BE)) {
2379 Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n",
2380 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2381 cfgerr++;
2382 } else if (target->mode != curproxy->mode) {
2383 Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
2384 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2385 cfgerr++;
2386 } else {
2387 free(curproxy->defbe.name);
2388 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 }
2390 }
2391
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002392 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002393 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2394 /* map jump target for ACT_SETBE in req_rep chain */
2395 struct hdr_exp *exp;
2396 struct proxy *target;
2397 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
2398 if (exp->action != ACT_SETBE)
2399 continue;
2400 for (target = proxy; target != NULL; target = target->next) {
2401 if (strcmp(target->id, exp->replace) == 0)
2402 break;
2403 }
2404 if (target == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002405 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002406 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaua496b602006-12-17 23:15:24 +01002407 cfgerr++;
2408 } else if (target == curproxy) {
2409 Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
2410 cfgerr++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002411 } else if (!(target->cap & PR_CAP_BE)) {
2412 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002413 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002414 cfgerr++;
2415 } else if (target->mode != PR_MODE_HTTP) {
2416 Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002417 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002418 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002419 } else {
2420 free((void *)exp->replace);
2421 exp->replace = (const char *)target;
2422 }
2423 }
2424 }
Willy Tarreau2738a142006-07-08 17:28:09 +02002425 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002426 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2427 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2428 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002429 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002430 " | While not properly invalid, you will certainly encounter various problems\n"
2431 " | with such a configuration. To fix this, please ensure that all following\n"
2432 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002433 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002434 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002435
2436 if (curproxy->options & PR_O_SSL3_CHK) {
2437 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2438 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2439 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2440 }
2441
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002442 /* The small pools required for the capture lists */
2443 if (curproxy->nb_req_cap)
2444 curproxy->req_cap_pool = create_pool("ptrcap",
2445 curproxy->nb_req_cap * sizeof(char *),
2446 MEM_F_SHARED);
2447 if (curproxy->nb_rsp_cap)
2448 curproxy->rsp_cap_pool = create_pool("ptrcap",
2449 curproxy->nb_rsp_cap * sizeof(char *),
2450 MEM_F_SHARED);
2451
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002452 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2453 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2454 MEM_F_SHARED);
2455
Willy Tarreau86034312006-12-29 00:10:33 +01002456 /* for backwards compatibility with "listen" instances, if
2457 * fullconn is not set but maxconn is set, then maxconn
2458 * is used.
2459 */
2460 if (!curproxy->fullconn)
2461 curproxy->fullconn = curproxy->maxconn;
2462
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 /* first, we will invert the servers list order */
2464 newsrv = NULL;
2465 while (curproxy->srv) {
2466 struct server *next;
2467
2468 next = curproxy->srv->next;
2469 curproxy->srv->next = newsrv;
2470 newsrv = curproxy->srv;
2471 if (!next)
2472 break;
2473 curproxy->srv = next;
2474 }
2475
2476 /* now, newsrv == curproxy->srv */
2477 if (newsrv) {
2478 struct server *srv;
2479 int pgcd;
2480 int act, bck;
2481
2482 /* We will factor the weights to reduce the table,
2483 * using Euclide's largest common divisor algorithm
2484 */
Willy Tarreau417fae02007-03-25 21:16:40 +02002485 pgcd = newsrv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002486 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2487 int t, w;
2488
Willy Tarreau417fae02007-03-25 21:16:40 +02002489 w = srv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002490 while (w) {
2491 t = pgcd % w;
2492 pgcd = w;
2493 w = t;
2494 }
2495 }
2496
2497 act = bck = 0;
2498 for (srv = newsrv; srv; srv = srv->next) {
Willy Tarreau417fae02007-03-25 21:16:40 +02002499 srv->eweight = srv->uweight / pgcd;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500 if (srv->state & SRV_BACKUP)
Willy Tarreau417fae02007-03-25 21:16:40 +02002501 bck += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002502 else
Willy Tarreau417fae02007-03-25 21:16:40 +02002503 act += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504 }
2505
2506 /* this is the largest map we will ever need for this servers list */
2507 if (act < bck)
2508 act = bck;
2509
2510 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2511 /* recounts servers and their weights */
2512 recount_servers(curproxy);
2513 recalc_server_map(curproxy);
2514 }
2515
2516 if (curproxy->options & PR_O_LOGASAP)
2517 curproxy->to_log &= ~LW_BYTES;
2518
Willy Tarreaubaaee002006-06-26 02:48:02 +02002519 /*
2520 * If this server supports a maxconn parameter, it needs a dedicated
2521 * tasks to fill the emptied slots when a connection leaves.
2522 */
2523 newsrv = curproxy->srv;
2524 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002525 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 /* Only 'minconn' was specified, or it was higher than or equal
2527 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2528 * this will avoid further useless expensive computations.
2529 */
2530 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002531 } else if (newsrv->maxconn && !newsrv->minconn) {
2532 /* minconn was not specified, so we set it to maxconn */
2533 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002534 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2535 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002536 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002537 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002538 }
2539
2540 if (newsrv->maxconn > 0) {
2541 struct task *t;
2542
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002543 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002544 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2545 return -1;
2546 }
2547
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002548 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002549 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 t->state = TASK_IDLE;
2551 t->process = process_srv_queue;
2552 t->context = newsrv;
2553 newsrv->queue_mgt = t;
2554
2555 /* never run it unless specifically woken up */
2556 tv_eternity(&t->expire);
2557 task_queue(t);
2558 }
2559 newsrv = newsrv->next;
2560 }
2561
2562 /* now we'll start this proxy's health checks if any */
2563 /* 1- count the checkers to run simultaneously */
2564 nbchk = 0;
2565 mininter = 0;
2566 newsrv = curproxy->srv;
2567 while (newsrv != NULL) {
2568 if (newsrv->state & SRV_CHECKED) {
2569 if (!mininter || mininter > newsrv->inter)
2570 mininter = newsrv->inter;
2571 nbchk++;
2572 }
2573 newsrv = newsrv->next;
2574 }
2575
2576 /* 2- start them as far as possible from each others while respecting
2577 * their own intervals. For this, we will start them after their own
2578 * interval added to the min interval divided by the number of servers,
2579 * weighted by the server's position in the list.
2580 */
2581 if (nbchk > 0) {
2582 struct task *t;
2583 int srvpos;
2584
2585 newsrv = curproxy->srv;
2586 srvpos = 0;
2587 while (newsrv != NULL) {
2588 /* should this server be checked ? */
2589 if (newsrv->state & SRV_CHECKED) {
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002590 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2592 return -1;
2593 }
2594
Willy Tarreau964c9362007-01-07 00:38:00 +01002595 t->wq = NULL;
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002596 t->qlist.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 t->state = TASK_IDLE;
2598 t->process = process_chk;
2599 t->context = newsrv;
2600
2601 /* check this every ms */
Willy Tarreau42aae5c2007-04-29 17:43:56 +02002602 tv_ms_add(&t->expire, &now,
2603 newsrv->inter + mininter * srvpos / nbchk);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 task_queue(t);
2605 //task_wakeup(&rq, t);
2606 srvpos++;
2607 }
2608 newsrv = newsrv->next;
2609 }
2610 }
2611
2612 curproxy = curproxy->next;
2613 }
2614 if (cfgerr > 0) {
2615 Alert("Errors found in configuration file, aborting.\n");
2616 return -1;
2617 }
2618 else
2619 return 0;
2620}
2621
2622
2623
2624/*
2625 * Local variables:
2626 * c-indent-level: 8
2627 * c-basic-offset: 8
2628 * End:
2629 */