blob: 5045ed27f94c320053121c4d1c0764a3b21a41b7 [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 }
279 else if (!strcmp(args[0], "uid")) {
280 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200281 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200282 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.uid = atol(args[1]);
289 }
290 else if (!strcmp(args[0], "gid")) {
291 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200292 Alert("parsing [%s:%d] : group/gid 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.gid = atol(args[1]);
300 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200301 /* user/group name handling */
302 else if (!strcmp(args[0], "user")) {
303 struct passwd *ha_user;
304 if (global.uid != 0) {
305 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
306 return 0;
307 }
308 errno = 0;
309 ha_user = getpwnam(args[1]);
310 if (ha_user != NULL) {
311 global.uid = (int)ha_user->pw_uid;
312 }
313 else {
314 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
315 exit(1);
316 }
317 }
318 else if (!strcmp(args[0], "group")) {
319 struct group *ha_group;
320 if (global.gid != 0) {
321 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]);
322 return 0;
323 }
324 errno = 0;
325 ha_group = getgrnam(args[1]);
326 if (ha_group != NULL) {
327 global.gid = (int)ha_group->gr_gid;
328 }
329 else {
330 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
331 exit(1);
332 }
333 }
334 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200335 else if (!strcmp(args[0], "nbproc")) {
336 if (global.nbproc != 0) {
337 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
338 return 0;
339 }
340 if (*(args[1]) == 0) {
341 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
342 return -1;
343 }
344 global.nbproc = atol(args[1]);
345 }
346 else if (!strcmp(args[0], "maxconn")) {
347 if (global.maxconn != 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.maxconn = atol(args[1]);
356#ifdef SYSTEM_MAXCONN
357 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
358 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);
359 global.maxconn = DEFAULT_MAXCONN;
360 }
361#endif /* SYSTEM_MAXCONN */
362 }
363 else if (!strcmp(args[0], "ulimit-n")) {
364 if (global.rlimit_nofile != 0) {
365 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
366 return 0;
367 }
368 if (*(args[1]) == 0) {
369 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
370 return -1;
371 }
372 global.rlimit_nofile = atol(args[1]);
373 }
374 else if (!strcmp(args[0], "chroot")) {
375 if (global.chroot != NULL) {
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 a directory as an argument.\n", file, linenum, args[0]);
381 return -1;
382 }
383 global.chroot = strdup(args[1]);
384 }
385 else if (!strcmp(args[0], "pidfile")) {
386 if (global.pidfile != 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 file name as an argument.\n", file, linenum, args[0]);
392 return -1;
393 }
394 global.pidfile = strdup(args[1]);
395 }
396 else if (!strcmp(args[0], "log")) { /* syslog server address */
397 struct sockaddr_in *sa;
398 int facility, level;
399
400 if (*(args[1]) == 0 || *(args[2]) == 0) {
401 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
402 return -1;
403 }
404
405 facility = get_log_facility(args[2]);
406 if (facility < 0) {
407 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
408 exit(1);
409 }
410
411 level = 7; /* max syslog level = debug */
412 if (*(args[3])) {
413 level = get_log_level(args[3]);
414 if (level < 0) {
415 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
416 exit(1);
417 }
418 }
419
420 sa = str2sa(args[1]);
421 if (!sa->sin_port)
422 sa->sin_port = htons(SYSLOG_PORT);
423
424 if (global.logfac1 == -1) {
425 global.logsrv1 = *sa;
426 global.logfac1 = facility;
427 global.loglev1 = level;
428 }
429 else if (global.logfac2 == -1) {
430 global.logsrv2 = *sa;
431 global.logfac2 = facility;
432 global.loglev2 = level;
433 }
434 else {
435 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
436 return -1;
437 }
438
439 }
440 else {
441 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
442 return -1;
443 }
444 return 0;
445}
446
447
448static void init_default_instance()
449{
450 memset(&defproxy, 0, sizeof(defproxy));
451 defproxy.mode = PR_MODE_TCP;
452 defproxy.state = PR_STNEW;
453 defproxy.maxconn = cfg_maxpconn;
454 defproxy.conn_retries = CONN_RETRIES;
455 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
456}
457
458/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100459 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
460 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200462int cfg_parse_listen(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463{
464 static struct proxy *curproxy = NULL;
465 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200466 const char *err;
Willy Tarreauee991362007-05-14 14:37:50 +0200467 int rc, val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468
Willy Tarreau977b8e42006-12-29 14:19:17 +0100469 if (!strcmp(args[0], "listen"))
470 rc = PR_CAP_LISTEN;
471 else if (!strcmp(args[0], "frontend"))
472 rc = PR_CAP_FE | PR_CAP_RS;
473 else if (!strcmp(args[0], "backend"))
474 rc = PR_CAP_BE | PR_CAP_RS;
475 else if (!strcmp(args[0], "ruleset"))
476 rc = PR_CAP_RS;
477 else
478 rc = PR_CAP_NONE;
479
480 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481 if (!*args[1]) {
482 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
483 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
484 file, linenum, args[0]);
485 return -1;
486 }
487
488 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
489 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
490 return -1;
491 }
492
493 curproxy->next = proxy;
494 proxy = curproxy;
495 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200496 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200497 LIST_INIT(&curproxy->block_cond);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200498
Willy Tarreauee991362007-05-14 14:37:50 +0200499 /* Timeouts are defined as -1, so we cannot use the zeroed area
500 * as a default value.
501 */
502 tv_eternity(&curproxy->clitimeout);
503 tv_eternity(&curproxy->srvtimeout);
504 tv_eternity(&curproxy->contimeout);
505 tv_eternity(&curproxy->appsession_timeout);
506
Willy Tarreaubaaee002006-06-26 02:48:02 +0200507 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100508 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509
510 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100511 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200512 curproxy->listen = str2listener(args[2], curproxy->listen);
513 if (!curproxy->listen)
514 return -1;
515 global.maxsock++;
516 }
517
518 /* set default values */
519 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520 curproxy->options = defproxy.options;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200521 curproxy->except_net = defproxy.except_net;
522 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523
Willy Tarreau977b8e42006-12-29 14:19:17 +0100524 if (curproxy->cap & PR_CAP_FE) {
525 curproxy->maxconn = defproxy.maxconn;
526
527 /* initialize error relocations */
528 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
529 if (defproxy.errmsg[rc].str)
530 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
531 }
532
533 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
534 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200535
Willy Tarreau977b8e42006-12-29 14:19:17 +0100536 if (curproxy->cap & PR_CAP_BE) {
537 curproxy->fullconn = defproxy.fullconn;
538 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200539
Willy Tarreau977b8e42006-12-29 14:19:17 +0100540 if (defproxy.check_req)
541 curproxy->check_req = strdup(defproxy.check_req);
542 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200543
Willy Tarreau977b8e42006-12-29 14:19:17 +0100544 if (defproxy.cookie_name)
545 curproxy->cookie_name = strdup(defproxy.cookie_name);
546 curproxy->cookie_len = defproxy.cookie_len;
547 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548
Willy Tarreau977b8e42006-12-29 14:19:17 +0100549 if (curproxy->cap & PR_CAP_RS) {
550 if (defproxy.capture_name)
551 curproxy->capture_name = strdup(defproxy.capture_name);
552 curproxy->capture_namelen = defproxy.capture_namelen;
553 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100554 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200555
Willy Tarreau977b8e42006-12-29 14:19:17 +0100556 if (curproxy->cap & PR_CAP_FE) {
557 curproxy->clitimeout = defproxy.clitimeout;
558 curproxy->uri_auth = defproxy.uri_auth;
559 curproxy->mon_net = defproxy.mon_net;
560 curproxy->mon_mask = defproxy.mon_mask;
561 if (defproxy.monitor_uri)
562 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
563 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100564 if (defproxy.defbe.name)
565 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100566 }
567
568 if (curproxy->cap & PR_CAP_BE) {
569 curproxy->contimeout = defproxy.contimeout;
570 curproxy->srvtimeout = defproxy.srvtimeout;
571 curproxy->source_addr = defproxy.source_addr;
572 }
573
Willy Tarreaubaaee002006-06-26 02:48:02 +0200574 curproxy->mode = defproxy.mode;
575 curproxy->logfac1 = defproxy.logfac1;
576 curproxy->logsrv1 = defproxy.logsrv1;
577 curproxy->loglev1 = defproxy.loglev1;
578 curproxy->logfac2 = defproxy.logfac2;
579 curproxy->logsrv2 = defproxy.logsrv2;
580 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581 curproxy->grace = defproxy.grace;
Willy Tarreau1c47f852006-07-09 08:22:27 +0200582
Willy Tarreaubaaee002006-06-26 02:48:02 +0200583 return 0;
584 }
585 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
586 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100587 /* FIXME-20070101: we should do this too at the end of the
588 * config parsing to free all default values.
589 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 if (defproxy.check_req) free(defproxy.check_req);
591 if (defproxy.cookie_name) free(defproxy.cookie_name);
592 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200593 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100594 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100595
596 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
597 if (defproxy.errmsg[rc].len)
598 free(defproxy.errmsg[rc].str);
599 }
600
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 /* we cannot free uri_auth because it might already be used */
602 init_default_instance();
603 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100604 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200605 return 0;
606 }
607 else if (curproxy == NULL) {
608 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
609 return -1;
610 }
611
Willy Tarreau977b8e42006-12-29 14:19:17 +0100612
613 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200614 if (!strcmp(args[0], "bind")) { /* new listen addresses */
615 if (curproxy == &defproxy) {
616 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
617 return -1;
618 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100619 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
620 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200621
622 if (strchr(args[1], ':') == NULL) {
623 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
624 file, linenum, args[0]);
625 return -1;
626 }
627 curproxy->listen = str2listener(args[1], curproxy->listen);
628 if (!curproxy->listen)
629 return -1;
630 global.maxsock++;
631 return 0;
632 }
633 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
634 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
635 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
636 file, linenum, args[0]);
637 return -1;
638 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100639 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
640 return 0;
641
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 /* flush useless bits */
643 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
644 return 0;
645 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200646 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100647 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
648 return 0;
649
Willy Tarreau1c47f852006-07-09 08:22:27 +0200650 if (!*args[1]) {
651 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
652 file, linenum, args[0]);
653 return -1;
654 }
655
656 if (curproxy->monitor_uri != NULL)
657 free(curproxy->monitor_uri);
658
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100659 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200660 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100661 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200662 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
663
664 return 0;
665 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
667 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
668 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
669 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
670 else {
671 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
672 return -1;
673 }
674 }
675 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
676 curproxy->state = PR_STSTOPPED;
677 }
678 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
679 curproxy->state = PR_STNEW;
680 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200681 else if (!strcmp(args[0], "acl")) { /* add an ACL */
682 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
683 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
684 file, linenum, args[1]);
685 return -1;
686 }
687 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 else if (!strcmp(args[0], "cookie")) { /* cookie name */
689 int cur_arg;
690 // if (curproxy == &defproxy) {
691 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
692 // return -1;
693 // }
694
Willy Tarreau977b8e42006-12-29 14:19:17 +0100695 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
696 return 0;
697
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 if (curproxy->cookie_name != NULL) {
699 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
700 // file, linenum);
701 // return 0;
702 free(curproxy->cookie_name);
703 }
704
705 if (*(args[1]) == 0) {
706 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
707 file, linenum, args[0]);
708 return -1;
709 }
710 curproxy->cookie_name = strdup(args[1]);
711 curproxy->cookie_len = strlen(curproxy->cookie_name);
712
713 cur_arg = 2;
714 while (*(args[cur_arg])) {
715 if (!strcmp(args[cur_arg], "rewrite")) {
716 curproxy->options |= PR_O_COOK_RW;
717 }
718 else if (!strcmp(args[cur_arg], "indirect")) {
719 curproxy->options |= PR_O_COOK_IND;
720 }
721 else if (!strcmp(args[cur_arg], "insert")) {
722 curproxy->options |= PR_O_COOK_INS;
723 }
724 else if (!strcmp(args[cur_arg], "nocache")) {
725 curproxy->options |= PR_O_COOK_NOC;
726 }
727 else if (!strcmp(args[cur_arg], "postonly")) {
728 curproxy->options |= PR_O_COOK_POST;
729 }
730 else if (!strcmp(args[cur_arg], "prefix")) {
731 curproxy->options |= PR_O_COOK_PFX;
732 }
733 else {
734 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
735 file, linenum, args[0]);
736 return -1;
737 }
738 cur_arg++;
739 }
740 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
741 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
742 file, linenum);
743 return -1;
744 }
745
746 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
747 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
748 file, linenum);
749 return -1;
750 }
751 }/* end else if (!strcmp(args[0], "cookie")) */
752 else if (!strcmp(args[0], "appsession")) { /* cookie name */
753 // if (curproxy == &defproxy) {
754 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
755 // return -1;
756 // }
757
Willy Tarreau977b8e42006-12-29 14:19:17 +0100758 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
759 return 0;
760
Willy Tarreaubaaee002006-06-26 02:48:02 +0200761 if (curproxy->appsession_name != NULL) {
762 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
763 // file, linenum);
764 // return 0;
765 free(curproxy->appsession_name);
766 }
767
768 if (*(args[5]) == 0) {
769 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
770 file, linenum, args[0]);
771 return -1;
772 }
773 have_appsession = 1;
774 curproxy->appsession_name = strdup(args[1]);
775 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
776 curproxy->appsession_len = atoi(args[3]);
Willy Tarreauee991362007-05-14 14:37:50 +0200777 val = atoi(args[5]);
778 if (val > 0)
779 __tv_from_ms(&curproxy->appsession_timeout, val);
780 else
781 tv_eternity(&curproxy->appsession_timeout);
782
Willy Tarreaubaaee002006-06-26 02:48:02 +0200783 rc = chtbl_init(&(curproxy->htbl_proxy), TBLSIZ, hashpjw, match_str, destroy);
784 if (rc) {
785 Alert("Error Init Appsession Hashtable.\n");
786 return -1;
787 }
788 } /* Url App Session */
789 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100790 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
791 return 0;
792
Willy Tarreaubaaee002006-06-26 02:48:02 +0200793 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
794 // if (curproxy == &defproxy) {
795 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
796 // return -1;
797 // }
798
799 if (curproxy->capture_name != NULL) {
800 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
801 // file, linenum, args[0]);
802 // return 0;
803 free(curproxy->capture_name);
804 }
805
806 if (*(args[4]) == 0) {
807 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
808 file, linenum, args[0]);
809 return -1;
810 }
811 curproxy->capture_name = strdup(args[2]);
812 curproxy->capture_namelen = strlen(curproxy->capture_name);
813 curproxy->capture_len = atol(args[4]);
814 if (curproxy->capture_len >= CAPTURE_LEN) {
815 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
816 file, linenum, CAPTURE_LEN - 1);
817 curproxy->capture_len = CAPTURE_LEN - 1;
818 }
819 curproxy->to_log |= LW_COOKIE;
820 }
821 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
822 struct cap_hdr *hdr;
823
824 if (curproxy == &defproxy) {
825 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
826 return -1;
827 }
828
829 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
830 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
831 file, linenum, args[0], args[1]);
832 return -1;
833 }
834
835 hdr = calloc(sizeof(struct cap_hdr), 1);
836 hdr->next = curproxy->req_cap;
837 hdr->name = strdup(args[3]);
838 hdr->namelen = strlen(args[3]);
839 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200840 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200841 hdr->index = curproxy->nb_req_cap++;
842 curproxy->req_cap = hdr;
843 curproxy->to_log |= LW_REQHDR;
844 }
845 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
846 struct cap_hdr *hdr;
847
848 if (curproxy == &defproxy) {
849 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
850 return -1;
851 }
852
853 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
854 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
855 file, linenum, args[0], args[1]);
856 return -1;
857 }
858 hdr = calloc(sizeof(struct cap_hdr), 1);
859 hdr->next = curproxy->rsp_cap;
860 hdr->name = strdup(args[3]);
861 hdr->namelen = strlen(args[3]);
862 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200863 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200864 hdr->index = curproxy->nb_rsp_cap++;
865 curproxy->rsp_cap = hdr;
866 curproxy->to_log |= LW_RSPHDR;
867 }
868 else {
869 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
870 file, linenum, args[0]);
871 return -1;
872 }
873 }
874 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200875 if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200876 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
877 return 0;
878 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100879 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
880 return 0;
881
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882 if (*(args[1]) == 0) {
883 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
884 file, linenum, args[0]);
885 return -1;
886 }
Willy Tarreauee991362007-05-14 14:37:50 +0200887 val = atoi(args[1]);
888 if (val > 0)
889 __tv_from_ms(&curproxy->contimeout, val);
890 else
891 tv_eternity(&curproxy->contimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 }
893 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200894 if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
896 file, linenum, args[0]);
897 return 0;
898 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100899 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
900 return 0;
901
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902 if (*(args[1]) == 0) {
903 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
904 file, linenum, args[0]);
905 return -1;
906 }
Willy Tarreauee991362007-05-14 14:37:50 +0200907 val = atoi(args[1]);
908 if (val > 0)
909 __tv_from_ms(&curproxy->clitimeout, val);
910 else
911 tv_eternity(&curproxy->clitimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200912 }
913 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200914 if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200915 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
916 return 0;
917 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100918 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
919 return 0;
920
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921 if (*(args[1]) == 0) {
922 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
923 file, linenum, args[0]);
924 return -1;
925 }
Willy Tarreauee991362007-05-14 14:37:50 +0200926 val = atoi(args[1]);
927 if (val > 0)
928 __tv_from_ms(&curproxy->srvtimeout, val);
929 else
930 tv_eternity(&curproxy->srvtimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 }
932 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100933 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
934 return 0;
935
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936 if (*(args[1]) == 0) {
937 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
938 file, linenum, args[0]);
939 return -1;
940 }
941 curproxy->conn_retries = atol(args[1]);
942 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200943 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
944 int pol = ACL_COND_NONE;
945 struct acl_cond *cond;
946
947 if (!strcmp(args[1], "if"))
948 pol = ACL_COND_IF;
949 else if (!strcmp(args[1], "unless"))
950 pol = ACL_COND_UNLESS;
951
952 if (pol == ACL_COND_NONE) {
953 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
954 file, linenum, args[0]);
955 return -1;
956 }
957
958 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
959 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
960 file, linenum);
961 return -1;
962 }
963 LIST_ADDQ(&curproxy->block_cond, &cond->list);
964 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200965 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100966 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
967 return 0;
968
Willy Tarreaubaaee002006-06-26 02:48:02 +0200969 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
970 curproxy->uri_auth = NULL; /* we must detach from the default config */
971
972 if (*(args[1]) == 0) {
973 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
974 return -1;
975 } else if (!strcmp(args[1], "uri")) {
976 if (*(args[2]) == 0) {
977 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
978 return -1;
979 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
980 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
981 return -1;
982 }
983 } else if (!strcmp(args[1], "realm")) {
984 if (*(args[2]) == 0) {
985 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
986 return -1;
987 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
988 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
989 return -1;
990 }
991 } else if (!strcmp(args[1], "auth")) {
992 if (*(args[2]) == 0) {
993 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
994 return -1;
995 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
996 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
997 return -1;
998 }
999 } else if (!strcmp(args[1], "scope")) {
1000 if (*(args[2]) == 0) {
1001 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1002 return -1;
1003 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1004 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1005 return -1;
1006 }
1007 } else if (!strcmp(args[1], "enable")) {
1008 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1009 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1010 return -1;
1011 }
1012 } else {
1013 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'uri', 'realm', 'auth' or 'enable').\n",
1014 file, linenum, args[0]);
1015 return -1;
1016 }
1017 }
1018 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001019 int optnum;
1020
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021 if (*(args[1]) == 0) {
1022 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
1023 return -1;
1024 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001025
1026 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1027 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1028 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1029 return 0;
1030 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001031 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001032 return 0;
1033 }
1034 }
1035
1036 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037 /* generate a complete HTTP log */
1038 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1039 else if (!strcmp(args[1], "tcplog"))
1040 /* generate a detailed TCP log */
1041 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 else if (!strcmp(args[1], "tcpka")) {
1043 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001044 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1045 return 0;
1046
1047 if (curproxy->cap & PR_CAP_FE)
1048 curproxy->options |= PR_O_TCP_CLI_KA;
1049 if (curproxy->cap & PR_CAP_BE)
1050 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 }
1052 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001053 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1054 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 /* use HTTP request to check servers' health */
1056 if (curproxy->check_req != NULL) {
1057 free(curproxy->check_req);
1058 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001059 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001060 curproxy->options &= ~PR_O_SMTP_CHK;
1061 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062 if (!*args[2]) { /* no argument */
1063 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1064 curproxy->check_len = strlen(DEF_CHECK_REQ);
1065 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001066 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001067 curproxy->check_req = (char *)malloc(reqlen);
1068 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1069 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1070 } else { /* more arguments : METHOD URI [HTTP_VER] */
1071 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1072 if (*args[4])
1073 reqlen += strlen(args[4]);
1074 else
1075 reqlen += strlen("HTTP/1.0");
1076
1077 curproxy->check_req = (char *)malloc(reqlen);
1078 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1079 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1080 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001081 }
1082 else if (!strcmp(args[1], "ssl-hello-chk")) {
1083 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001084 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1085 return 0;
1086
Willy Tarreauf3c69202006-07-09 16:42:34 +02001087 if (curproxy->check_req != NULL) {
1088 free(curproxy->check_req);
1089 }
1090 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001091 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001092 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001093 }
Willy Tarreau23677902007-05-08 23:50:35 +02001094 else if (!strcmp(args[1], "smtpchk")) {
1095 /* use SMTP request to check servers' health */
1096 if (curproxy->check_req != NULL) {
1097 free(curproxy->check_req);
1098 }
1099 curproxy->options &= ~PR_O_HTTP_CHK;
1100 curproxy->options &= ~PR_O_SSL3_CHK;
1101 curproxy->options |= PR_O_SMTP_CHK;
1102
1103 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1104 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1105 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1106 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1107 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1108 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1109 curproxy->check_req = (char *)malloc(reqlen);
1110 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1111 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1112 } else {
1113 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1114 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1115 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1116 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1117 }
1118 }
1119 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001120 else if (!strcmp(args[1], "forwardfor")) {
1121 /* insert x-forwarded-for field, but not for the
1122 * IP address listed as an except.
1123 */
1124 if (*(args[2])) {
1125 if (!strcmp(args[2], "except")) {
1126 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1127 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1128 file, linenum, args[0]);
1129 return -1;
1130 }
1131 /* flush useless bits */
1132 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1133 } else {
1134 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1135 file, linenum, args[0]);
1136 return -1;
1137 }
1138 }
1139 curproxy->options |= PR_O_FWDFOR;
1140 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 else {
1142 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1143 return -1;
1144 }
1145 return 0;
1146 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001147 else if (!strcmp(args[0], "default_backend")) {
1148 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1149 return 0;
1150
1151 if (*(args[1]) == 0) {
1152 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1153 return -1;
1154 }
1155 if (curproxy->defbe.name)
1156 free(curproxy->defbe.name);
1157 curproxy->defbe.name = strdup(args[1]);
1158 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001160 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1161 return 0;
1162
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 /* enable reconnections to dispatch */
1164 curproxy->options |= PR_O_REDISP;
1165 }
1166#ifdef TPROXY
1167 else if (!strcmp(args[0], "transparent")) {
1168 /* enable transparent proxy connections */
1169 curproxy->options |= PR_O_TRANSP;
1170 }
1171#endif
1172 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001173 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1174 return 0;
1175
Willy Tarreaubaaee002006-06-26 02:48:02 +02001176 if (*(args[1]) == 0) {
1177 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1178 return -1;
1179 }
1180 curproxy->maxconn = atol(args[1]);
1181 }
Willy Tarreau86034312006-12-29 00:10:33 +01001182 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001183 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1184 return 0;
1185
Willy Tarreau86034312006-12-29 00:10:33 +01001186 if (*(args[1]) == 0) {
1187 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1188 return -1;
1189 }
1190 curproxy->fullconn = atol(args[1]);
1191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001192 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1193 if (*(args[1]) == 0) {
1194 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1195 return -1;
1196 }
1197 curproxy->grace = atol(args[1]);
1198 }
1199 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1200 if (curproxy == &defproxy) {
1201 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1202 return -1;
1203 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001204 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1205 return 0;
1206
Willy Tarreaubaaee002006-06-26 02:48:02 +02001207 if (strchr(args[1], ':') == NULL) {
1208 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1209 return -1;
1210 }
1211 curproxy->dispatch_addr = *str2sa(args[1]);
1212 }
1213 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001214 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1215 return 0;
1216
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 if (*(args[1])) {
1218 if (!strcmp(args[1], "roundrobin")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001219 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001220 curproxy->options |= PR_O_BALANCE_RR;
1221 }
1222 else if (!strcmp(args[1], "source")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001223 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224 curproxy->options |= PR_O_BALANCE_SH;
1225 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001226 else if (!strcmp(args[1], "uri")) {
1227 curproxy->options &= ~PR_O_BALANCE;
1228 curproxy->options |= PR_O_BALANCE_UH;
1229 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001230 else {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001231 Alert("parsing [%s:%d] : '%s' only supports 'roundrobin', 'source' and 'uri' options.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001232 return -1;
1233 }
1234 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001235 else {/* if no option is set, use round-robin by default */
1236 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001237 curproxy->options |= PR_O_BALANCE_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001238 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001239 }
1240 else if (!strcmp(args[0], "server")) { /* server address */
1241 int cur_arg;
1242 char *rport;
1243 char *raddr;
1244 short realport;
1245 int do_check;
1246
1247 if (curproxy == &defproxy) {
1248 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1249 return -1;
1250 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001251 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1252 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253
1254 if (!*args[2]) {
1255 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1256 file, linenum, args[0]);
1257 return -1;
1258 }
1259 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1260 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1261 return -1;
1262 }
1263
1264 /* the servers are linked backwards first */
1265 newsrv->next = curproxy->srv;
1266 curproxy->srv = newsrv;
1267 newsrv->proxy = curproxy;
1268
1269 LIST_INIT(&newsrv->pendconns);
1270 do_check = 0;
1271 newsrv->state = SRV_RUNNING; /* early server setup */
1272 newsrv->id = strdup(args[1]);
1273
1274 /* several ways to check the port component :
1275 * - IP => port=+0, relative
1276 * - IP: => port=+0, relative
1277 * - IP:N => port=N, absolute
1278 * - IP:+N => port=+N, relative
1279 * - IP:-N => port=-N, relative
1280 */
1281 raddr = strdup(args[2]);
1282 rport = strchr(raddr, ':');
1283 if (rport) {
1284 *rport++ = 0;
1285 realport = atol(rport);
1286 if (!isdigit((int)*rport))
1287 newsrv->state |= SRV_MAPPORTS;
1288 } else {
1289 realport = 0;
1290 newsrv->state |= SRV_MAPPORTS;
1291 }
1292
1293 newsrv->addr = *str2sa(raddr);
1294 newsrv->addr.sin_port = htons(realport);
1295 free(raddr);
1296
1297 newsrv->curfd = -1; /* no health-check in progress */
1298 newsrv->inter = DEF_CHKINTR;
1299 newsrv->rise = DEF_RISETIME;
1300 newsrv->fall = DEF_FALLTIME;
1301 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001302 newsrv->uweight = 1;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001303
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304 cur_arg = 3;
1305 while (*args[cur_arg]) {
1306 if (!strcmp(args[cur_arg], "cookie")) {
1307 newsrv->cookie = strdup(args[cur_arg + 1]);
1308 newsrv->cklen = strlen(args[cur_arg + 1]);
1309 cur_arg += 2;
1310 }
1311 else if (!strcmp(args[cur_arg], "rise")) {
1312 newsrv->rise = atol(args[cur_arg + 1]);
1313 newsrv->health = newsrv->rise;
1314 cur_arg += 2;
1315 }
1316 else if (!strcmp(args[cur_arg], "fall")) {
1317 newsrv->fall = atol(args[cur_arg + 1]);
1318 cur_arg += 2;
1319 }
1320 else if (!strcmp(args[cur_arg], "inter")) {
1321 newsrv->inter = atol(args[cur_arg + 1]);
1322 cur_arg += 2;
1323 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001324 else if (!strcmp(args[cur_arg], "addr")) {
1325 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001326 cur_arg += 2;
1327 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001328 else if (!strcmp(args[cur_arg], "port")) {
1329 newsrv->check_port = atol(args[cur_arg + 1]);
1330 cur_arg += 2;
1331 }
1332 else if (!strcmp(args[cur_arg], "backup")) {
1333 newsrv->state |= SRV_BACKUP;
1334 cur_arg ++;
1335 }
1336 else if (!strcmp(args[cur_arg], "weight")) {
1337 int w;
1338 w = atol(args[cur_arg + 1]);
1339 if (w < 1 || w > 256) {
1340 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1341 file, linenum, newsrv->id, w);
1342 return -1;
1343 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001344 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001345 cur_arg += 2;
1346 }
1347 else if (!strcmp(args[cur_arg], "minconn")) {
1348 newsrv->minconn = atol(args[cur_arg + 1]);
1349 cur_arg += 2;
1350 }
1351 else if (!strcmp(args[cur_arg], "maxconn")) {
1352 newsrv->maxconn = atol(args[cur_arg + 1]);
1353 cur_arg += 2;
1354 }
1355 else if (!strcmp(args[cur_arg], "check")) {
1356 global.maxsock++;
1357 do_check = 1;
1358 cur_arg += 1;
1359 }
1360 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1361 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001362#ifdef CONFIG_HAP_CTTPROXY
1363 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1364 file, linenum, "source", "usesrc");
1365#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001366 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1367 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001368#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001369 return -1;
1370 }
1371 newsrv->state |= SRV_BIND_SRC;
1372 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1373 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001374 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001375#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001376 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001377 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1378 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001379 return -1;
1380 }
1381 if (!*args[cur_arg + 1]) {
1382 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1383 file, linenum, "usesrc");
1384 return -1;
1385 }
1386 if (!strcmp(args[cur_arg + 1], "client")) {
1387 newsrv->state |= SRV_TPROXY_CLI;
1388 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1389 newsrv->state |= SRV_TPROXY_CIP;
1390 } else {
1391 newsrv->state |= SRV_TPROXY_ADDR;
1392 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1393 }
1394 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1395 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001396#else /* no CTTPROXY support */
1397 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1398 file, linenum, "usesrc");
1399 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001400#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001401 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001403#ifdef CONFIG_HAP_CTTPROXY
1404 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1405 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1406 file, linenum, "usesrc", "source");
1407 return -1;
1408 }
1409#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410 else {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001411 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 +02001412 file, linenum, newsrv->id);
1413 return -1;
1414 }
1415 }
1416
1417 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001418 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1419 newsrv->check_port = newsrv->check_addr.sin_port;
1420
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1422 newsrv->check_port = realport; /* by default */
1423 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001424 /* not yet valid, because no port was set on
1425 * the server either. We'll check if we have
1426 * a known port on the first listener.
1427 */
1428 struct listener *l;
1429 l = curproxy->listen;
1430 if (l) {
1431 int port;
1432 port = (l->addr.ss_family == AF_INET6)
1433 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1434 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1435 newsrv->check_port = port;
1436 }
1437 }
1438 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1440 file, linenum, newsrv->id);
1441 return -1;
1442 }
1443 newsrv->state |= SRV_CHECKED;
1444 }
1445
1446 if (newsrv->state & SRV_BACKUP)
1447 curproxy->srv_bck++;
1448 else
1449 curproxy->srv_act++;
1450 }
1451 else if (!strcmp(args[0], "log")) { /* syslog server address */
1452 struct sockaddr_in *sa;
1453 int facility;
1454
1455 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1456 curproxy->logfac1 = global.logfac1;
1457 curproxy->logsrv1 = global.logsrv1;
1458 curproxy->loglev1 = global.loglev1;
1459 curproxy->logfac2 = global.logfac2;
1460 curproxy->logsrv2 = global.logsrv2;
1461 curproxy->loglev2 = global.loglev2;
1462 }
1463 else if (*(args[1]) && *(args[2])) {
1464 int level;
1465
1466 facility = get_log_facility(args[2]);
1467 if (facility < 0) {
1468 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1469 exit(1);
1470 }
1471
1472 level = 7; /* max syslog level = debug */
1473 if (*(args[3])) {
1474 level = get_log_level(args[3]);
1475 if (level < 0) {
1476 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1477 exit(1);
1478 }
1479 }
1480
1481 sa = str2sa(args[1]);
1482 if (!sa->sin_port)
1483 sa->sin_port = htons(SYSLOG_PORT);
1484
1485 if (curproxy->logfac1 == -1) {
1486 curproxy->logsrv1 = *sa;
1487 curproxy->logfac1 = facility;
1488 curproxy->loglev1 = level;
1489 }
1490 else if (curproxy->logfac2 == -1) {
1491 curproxy->logsrv2 = *sa;
1492 curproxy->logfac2 = facility;
1493 curproxy->loglev2 = level;
1494 }
1495 else {
1496 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1497 return -1;
1498 }
1499 }
1500 else {
1501 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1502 file, linenum);
1503 return -1;
1504 }
1505 }
1506 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001507 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1508 return 0;
1509
Willy Tarreaubaaee002006-06-26 02:48:02 +02001510 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001511#ifdef CONFIG_HAP_CTTPROXY
1512 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1513 file, linenum, "source", "usesrc");
1514#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1516 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001517#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001518 return -1;
1519 }
1520
1521 curproxy->source_addr = *str2sa(args[1]);
1522 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001523 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001524#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001525 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1526 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1527 file, linenum, "usesrc");
1528 return -1;
1529 }
1530 if (!*args[3]) {
1531 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1532 file, linenum, "usesrc");
1533 return -1;
1534 }
1535
1536 if (!strcmp(args[3], "client")) {
1537 curproxy->options |= PR_O_TPXY_CLI;
1538 } else if (!strcmp(args[3], "clientip")) {
1539 curproxy->options |= PR_O_TPXY_CIP;
1540 } else {
1541 curproxy->options |= PR_O_TPXY_ADDR;
1542 curproxy->tproxy_addr = *str2sa(args[3]);
1543 }
1544 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001545#else /* no CTTPROXY support */
1546 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1547 file, linenum, "usesrc");
1548 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001549#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001550 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001551 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001552#ifdef CONFIG_HAP_CTTPROXY
1553 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1554 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1555 file, linenum, "usesrc", "source");
1556 return -1;
1557 }
1558#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1560 regex_t *preg;
1561 if (curproxy == &defproxy) {
1562 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1563 return -1;
1564 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001565 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1566 return 0;
1567
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 if (*(args[1]) == 0 || *(args[2]) == 0) {
1569 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1570 file, linenum, args[0]);
1571 return -1;
1572 }
1573
1574 preg = calloc(1, sizeof(regex_t));
1575 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1576 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1577 return -1;
1578 }
1579
1580 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1581 if (err) {
1582 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1583 file, linenum, *err);
1584 return -1;
1585 }
1586 }
1587 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1588 regex_t *preg;
1589 if (curproxy == &defproxy) {
1590 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1591 return -1;
1592 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001593 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1594 return 0;
1595
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 if (*(args[1]) == 0) {
1597 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1598 return -1;
1599 }
1600
1601 preg = calloc(1, sizeof(regex_t));
1602 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1603 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1604 return -1;
1605 }
1606
1607 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1608 }
1609 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1610 regex_t *preg;
1611 if (curproxy == &defproxy) {
1612 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1613 return -1;
1614 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001615 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1616 return 0;
1617
Willy Tarreaubaaee002006-06-26 02:48:02 +02001618 if (*(args[1]) == 0) {
1619 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1620 return -1;
1621 }
1622
1623 preg = calloc(1, sizeof(regex_t));
1624 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1625 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1626 return -1;
1627 }
1628
1629 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1630 }
1631 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1632 regex_t *preg;
1633 if (curproxy == &defproxy) {
1634 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1635 return -1;
1636 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001637 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1638 return 0;
1639
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640 if (*(args[1]) == 0) {
1641 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1642 return -1;
1643 }
1644
1645 preg = calloc(1, sizeof(regex_t));
1646 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1647 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1648 return -1;
1649 }
1650
1651 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1652 }
1653 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1654 regex_t *preg;
1655 if (curproxy == &defproxy) {
1656 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1657 return -1;
1658 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001659 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1660 return 0;
1661
Willy Tarreaubaaee002006-06-26 02:48:02 +02001662 if (*(args[1]) == 0) {
1663 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1664 return -1;
1665 }
1666
1667 preg = calloc(1, sizeof(regex_t));
1668 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1669 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1670 return -1;
1671 }
1672
1673 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1674 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001675 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1676 regex_t *preg;
1677 if (curproxy == &defproxy) {
1678 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1679 return -1;
1680 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001681 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1682 return 0;
1683
Willy Tarreaub8750a82006-09-03 09:56:00 +02001684 if (*(args[1]) == 0) {
1685 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1686 return -1;
1687 }
1688
1689 preg = calloc(1, sizeof(regex_t));
1690 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1691 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1692 return -1;
1693 }
1694
1695 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1696 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001697 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1698 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001699 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001700 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1701 return -1;
1702 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001703 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1704 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001705
Willy Tarreau977b8e42006-12-29 14:19:17 +01001706 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001707 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1708 file, linenum, args[0]);
1709 return -1;
1710 }
1711
1712 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001713 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001714 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1715 }
1716
1717 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1718 }
1719 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1720 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001721 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001722 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1723 return -1;
1724 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001725 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1726 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001727
Willy Tarreau977b8e42006-12-29 14:19:17 +01001728 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001729 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1730 file, linenum, args[0]);
1731 return -1;
1732 }
1733
1734 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001735 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001736 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1737 }
1738
1739 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1740 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001741 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1742 regex_t *preg;
1743 if (curproxy == &defproxy) {
1744 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1745 return -1;
1746 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001747 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1748 return 0;
1749
Willy Tarreaubaaee002006-06-26 02:48:02 +02001750 if (*(args[1]) == 0 || *(args[2]) == 0) {
1751 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1752 file, linenum, args[0]);
1753 return -1;
1754 }
1755
1756 preg = calloc(1, sizeof(regex_t));
1757 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1758 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1759 return -1;
1760 }
1761
1762 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1763 if (err) {
1764 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1765 file, linenum, *err);
1766 return -1;
1767 }
1768 }
1769 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1770 regex_t *preg;
1771 if (curproxy == &defproxy) {
1772 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1773 return -1;
1774 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001775 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1776 return 0;
1777
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 if (*(args[1]) == 0) {
1779 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1780 return -1;
1781 }
1782
1783 preg = calloc(1, sizeof(regex_t));
1784 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1785 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1786 return -1;
1787 }
1788
1789 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1790 }
1791 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1792 regex_t *preg;
1793 if (curproxy == &defproxy) {
1794 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1795 return -1;
1796 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001797 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1798 return 0;
1799
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800 if (*(args[1]) == 0) {
1801 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1802 return -1;
1803 }
1804
1805 preg = calloc(1, sizeof(regex_t));
1806 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1807 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1808 return -1;
1809 }
1810
1811 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1812 }
1813 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1814 regex_t *preg;
1815 if (curproxy == &defproxy) {
1816 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1817 return -1;
1818 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001819 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1820 return 0;
1821
Willy Tarreaubaaee002006-06-26 02:48:02 +02001822 if (*(args[1]) == 0) {
1823 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1824 return -1;
1825 }
1826
1827 preg = calloc(1, sizeof(regex_t));
1828 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1829 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1830 return -1;
1831 }
1832
1833 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1834 }
1835 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1836 regex_t *preg;
1837 if (curproxy == &defproxy) {
1838 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1839 return -1;
1840 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001841 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1842 return 0;
1843
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844 if (*(args[1]) == 0) {
1845 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1846 return -1;
1847 }
1848
1849 preg = calloc(1, sizeof(regex_t));
1850 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1851 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1852 return -1;
1853 }
1854
1855 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1856 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001857 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1858 regex_t *preg;
1859 if (curproxy == &defproxy) {
1860 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1861 return -1;
1862 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001863 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1864 return 0;
1865
Willy Tarreaub8750a82006-09-03 09:56:00 +02001866 if (*(args[1]) == 0) {
1867 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1868 return -1;
1869 }
1870
1871 preg = calloc(1, sizeof(regex_t));
1872 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1873 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1874 return -1;
1875 }
1876
1877 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1878 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001879 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1880 if (curproxy == &defproxy) {
1881 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1882 return -1;
1883 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001884 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1885 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001886
1887 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
1888 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1889 return 0;
1890 }
1891
1892 if (*(args[1]) == 0) {
1893 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1894 return -1;
1895 }
1896
1897 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
1898 }
1899 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
1900 regex_t *preg;
1901
1902 if (*(args[1]) == 0 || *(args[2]) == 0) {
1903 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1904 file, linenum, args[0]);
1905 return -1;
1906 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001907 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1908 return 0;
1909
Willy Tarreaubaaee002006-06-26 02:48:02 +02001910 preg = calloc(1, sizeof(regex_t));
1911 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1912 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1913 return -1;
1914 }
1915
1916 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1917 if (err) {
1918 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1919 file, linenum, *err);
1920 return -1;
1921 }
1922 }
1923 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
1924 regex_t *preg;
1925 if (curproxy == &defproxy) {
1926 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1927 return -1;
1928 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001929 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1930 return 0;
1931
Willy Tarreaubaaee002006-06-26 02:48:02 +02001932 if (*(args[1]) == 0) {
1933 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1934 return -1;
1935 }
1936
1937 preg = calloc(1, sizeof(regex_t));
1938 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1939 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1940 return -1;
1941 }
1942
1943 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
1944 if (err) {
1945 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1946 file, linenum, *err);
1947 return -1;
1948 }
1949 }
1950 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
1951 regex_t *preg;
1952 if (curproxy == &defproxy) {
1953 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1954 return -1;
1955 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001956 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1957 return 0;
1958
Willy Tarreaubaaee002006-06-26 02:48:02 +02001959 if (*(args[1]) == 0) {
1960 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1961 return -1;
1962 }
1963
1964 preg = calloc(1, sizeof(regex_t));
1965 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1966 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1967 return -1;
1968 }
1969
1970 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
1971 if (err) {
1972 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1973 file, linenum, *err);
1974 return -1;
1975 }
1976 }
1977 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
1978 regex_t *preg;
1979 if (curproxy == &defproxy) {
1980 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1981 return -1;
1982 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001983 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1984 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001985
1986 if (*(args[1]) == 0 || *(args[2]) == 0) {
1987 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1988 file, linenum, args[0]);
1989 return -1;
1990 }
1991
1992 preg = calloc(1, sizeof(regex_t));
1993 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1994 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1995 return -1;
1996 }
1997
1998 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1999 if (err) {
2000 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2001 file, linenum, *err);
2002 return -1;
2003 }
2004 }
2005 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2006 regex_t *preg;
2007 if (curproxy == &defproxy) {
2008 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2009 return -1;
2010 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002011 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2012 return 0;
2013
Willy Tarreaubaaee002006-06-26 02:48:02 +02002014 if (*(args[1]) == 0) {
2015 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2016 return -1;
2017 }
2018
2019 preg = calloc(1, sizeof(regex_t));
2020 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2021 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2022 return -1;
2023 }
2024
2025 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2026 if (err) {
2027 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2028 file, linenum, *err);
2029 return -1;
2030 }
2031 }
2032 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2033 regex_t *preg;
2034 if (curproxy == &defproxy) {
2035 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2036 return -1;
2037 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002038 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2039 return 0;
2040
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041 if (*(args[1]) == 0) {
2042 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2043 return -1;
2044 }
2045
2046 preg = calloc(1, sizeof(regex_t));
2047 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2048 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2049 return -1;
2050 }
2051
2052 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2053 if (err) {
2054 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2055 file, linenum, *err);
2056 return -1;
2057 }
2058 }
2059 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2060 if (curproxy == &defproxy) {
2061 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2062 return -1;
2063 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002064 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2065 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066
2067 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2068 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2069 return 0;
2070 }
2071
2072 if (*(args[1]) == 0) {
2073 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2074 return -1;
2075 }
2076
2077 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2078 }
2079 else if (!strcmp(args[0], "errorloc") ||
2080 !strcmp(args[0], "errorloc302") ||
2081 !strcmp(args[0], "errorloc303")) { /* error location */
2082 int errnum, errlen;
2083 char *err;
2084
2085 // if (curproxy == &defproxy) {
2086 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2087 // return -1;
2088 // }
2089
Willy Tarreau977b8e42006-12-29 14:19:17 +01002090 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2091 return 0;
2092
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002094 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 return -1;
2096 }
2097
2098 errnum = atol(args[1]);
2099 if (!strcmp(args[0], "errorloc303")) {
2100 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2101 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2102 } else {
2103 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2104 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2105 }
2106
Willy Tarreau0f772532006-12-23 20:51:41 +01002107 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2108 if (http_err_codes[rc] == errnum) {
2109 if (curproxy->errmsg[rc].str)
2110 free(curproxy->errmsg[rc].str);
2111 curproxy->errmsg[rc].str = err;
2112 curproxy->errmsg[rc].len = errlen;
2113 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002115 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002116
2117 if (rc >= HTTP_ERR_SIZE) {
2118 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2119 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002120 free(err);
2121 }
2122 }
2123 else {
2124 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2125 return -1;
2126 }
2127 return 0;
2128}
2129
2130
2131/*
2132 * This function reads and parses the configuration file given in the argument.
2133 * returns 0 if OK, -1 if error.
2134 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002135int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002136{
2137 char thisline[256];
2138 char *line;
2139 FILE *f;
2140 int linenum = 0;
2141 char *end;
Willy Tarreau540abe42007-05-02 20:50:16 +02002142 char *args[MAX_LINE_ARGS + 1];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002143 int arg;
2144 int cfgerr = 0;
Willy Tarreau80587432006-12-24 17:47:20 +01002145 int nbchk, mininter;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002146 int confsect = CFG_NONE;
2147
2148 struct proxy *curproxy = NULL;
2149 struct server *newsrv = NULL;
2150
2151 if ((f=fopen(file,"r")) == NULL)
2152 return -1;
2153
2154 init_default_instance();
2155
2156 while (fgets(line = thisline, sizeof(thisline), f) != NULL) {
2157 linenum++;
2158
2159 end = line + strlen(line);
2160
2161 /* skip leading spaces */
2162 while (isspace((int)*line))
2163 line++;
2164
2165 arg = 0;
2166 args[arg] = line;
2167
2168 while (*line && arg < MAX_LINE_ARGS) {
2169 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2170 * C equivalent value. Other combinations left unchanged (eg: \1).
2171 */
2172 if (*line == '\\') {
2173 int skip = 0;
2174 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2175 *line = line[1];
2176 skip = 1;
2177 }
2178 else if (line[1] == 'r') {
2179 *line = '\r';
2180 skip = 1;
2181 }
2182 else if (line[1] == 'n') {
2183 *line = '\n';
2184 skip = 1;
2185 }
2186 else if (line[1] == 't') {
2187 *line = '\t';
2188 skip = 1;
2189 }
2190 else if (line[1] == 'x') {
2191 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2192 unsigned char hex1, hex2;
2193 hex1 = toupper(line[2]) - '0';
2194 hex2 = toupper(line[3]) - '0';
2195 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2196 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2197 *line = (hex1<<4) + hex2;
2198 skip = 3;
2199 }
2200 else {
2201 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2202 return -1;
2203 }
2204 }
2205 if (skip) {
2206 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2207 end -= skip;
2208 }
2209 line++;
2210 }
2211 else if (*line == '#' || *line == '\n' || *line == '\r') {
2212 /* end of string, end of loop */
2213 *line = 0;
2214 break;
2215 }
2216 else if (isspace((int)*line)) {
2217 /* a non-escaped space is an argument separator */
2218 *line++ = 0;
2219 while (isspace((int)*line))
2220 line++;
2221 args[++arg] = line;
2222 }
2223 else {
2224 line++;
2225 }
2226 }
2227
2228 /* empty line */
2229 if (!**args)
2230 continue;
2231
Willy Tarreau540abe42007-05-02 20:50:16 +02002232 /* zero out remaining args and ensure that at least one entry
2233 * is zeroed out.
2234 */
2235 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 args[arg] = line;
2237 }
2238
Willy Tarreau977b8e42006-12-29 14:19:17 +01002239 if (!strcmp(args[0], "listen") ||
2240 !strcmp(args[0], "frontend") ||
2241 !strcmp(args[0], "backend") ||
2242 !strcmp(args[0], "ruleset") ||
2243 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002244 confsect = CFG_LISTEN;
2245 else if (!strcmp(args[0], "global")) /* global config */
2246 confsect = CFG_GLOBAL;
2247 /* else it's a section keyword */
2248
2249 switch (confsect) {
2250 case CFG_LISTEN:
2251 if (cfg_parse_listen(file, linenum, args) < 0)
2252 return -1;
2253 break;
2254 case CFG_GLOBAL:
2255 if (cfg_parse_global(file, linenum, args) < 0)
2256 return -1;
2257 break;
2258 default:
2259 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2260 return -1;
2261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002262 }
2263 fclose(f);
2264
2265 /*
2266 * Now, check for the integrity of all that we have collected.
2267 */
2268
2269 /* will be needed further to delay some tasks */
2270 tv_now(&now);
2271
2272 if ((curproxy = proxy) == NULL) {
2273 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2274 file);
2275 return -1;
2276 }
2277
2278 while (curproxy != NULL) {
2279 if (curproxy->state == PR_STSTOPPED) {
2280 curproxy = curproxy->next;
2281 continue;
2282 }
2283
Willy Tarreau977b8e42006-12-29 14:19:17 +01002284 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2285 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 +01002286 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002287 cfgerr++;
2288 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002289 else if (curproxy->cap & PR_CAP_BE &&
2290 ((curproxy->mode != PR_MODE_HEALTH) &&
2291 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
2292 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2293 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 +01002294 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295 cfgerr++;
2296 }
2297 else if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
2298 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002299 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002300 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 cfgerr++;
2302 }
2303#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2304 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002305 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002306 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002307 cfgerr++;
2308 }
2309#endif
2310 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002311 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002312 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002313 }
2314 }
2315 else if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2316 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002317 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002318 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 }
2320 if ((newsrv = curproxy->srv) != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002321 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002322 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323 }
2324 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002325 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002326 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002327 }
2328 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002329 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002330 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002332 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002333 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002334 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002335 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002336 if (curproxy->options & PR_O_BALANCE_UH) {
2337 curproxy->options &= ~PR_O_BALANCE;
2338 curproxy->options |= PR_O_BALANCE_RR;
2339
2340 Warning("parsing %s : URI hash will be ignored for %s '%s'. Falling back to round robin.\n",
2341 file, proxy_type_str(curproxy), curproxy->id);
2342 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002343 }
2344 else if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
2345 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2346 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2347 file, curproxy->id);
2348 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002349 }
2350 }
2351
2352 /* if a default backend was specified, let's find it */
2353 if (curproxy->defbe.name) {
2354 struct proxy *target;
2355
2356 for (target = proxy; target != NULL; target = target->next) {
2357 if (strcmp(target->id, curproxy->defbe.name) == 0)
2358 break;
2359 }
2360 if (target == NULL) {
2361 Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n",
2362 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2363 cfgerr++;
2364 } else if (target == curproxy) {
2365 Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
2366 cfgerr++;
2367 } else if (!(target->cap & PR_CAP_BE)) {
2368 Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n",
2369 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2370 cfgerr++;
2371 } else if (target->mode != curproxy->mode) {
2372 Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
2373 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2374 cfgerr++;
2375 } else {
2376 free(curproxy->defbe.name);
2377 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 }
2379 }
2380
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002381 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002382 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2383 /* map jump target for ACT_SETBE in req_rep chain */
2384 struct hdr_exp *exp;
2385 struct proxy *target;
2386 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
2387 if (exp->action != ACT_SETBE)
2388 continue;
2389 for (target = proxy; target != NULL; target = target->next) {
2390 if (strcmp(target->id, exp->replace) == 0)
2391 break;
2392 }
2393 if (target == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002394 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002395 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaua496b602006-12-17 23:15:24 +01002396 cfgerr++;
2397 } else if (target == curproxy) {
2398 Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
2399 cfgerr++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002400 } else if (!(target->cap & PR_CAP_BE)) {
2401 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002402 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002403 cfgerr++;
2404 } else if (target->mode != PR_MODE_HTTP) {
2405 Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002406 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002407 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002408 } else {
2409 free((void *)exp->replace);
2410 exp->replace = (const char *)target;
2411 }
2412 }
2413 }
Willy Tarreau2738a142006-07-08 17:28:09 +02002414 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002415 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2416 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2417 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002418 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002419 " | While not properly invalid, you will certainly encounter various problems\n"
2420 " | with such a configuration. To fix this, please ensure that all following\n"
2421 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002422 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002423 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002424
2425 if (curproxy->options & PR_O_SSL3_CHK) {
2426 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2427 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2428 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2429 }
2430
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002431 /* The small pools required for the capture lists */
2432 if (curproxy->nb_req_cap)
2433 curproxy->req_cap_pool = create_pool("ptrcap",
2434 curproxy->nb_req_cap * sizeof(char *),
2435 MEM_F_SHARED);
2436 if (curproxy->nb_rsp_cap)
2437 curproxy->rsp_cap_pool = create_pool("ptrcap",
2438 curproxy->nb_rsp_cap * sizeof(char *),
2439 MEM_F_SHARED);
2440
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002441 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2442 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2443 MEM_F_SHARED);
2444
Willy Tarreau86034312006-12-29 00:10:33 +01002445 /* for backwards compatibility with "listen" instances, if
2446 * fullconn is not set but maxconn is set, then maxconn
2447 * is used.
2448 */
2449 if (!curproxy->fullconn)
2450 curproxy->fullconn = curproxy->maxconn;
2451
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 /* first, we will invert the servers list order */
2453 newsrv = NULL;
2454 while (curproxy->srv) {
2455 struct server *next;
2456
2457 next = curproxy->srv->next;
2458 curproxy->srv->next = newsrv;
2459 newsrv = curproxy->srv;
2460 if (!next)
2461 break;
2462 curproxy->srv = next;
2463 }
2464
2465 /* now, newsrv == curproxy->srv */
2466 if (newsrv) {
2467 struct server *srv;
2468 int pgcd;
2469 int act, bck;
2470
2471 /* We will factor the weights to reduce the table,
2472 * using Euclide's largest common divisor algorithm
2473 */
Willy Tarreau417fae02007-03-25 21:16:40 +02002474 pgcd = newsrv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2476 int t, w;
2477
Willy Tarreau417fae02007-03-25 21:16:40 +02002478 w = srv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002479 while (w) {
2480 t = pgcd % w;
2481 pgcd = w;
2482 w = t;
2483 }
2484 }
2485
2486 act = bck = 0;
2487 for (srv = newsrv; srv; srv = srv->next) {
Willy Tarreau417fae02007-03-25 21:16:40 +02002488 srv->eweight = srv->uweight / pgcd;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 if (srv->state & SRV_BACKUP)
Willy Tarreau417fae02007-03-25 21:16:40 +02002490 bck += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491 else
Willy Tarreau417fae02007-03-25 21:16:40 +02002492 act += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002493 }
2494
2495 /* this is the largest map we will ever need for this servers list */
2496 if (act < bck)
2497 act = bck;
2498
2499 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2500 /* recounts servers and their weights */
2501 recount_servers(curproxy);
2502 recalc_server_map(curproxy);
2503 }
2504
2505 if (curproxy->options & PR_O_LOGASAP)
2506 curproxy->to_log &= ~LW_BYTES;
2507
Willy Tarreaubaaee002006-06-26 02:48:02 +02002508 /*
2509 * If this server supports a maxconn parameter, it needs a dedicated
2510 * tasks to fill the emptied slots when a connection leaves.
2511 */
2512 newsrv = curproxy->srv;
2513 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002514 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515 /* Only 'minconn' was specified, or it was higher than or equal
2516 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2517 * this will avoid further useless expensive computations.
2518 */
2519 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002520 } else if (newsrv->maxconn && !newsrv->minconn) {
2521 /* minconn was not specified, so we set it to maxconn */
2522 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002523 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2524 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002525 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002526 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 }
2528
2529 if (newsrv->maxconn > 0) {
2530 struct task *t;
2531
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002532 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2534 return -1;
2535 }
2536
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002537 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002538 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002539 t->state = TASK_IDLE;
2540 t->process = process_srv_queue;
2541 t->context = newsrv;
2542 newsrv->queue_mgt = t;
2543
2544 /* never run it unless specifically woken up */
2545 tv_eternity(&t->expire);
2546 task_queue(t);
2547 }
2548 newsrv = newsrv->next;
2549 }
2550
2551 /* now we'll start this proxy's health checks if any */
2552 /* 1- count the checkers to run simultaneously */
2553 nbchk = 0;
2554 mininter = 0;
2555 newsrv = curproxy->srv;
2556 while (newsrv != NULL) {
2557 if (newsrv->state & SRV_CHECKED) {
2558 if (!mininter || mininter > newsrv->inter)
2559 mininter = newsrv->inter;
2560 nbchk++;
2561 }
2562 newsrv = newsrv->next;
2563 }
2564
2565 /* 2- start them as far as possible from each others while respecting
2566 * their own intervals. For this, we will start them after their own
2567 * interval added to the min interval divided by the number of servers,
2568 * weighted by the server's position in the list.
2569 */
2570 if (nbchk > 0) {
2571 struct task *t;
2572 int srvpos;
2573
2574 newsrv = curproxy->srv;
2575 srvpos = 0;
2576 while (newsrv != NULL) {
2577 /* should this server be checked ? */
2578 if (newsrv->state & SRV_CHECKED) {
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002579 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2581 return -1;
2582 }
2583
Willy Tarreau964c9362007-01-07 00:38:00 +01002584 t->wq = NULL;
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002585 t->qlist.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 t->state = TASK_IDLE;
2587 t->process = process_chk;
2588 t->context = newsrv;
2589
2590 /* check this every ms */
Willy Tarreau42aae5c2007-04-29 17:43:56 +02002591 tv_ms_add(&t->expire, &now,
2592 newsrv->inter + mininter * srvpos / nbchk);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 task_queue(t);
2594 //task_wakeup(&rq, t);
2595 srvpos++;
2596 }
2597 newsrv = newsrv->next;
2598 }
2599 }
2600
2601 curproxy = curproxy->next;
2602 }
2603 if (cfgerr > 0) {
2604 Alert("Errors found in configuration file, aborting.\n");
2605 return -1;
2606 }
2607 else
2608 return 0;
2609}
2610
2611
2612
2613/*
2614 * Local variables:
2615 * c-indent-level: 8
2616 * c-basic-offset: 8
2617 * End:
2618 */