blob: 1edaa8fc0b52068df8eb67e8c39bb7c185c47151 [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 Tarreaubaaee002006-06-26 02:48:02 +0200467 int rc;
468
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
499 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100500 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200501
502 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100503 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200504 curproxy->listen = str2listener(args[2], curproxy->listen);
505 if (!curproxy->listen)
506 return -1;
507 global.maxsock++;
508 }
509
510 /* set default values */
511 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200512 curproxy->options = defproxy.options;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200513 curproxy->except_net = defproxy.except_net;
514 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200515
Willy Tarreau977b8e42006-12-29 14:19:17 +0100516 if (curproxy->cap & PR_CAP_FE) {
517 curproxy->maxconn = defproxy.maxconn;
518
519 /* initialize error relocations */
520 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
521 if (defproxy.errmsg[rc].str)
522 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
523 }
524
525 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527
Willy Tarreau977b8e42006-12-29 14:19:17 +0100528 if (curproxy->cap & PR_CAP_BE) {
529 curproxy->fullconn = defproxy.fullconn;
530 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200531
Willy Tarreau977b8e42006-12-29 14:19:17 +0100532 if (defproxy.check_req)
533 curproxy->check_req = strdup(defproxy.check_req);
534 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200535
Willy Tarreau977b8e42006-12-29 14:19:17 +0100536 if (defproxy.cookie_name)
537 curproxy->cookie_name = strdup(defproxy.cookie_name);
538 curproxy->cookie_len = defproxy.cookie_len;
539 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200540
Willy Tarreau977b8e42006-12-29 14:19:17 +0100541 if (curproxy->cap & PR_CAP_RS) {
542 if (defproxy.capture_name)
543 curproxy->capture_name = strdup(defproxy.capture_name);
544 curproxy->capture_namelen = defproxy.capture_namelen;
545 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200547
Willy Tarreau977b8e42006-12-29 14:19:17 +0100548 if (curproxy->cap & PR_CAP_FE) {
549 curproxy->clitimeout = defproxy.clitimeout;
550 curproxy->uri_auth = defproxy.uri_auth;
551 curproxy->mon_net = defproxy.mon_net;
552 curproxy->mon_mask = defproxy.mon_mask;
553 if (defproxy.monitor_uri)
554 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
555 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100556 if (defproxy.defbe.name)
557 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100558 }
559
560 if (curproxy->cap & PR_CAP_BE) {
561 curproxy->contimeout = defproxy.contimeout;
562 curproxy->srvtimeout = defproxy.srvtimeout;
563 curproxy->source_addr = defproxy.source_addr;
564 }
565
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566 curproxy->mode = defproxy.mode;
567 curproxy->logfac1 = defproxy.logfac1;
568 curproxy->logsrv1 = defproxy.logsrv1;
569 curproxy->loglev1 = defproxy.loglev1;
570 curproxy->logfac2 = defproxy.logfac2;
571 curproxy->logsrv2 = defproxy.logsrv2;
572 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200573 curproxy->grace = defproxy.grace;
Willy Tarreau1c47f852006-07-09 08:22:27 +0200574
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575 return 0;
576 }
577 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
578 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100579 /* FIXME-20070101: we should do this too at the end of the
580 * config parsing to free all default values.
581 */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582 if (defproxy.check_req) free(defproxy.check_req);
583 if (defproxy.cookie_name) free(defproxy.cookie_name);
584 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200585 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100586 if (defproxy.defbe.name) free(defproxy.defbe.name);
Willy Tarreau0f772532006-12-23 20:51:41 +0100587
588 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
589 if (defproxy.errmsg[rc].len)
590 free(defproxy.errmsg[rc].str);
591 }
592
Willy Tarreaubaaee002006-06-26 02:48:02 +0200593 /* we cannot free uri_auth because it might already be used */
594 init_default_instance();
595 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100596 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200597 return 0;
598 }
599 else if (curproxy == NULL) {
600 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
601 return -1;
602 }
603
Willy Tarreau977b8e42006-12-29 14:19:17 +0100604
605 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200606 if (!strcmp(args[0], "bind")) { /* new listen addresses */
607 if (curproxy == &defproxy) {
608 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
609 return -1;
610 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100611 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
612 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613
614 if (strchr(args[1], ':') == NULL) {
615 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
616 file, linenum, args[0]);
617 return -1;
618 }
619 curproxy->listen = str2listener(args[1], curproxy->listen);
620 if (!curproxy->listen)
621 return -1;
622 global.maxsock++;
623 return 0;
624 }
625 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
626 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
627 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
628 file, linenum, args[0]);
629 return -1;
630 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100631 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
632 return 0;
633
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 /* flush useless bits */
635 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
636 return 0;
637 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200638 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100639 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
640 return 0;
641
Willy Tarreau1c47f852006-07-09 08:22:27 +0200642 if (!*args[1]) {
643 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
644 file, linenum, args[0]);
645 return -1;
646 }
647
648 if (curproxy->monitor_uri != NULL)
649 free(curproxy->monitor_uri);
650
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100651 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200652 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100653 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200654 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
655
656 return 0;
657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
659 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
660 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
661 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
662 else {
663 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
664 return -1;
665 }
666 }
667 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
668 curproxy->state = PR_STSTOPPED;
669 }
670 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
671 curproxy->state = PR_STNEW;
672 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200673 else if (!strcmp(args[0], "acl")) { /* add an ACL */
674 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
675 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
676 file, linenum, args[1]);
677 return -1;
678 }
679 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 else if (!strcmp(args[0], "cookie")) { /* cookie name */
681 int cur_arg;
682 // if (curproxy == &defproxy) {
683 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
684 // return -1;
685 // }
686
Willy Tarreau977b8e42006-12-29 14:19:17 +0100687 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
688 return 0;
689
Willy Tarreaubaaee002006-06-26 02:48:02 +0200690 if (curproxy->cookie_name != NULL) {
691 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
692 // file, linenum);
693 // return 0;
694 free(curproxy->cookie_name);
695 }
696
697 if (*(args[1]) == 0) {
698 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
699 file, linenum, args[0]);
700 return -1;
701 }
702 curproxy->cookie_name = strdup(args[1]);
703 curproxy->cookie_len = strlen(curproxy->cookie_name);
704
705 cur_arg = 2;
706 while (*(args[cur_arg])) {
707 if (!strcmp(args[cur_arg], "rewrite")) {
708 curproxy->options |= PR_O_COOK_RW;
709 }
710 else if (!strcmp(args[cur_arg], "indirect")) {
711 curproxy->options |= PR_O_COOK_IND;
712 }
713 else if (!strcmp(args[cur_arg], "insert")) {
714 curproxy->options |= PR_O_COOK_INS;
715 }
716 else if (!strcmp(args[cur_arg], "nocache")) {
717 curproxy->options |= PR_O_COOK_NOC;
718 }
719 else if (!strcmp(args[cur_arg], "postonly")) {
720 curproxy->options |= PR_O_COOK_POST;
721 }
722 else if (!strcmp(args[cur_arg], "prefix")) {
723 curproxy->options |= PR_O_COOK_PFX;
724 }
725 else {
726 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
727 file, linenum, args[0]);
728 return -1;
729 }
730 cur_arg++;
731 }
732 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
733 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
734 file, linenum);
735 return -1;
736 }
737
738 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
739 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
740 file, linenum);
741 return -1;
742 }
743 }/* end else if (!strcmp(args[0], "cookie")) */
744 else if (!strcmp(args[0], "appsession")) { /* cookie name */
745 // if (curproxy == &defproxy) {
746 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
747 // return -1;
748 // }
749
Willy Tarreau977b8e42006-12-29 14:19:17 +0100750 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
751 return 0;
752
Willy Tarreaubaaee002006-06-26 02:48:02 +0200753 if (curproxy->appsession_name != NULL) {
754 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
755 // file, linenum);
756 // return 0;
757 free(curproxy->appsession_name);
758 }
759
760 if (*(args[5]) == 0) {
761 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
762 file, linenum, args[0]);
763 return -1;
764 }
765 have_appsession = 1;
766 curproxy->appsession_name = strdup(args[1]);
767 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
768 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaud825eef2007-05-12 22:35:00 +0200769 __tv_from_ms(&curproxy->appsession_timeout, atoi(args[5]));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 rc = chtbl_init(&(curproxy->htbl_proxy), TBLSIZ, hashpjw, match_str, destroy);
771 if (rc) {
772 Alert("Error Init Appsession Hashtable.\n");
773 return -1;
774 }
775 } /* Url App Session */
776 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100777 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
778 return 0;
779
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
781 // if (curproxy == &defproxy) {
782 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
783 // return -1;
784 // }
785
786 if (curproxy->capture_name != NULL) {
787 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
788 // file, linenum, args[0]);
789 // return 0;
790 free(curproxy->capture_name);
791 }
792
793 if (*(args[4]) == 0) {
794 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
795 file, linenum, args[0]);
796 return -1;
797 }
798 curproxy->capture_name = strdup(args[2]);
799 curproxy->capture_namelen = strlen(curproxy->capture_name);
800 curproxy->capture_len = atol(args[4]);
801 if (curproxy->capture_len >= CAPTURE_LEN) {
802 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
803 file, linenum, CAPTURE_LEN - 1);
804 curproxy->capture_len = CAPTURE_LEN - 1;
805 }
806 curproxy->to_log |= LW_COOKIE;
807 }
808 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
809 struct cap_hdr *hdr;
810
811 if (curproxy == &defproxy) {
812 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
813 return -1;
814 }
815
816 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
817 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
818 file, linenum, args[0], args[1]);
819 return -1;
820 }
821
822 hdr = calloc(sizeof(struct cap_hdr), 1);
823 hdr->next = curproxy->req_cap;
824 hdr->name = strdup(args[3]);
825 hdr->namelen = strlen(args[3]);
826 hdr->len = atol(args[5]);
827 hdr->index = curproxy->nb_req_cap++;
828 curproxy->req_cap = hdr;
829 curproxy->to_log |= LW_REQHDR;
830 }
831 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
832 struct cap_hdr *hdr;
833
834 if (curproxy == &defproxy) {
835 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
836 return -1;
837 }
838
839 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
840 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
841 file, linenum, args[0], args[1]);
842 return -1;
843 }
844 hdr = calloc(sizeof(struct cap_hdr), 1);
845 hdr->next = curproxy->rsp_cap;
846 hdr->name = strdup(args[3]);
847 hdr->namelen = strlen(args[3]);
848 hdr->len = atol(args[5]);
849 hdr->index = curproxy->nb_rsp_cap++;
850 curproxy->rsp_cap = hdr;
851 curproxy->to_log |= LW_RSPHDR;
852 }
853 else {
854 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
855 file, linenum, args[0]);
856 return -1;
857 }
858 }
859 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200860 if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200861 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
862 return 0;
863 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100864 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
865 return 0;
866
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867 if (*(args[1]) == 0) {
868 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
869 file, linenum, args[0]);
870 return -1;
871 }
Willy Tarreaud825eef2007-05-12 22:35:00 +0200872 __tv_from_ms(&curproxy->contimeout, atol(args[1]));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200873 }
874 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200875 if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200876 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
877 file, linenum, args[0]);
878 return 0;
879 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100880 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
881 return 0;
882
Willy Tarreaubaaee002006-06-26 02:48:02 +0200883 if (*(args[1]) == 0) {
884 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
885 file, linenum, args[0]);
886 return -1;
887 }
Willy Tarreaud825eef2007-05-12 22:35:00 +0200888 __tv_from_ms(&curproxy->clitimeout, atol(args[1]));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200889 }
890 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200891 if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
893 return 0;
894 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100895 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
896 return 0;
897
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898 if (*(args[1]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
900 file, linenum, args[0]);
901 return -1;
902 }
Willy Tarreaud825eef2007-05-12 22:35:00 +0200903 __tv_from_ms(&curproxy->srvtimeout, atol(args[1]));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 }
905 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100906 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
907 return 0;
908
Willy Tarreaubaaee002006-06-26 02:48:02 +0200909 if (*(args[1]) == 0) {
910 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
911 file, linenum, args[0]);
912 return -1;
913 }
914 curproxy->conn_retries = atol(args[1]);
915 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200916 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
917 int pol = ACL_COND_NONE;
918 struct acl_cond *cond;
919
920 if (!strcmp(args[1], "if"))
921 pol = ACL_COND_IF;
922 else if (!strcmp(args[1], "unless"))
923 pol = ACL_COND_UNLESS;
924
925 if (pol == ACL_COND_NONE) {
926 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
927 file, linenum, args[0]);
928 return -1;
929 }
930
931 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
932 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
933 file, linenum);
934 return -1;
935 }
936 LIST_ADDQ(&curproxy->block_cond, &cond->list);
937 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100939 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
940 return 0;
941
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
943 curproxy->uri_auth = NULL; /* we must detach from the default config */
944
945 if (*(args[1]) == 0) {
946 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
947 return -1;
948 } else if (!strcmp(args[1], "uri")) {
949 if (*(args[2]) == 0) {
950 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
951 return -1;
952 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
953 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
954 return -1;
955 }
956 } else if (!strcmp(args[1], "realm")) {
957 if (*(args[2]) == 0) {
958 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
959 return -1;
960 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
961 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
962 return -1;
963 }
964 } else if (!strcmp(args[1], "auth")) {
965 if (*(args[2]) == 0) {
966 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
967 return -1;
968 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
969 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
970 return -1;
971 }
972 } else if (!strcmp(args[1], "scope")) {
973 if (*(args[2]) == 0) {
974 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
975 return -1;
976 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
977 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
978 return -1;
979 }
980 } else if (!strcmp(args[1], "enable")) {
981 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
982 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
983 return -1;
984 }
985 } else {
986 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'uri', 'realm', 'auth' or 'enable').\n",
987 file, linenum, args[0]);
988 return -1;
989 }
990 }
991 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100992 int optnum;
993
Willy Tarreaubaaee002006-06-26 02:48:02 +0200994 if (*(args[1]) == 0) {
995 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
996 return -1;
997 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100998
999 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1000 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1001 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1002 return 0;
1003 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001004 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001005 return 0;
1006 }
1007 }
1008
1009 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001010 /* generate a complete HTTP log */
1011 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1012 else if (!strcmp(args[1], "tcplog"))
1013 /* generate a detailed TCP log */
1014 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001015 else if (!strcmp(args[1], "tcpka")) {
1016 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001017 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1018 return 0;
1019
1020 if (curproxy->cap & PR_CAP_FE)
1021 curproxy->options |= PR_O_TCP_CLI_KA;
1022 if (curproxy->cap & PR_CAP_BE)
1023 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001024 }
1025 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001026 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1027 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001028 /* use HTTP request to check servers' health */
1029 if (curproxy->check_req != NULL) {
1030 free(curproxy->check_req);
1031 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001032 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001033 curproxy->options &= ~PR_O_SMTP_CHK;
1034 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001035 if (!*args[2]) { /* no argument */
1036 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1037 curproxy->check_len = strlen(DEF_CHECK_REQ);
1038 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001039 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001040 curproxy->check_req = (char *)malloc(reqlen);
1041 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1042 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1043 } else { /* more arguments : METHOD URI [HTTP_VER] */
1044 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1045 if (*args[4])
1046 reqlen += strlen(args[4]);
1047 else
1048 reqlen += strlen("HTTP/1.0");
1049
1050 curproxy->check_req = (char *)malloc(reqlen);
1051 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1052 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1053 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001054 }
1055 else if (!strcmp(args[1], "ssl-hello-chk")) {
1056 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001057 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1058 return 0;
1059
Willy Tarreauf3c69202006-07-09 16:42:34 +02001060 if (curproxy->check_req != NULL) {
1061 free(curproxy->check_req);
1062 }
1063 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001064 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001065 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066 }
Willy Tarreau23677902007-05-08 23:50:35 +02001067 else if (!strcmp(args[1], "smtpchk")) {
1068 /* use SMTP request to check servers' health */
1069 if (curproxy->check_req != NULL) {
1070 free(curproxy->check_req);
1071 }
1072 curproxy->options &= ~PR_O_HTTP_CHK;
1073 curproxy->options &= ~PR_O_SSL3_CHK;
1074 curproxy->options |= PR_O_SMTP_CHK;
1075
1076 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1077 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1078 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1079 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1080 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1081 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1082 curproxy->check_req = (char *)malloc(reqlen);
1083 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1084 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1085 } else {
1086 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1087 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1088 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1089 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1090 }
1091 }
1092 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001093 else if (!strcmp(args[1], "forwardfor")) {
1094 /* insert x-forwarded-for field, but not for the
1095 * IP address listed as an except.
1096 */
1097 if (*(args[2])) {
1098 if (!strcmp(args[2], "except")) {
1099 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1100 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1101 file, linenum, args[0]);
1102 return -1;
1103 }
1104 /* flush useless bits */
1105 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1106 } else {
1107 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1108 file, linenum, args[0]);
1109 return -1;
1110 }
1111 }
1112 curproxy->options |= PR_O_FWDFOR;
1113 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001114 else {
1115 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1116 return -1;
1117 }
1118 return 0;
1119 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001120 else if (!strcmp(args[0], "default_backend")) {
1121 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1122 return 0;
1123
1124 if (*(args[1]) == 0) {
1125 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1126 return -1;
1127 }
1128 if (curproxy->defbe.name)
1129 free(curproxy->defbe.name);
1130 curproxy->defbe.name = strdup(args[1]);
1131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001133 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1134 return 0;
1135
Willy Tarreaubaaee002006-06-26 02:48:02 +02001136 /* enable reconnections to dispatch */
1137 curproxy->options |= PR_O_REDISP;
1138 }
1139#ifdef TPROXY
1140 else if (!strcmp(args[0], "transparent")) {
1141 /* enable transparent proxy connections */
1142 curproxy->options |= PR_O_TRANSP;
1143 }
1144#endif
1145 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001146 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1147 return 0;
1148
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 if (*(args[1]) == 0) {
1150 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1151 return -1;
1152 }
1153 curproxy->maxconn = atol(args[1]);
1154 }
Willy Tarreau86034312006-12-29 00:10:33 +01001155 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001156 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1157 return 0;
1158
Willy Tarreau86034312006-12-29 00:10:33 +01001159 if (*(args[1]) == 0) {
1160 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1161 return -1;
1162 }
1163 curproxy->fullconn = atol(args[1]);
1164 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001165 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1166 if (*(args[1]) == 0) {
1167 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1168 return -1;
1169 }
1170 curproxy->grace = atol(args[1]);
1171 }
1172 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1173 if (curproxy == &defproxy) {
1174 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1175 return -1;
1176 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001177 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1178 return 0;
1179
Willy Tarreaubaaee002006-06-26 02:48:02 +02001180 if (strchr(args[1], ':') == NULL) {
1181 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1182 return -1;
1183 }
1184 curproxy->dispatch_addr = *str2sa(args[1]);
1185 }
1186 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001187 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1188 return 0;
1189
Willy Tarreaubaaee002006-06-26 02:48:02 +02001190 if (*(args[1])) {
1191 if (!strcmp(args[1], "roundrobin")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001192 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 curproxy->options |= PR_O_BALANCE_RR;
1194 }
1195 else if (!strcmp(args[1], "source")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001196 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197 curproxy->options |= PR_O_BALANCE_SH;
1198 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001199 else if (!strcmp(args[1], "uri")) {
1200 curproxy->options &= ~PR_O_BALANCE;
1201 curproxy->options |= PR_O_BALANCE_UH;
1202 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 else {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001204 Alert("parsing [%s:%d] : '%s' only supports 'roundrobin', 'source' and 'uri' options.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 return -1;
1206 }
1207 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001208 else {/* if no option is set, use round-robin by default */
1209 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001210 curproxy->options |= PR_O_BALANCE_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001211 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001212 }
1213 else if (!strcmp(args[0], "server")) { /* server address */
1214 int cur_arg;
1215 char *rport;
1216 char *raddr;
1217 short realport;
1218 int do_check;
1219
1220 if (curproxy == &defproxy) {
1221 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1222 return -1;
1223 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001224 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1225 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001226
1227 if (!*args[2]) {
1228 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1229 file, linenum, args[0]);
1230 return -1;
1231 }
1232 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1233 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1234 return -1;
1235 }
1236
1237 /* the servers are linked backwards first */
1238 newsrv->next = curproxy->srv;
1239 curproxy->srv = newsrv;
1240 newsrv->proxy = curproxy;
1241
1242 LIST_INIT(&newsrv->pendconns);
1243 do_check = 0;
1244 newsrv->state = SRV_RUNNING; /* early server setup */
1245 newsrv->id = strdup(args[1]);
1246
1247 /* several ways to check the port component :
1248 * - IP => port=+0, relative
1249 * - IP: => port=+0, relative
1250 * - IP:N => port=N, absolute
1251 * - IP:+N => port=+N, relative
1252 * - IP:-N => port=-N, relative
1253 */
1254 raddr = strdup(args[2]);
1255 rport = strchr(raddr, ':');
1256 if (rport) {
1257 *rport++ = 0;
1258 realport = atol(rport);
1259 if (!isdigit((int)*rport))
1260 newsrv->state |= SRV_MAPPORTS;
1261 } else {
1262 realport = 0;
1263 newsrv->state |= SRV_MAPPORTS;
1264 }
1265
1266 newsrv->addr = *str2sa(raddr);
1267 newsrv->addr.sin_port = htons(realport);
1268 free(raddr);
1269
1270 newsrv->curfd = -1; /* no health-check in progress */
1271 newsrv->inter = DEF_CHKINTR;
1272 newsrv->rise = DEF_RISETIME;
1273 newsrv->fall = DEF_FALLTIME;
1274 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001275 newsrv->uweight = 1;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001276
Willy Tarreaubaaee002006-06-26 02:48:02 +02001277 cur_arg = 3;
1278 while (*args[cur_arg]) {
1279 if (!strcmp(args[cur_arg], "cookie")) {
1280 newsrv->cookie = strdup(args[cur_arg + 1]);
1281 newsrv->cklen = strlen(args[cur_arg + 1]);
1282 cur_arg += 2;
1283 }
1284 else if (!strcmp(args[cur_arg], "rise")) {
1285 newsrv->rise = atol(args[cur_arg + 1]);
1286 newsrv->health = newsrv->rise;
1287 cur_arg += 2;
1288 }
1289 else if (!strcmp(args[cur_arg], "fall")) {
1290 newsrv->fall = atol(args[cur_arg + 1]);
1291 cur_arg += 2;
1292 }
1293 else if (!strcmp(args[cur_arg], "inter")) {
1294 newsrv->inter = atol(args[cur_arg + 1]);
1295 cur_arg += 2;
1296 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001297 else if (!strcmp(args[cur_arg], "addr")) {
1298 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001299 cur_arg += 2;
1300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001301 else if (!strcmp(args[cur_arg], "port")) {
1302 newsrv->check_port = atol(args[cur_arg + 1]);
1303 cur_arg += 2;
1304 }
1305 else if (!strcmp(args[cur_arg], "backup")) {
1306 newsrv->state |= SRV_BACKUP;
1307 cur_arg ++;
1308 }
1309 else if (!strcmp(args[cur_arg], "weight")) {
1310 int w;
1311 w = atol(args[cur_arg + 1]);
1312 if (w < 1 || w > 256) {
1313 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1314 file, linenum, newsrv->id, w);
1315 return -1;
1316 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001317 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318 cur_arg += 2;
1319 }
1320 else if (!strcmp(args[cur_arg], "minconn")) {
1321 newsrv->minconn = atol(args[cur_arg + 1]);
1322 cur_arg += 2;
1323 }
1324 else if (!strcmp(args[cur_arg], "maxconn")) {
1325 newsrv->maxconn = atol(args[cur_arg + 1]);
1326 cur_arg += 2;
1327 }
1328 else if (!strcmp(args[cur_arg], "check")) {
1329 global.maxsock++;
1330 do_check = 1;
1331 cur_arg += 1;
1332 }
1333 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1334 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001335#ifdef CONFIG_HAP_CTTPROXY
1336 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1337 file, linenum, "source", "usesrc");
1338#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001339 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1340 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001341#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001342 return -1;
1343 }
1344 newsrv->state |= SRV_BIND_SRC;
1345 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1346 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001347 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001348#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001349 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001350 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1351 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001352 return -1;
1353 }
1354 if (!*args[cur_arg + 1]) {
1355 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1356 file, linenum, "usesrc");
1357 return -1;
1358 }
1359 if (!strcmp(args[cur_arg + 1], "client")) {
1360 newsrv->state |= SRV_TPROXY_CLI;
1361 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1362 newsrv->state |= SRV_TPROXY_CIP;
1363 } else {
1364 newsrv->state |= SRV_TPROXY_ADDR;
1365 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1366 }
1367 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1368 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001369#else /* no CTTPROXY support */
1370 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1371 file, linenum, "usesrc");
1372 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001373#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001374 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001375 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001376#ifdef CONFIG_HAP_CTTPROXY
1377 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1378 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1379 file, linenum, "usesrc", "source");
1380 return -1;
1381 }
1382#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001383 else {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001384 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 +02001385 file, linenum, newsrv->id);
1386 return -1;
1387 }
1388 }
1389
1390 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001391 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1392 newsrv->check_port = newsrv->check_addr.sin_port;
1393
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1395 newsrv->check_port = realport; /* by default */
1396 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001397 /* not yet valid, because no port was set on
1398 * the server either. We'll check if we have
1399 * a known port on the first listener.
1400 */
1401 struct listener *l;
1402 l = curproxy->listen;
1403 if (l) {
1404 int port;
1405 port = (l->addr.ss_family == AF_INET6)
1406 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1407 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1408 newsrv->check_port = port;
1409 }
1410 }
1411 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1413 file, linenum, newsrv->id);
1414 return -1;
1415 }
1416 newsrv->state |= SRV_CHECKED;
1417 }
1418
1419 if (newsrv->state & SRV_BACKUP)
1420 curproxy->srv_bck++;
1421 else
1422 curproxy->srv_act++;
1423 }
1424 else if (!strcmp(args[0], "log")) { /* syslog server address */
1425 struct sockaddr_in *sa;
1426 int facility;
1427
1428 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1429 curproxy->logfac1 = global.logfac1;
1430 curproxy->logsrv1 = global.logsrv1;
1431 curproxy->loglev1 = global.loglev1;
1432 curproxy->logfac2 = global.logfac2;
1433 curproxy->logsrv2 = global.logsrv2;
1434 curproxy->loglev2 = global.loglev2;
1435 }
1436 else if (*(args[1]) && *(args[2])) {
1437 int level;
1438
1439 facility = get_log_facility(args[2]);
1440 if (facility < 0) {
1441 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1442 exit(1);
1443 }
1444
1445 level = 7; /* max syslog level = debug */
1446 if (*(args[3])) {
1447 level = get_log_level(args[3]);
1448 if (level < 0) {
1449 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1450 exit(1);
1451 }
1452 }
1453
1454 sa = str2sa(args[1]);
1455 if (!sa->sin_port)
1456 sa->sin_port = htons(SYSLOG_PORT);
1457
1458 if (curproxy->logfac1 == -1) {
1459 curproxy->logsrv1 = *sa;
1460 curproxy->logfac1 = facility;
1461 curproxy->loglev1 = level;
1462 }
1463 else if (curproxy->logfac2 == -1) {
1464 curproxy->logsrv2 = *sa;
1465 curproxy->logfac2 = facility;
1466 curproxy->loglev2 = level;
1467 }
1468 else {
1469 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1470 return -1;
1471 }
1472 }
1473 else {
1474 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1475 file, linenum);
1476 return -1;
1477 }
1478 }
1479 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001480 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1481 return 0;
1482
Willy Tarreaubaaee002006-06-26 02:48:02 +02001483 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001484#ifdef CONFIG_HAP_CTTPROXY
1485 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1486 file, linenum, "source", "usesrc");
1487#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001488 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1489 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001490#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491 return -1;
1492 }
1493
1494 curproxy->source_addr = *str2sa(args[1]);
1495 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001496 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001497#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001498 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1499 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1500 file, linenum, "usesrc");
1501 return -1;
1502 }
1503 if (!*args[3]) {
1504 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1505 file, linenum, "usesrc");
1506 return -1;
1507 }
1508
1509 if (!strcmp(args[3], "client")) {
1510 curproxy->options |= PR_O_TPXY_CLI;
1511 } else if (!strcmp(args[3], "clientip")) {
1512 curproxy->options |= PR_O_TPXY_CIP;
1513 } else {
1514 curproxy->options |= PR_O_TPXY_ADDR;
1515 curproxy->tproxy_addr = *str2sa(args[3]);
1516 }
1517 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001518#else /* no CTTPROXY support */
1519 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1520 file, linenum, "usesrc");
1521 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001522#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001524 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001525#ifdef CONFIG_HAP_CTTPROXY
1526 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1527 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1528 file, linenum, "usesrc", "source");
1529 return -1;
1530 }
1531#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1533 regex_t *preg;
1534 if (curproxy == &defproxy) {
1535 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1536 return -1;
1537 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001538 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1539 return 0;
1540
Willy Tarreaubaaee002006-06-26 02:48:02 +02001541 if (*(args[1]) == 0 || *(args[2]) == 0) {
1542 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1543 file, linenum, args[0]);
1544 return -1;
1545 }
1546
1547 preg = calloc(1, sizeof(regex_t));
1548 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1549 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1550 return -1;
1551 }
1552
1553 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1554 if (err) {
1555 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1556 file, linenum, *err);
1557 return -1;
1558 }
1559 }
1560 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1561 regex_t *preg;
1562 if (curproxy == &defproxy) {
1563 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1564 return -1;
1565 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001566 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1567 return 0;
1568
Willy Tarreaubaaee002006-06-26 02:48:02 +02001569 if (*(args[1]) == 0) {
1570 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", 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 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1581 }
1582 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1583 regex_t *preg;
1584 if (curproxy == &defproxy) {
1585 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1586 return -1;
1587 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001588 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1589 return 0;
1590
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591 if (*(args[1]) == 0) {
1592 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1593 return -1;
1594 }
1595
1596 preg = calloc(1, sizeof(regex_t));
1597 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1598 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1599 return -1;
1600 }
1601
1602 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1603 }
1604 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1605 regex_t *preg;
1606 if (curproxy == &defproxy) {
1607 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1608 return -1;
1609 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001610 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1611 return 0;
1612
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613 if (*(args[1]) == 0) {
1614 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1615 return -1;
1616 }
1617
1618 preg = calloc(1, sizeof(regex_t));
1619 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1620 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1621 return -1;
1622 }
1623
1624 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1625 }
1626 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1627 regex_t *preg;
1628 if (curproxy == &defproxy) {
1629 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1630 return -1;
1631 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001632 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1633 return 0;
1634
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635 if (*(args[1]) == 0) {
1636 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1637 return -1;
1638 }
1639
1640 preg = calloc(1, sizeof(regex_t));
1641 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1642 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1643 return -1;
1644 }
1645
1646 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1647 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001648 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1649 regex_t *preg;
1650 if (curproxy == &defproxy) {
1651 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1652 return -1;
1653 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001654 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1655 return 0;
1656
Willy Tarreaub8750a82006-09-03 09:56:00 +02001657 if (*(args[1]) == 0) {
1658 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1659 return -1;
1660 }
1661
1662 preg = calloc(1, sizeof(regex_t));
1663 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1664 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1665 return -1;
1666 }
1667
1668 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1669 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001670 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1671 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001672 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001673 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1674 return -1;
1675 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001676 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1677 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001678
Willy Tarreau977b8e42006-12-29 14:19:17 +01001679 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001680 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1681 file, linenum, args[0]);
1682 return -1;
1683 }
1684
1685 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001686 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001687 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1688 }
1689
1690 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1691 }
1692 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1693 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001694 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001695 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1696 return -1;
1697 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001698 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1699 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001700
Willy Tarreau977b8e42006-12-29 14:19:17 +01001701 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001702 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1703 file, linenum, args[0]);
1704 return -1;
1705 }
1706
1707 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001708 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001709 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1710 }
1711
1712 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1715 regex_t *preg;
1716 if (curproxy == &defproxy) {
1717 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1718 return -1;
1719 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001720 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1721 return 0;
1722
Willy Tarreaubaaee002006-06-26 02:48:02 +02001723 if (*(args[1]) == 0 || *(args[2]) == 0) {
1724 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1725 file, linenum, args[0]);
1726 return -1;
1727 }
1728
1729 preg = calloc(1, sizeof(regex_t));
1730 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1731 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1732 return -1;
1733 }
1734
1735 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1736 if (err) {
1737 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1738 file, linenum, *err);
1739 return -1;
1740 }
1741 }
1742 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1743 regex_t *preg;
1744 if (curproxy == &defproxy) {
1745 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1746 return -1;
1747 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001748 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1749 return 0;
1750
Willy Tarreaubaaee002006-06-26 02:48:02 +02001751 if (*(args[1]) == 0) {
1752 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", 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 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1763 }
1764 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1765 regex_t *preg;
1766 if (curproxy == &defproxy) {
1767 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1768 return -1;
1769 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001770 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1771 return 0;
1772
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773 if (*(args[1]) == 0) {
1774 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1775 return -1;
1776 }
1777
1778 preg = calloc(1, sizeof(regex_t));
1779 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1780 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1781 return -1;
1782 }
1783
1784 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1785 }
1786 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1787 regex_t *preg;
1788 if (curproxy == &defproxy) {
1789 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1790 return -1;
1791 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001792 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1793 return 0;
1794
Willy Tarreaubaaee002006-06-26 02:48:02 +02001795 if (*(args[1]) == 0) {
1796 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1797 return -1;
1798 }
1799
1800 preg = calloc(1, sizeof(regex_t));
1801 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1802 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1803 return -1;
1804 }
1805
1806 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1807 }
1808 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1809 regex_t *preg;
1810 if (curproxy == &defproxy) {
1811 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1812 return -1;
1813 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001814 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1815 return 0;
1816
Willy Tarreaubaaee002006-06-26 02:48:02 +02001817 if (*(args[1]) == 0) {
1818 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1819 return -1;
1820 }
1821
1822 preg = calloc(1, sizeof(regex_t));
1823 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1824 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1825 return -1;
1826 }
1827
1828 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1829 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001830 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1831 regex_t *preg;
1832 if (curproxy == &defproxy) {
1833 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1834 return -1;
1835 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001836 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1837 return 0;
1838
Willy Tarreaub8750a82006-09-03 09:56:00 +02001839 if (*(args[1]) == 0) {
1840 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1841 return -1;
1842 }
1843
1844 preg = calloc(1, sizeof(regex_t));
1845 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1846 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1847 return -1;
1848 }
1849
1850 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1853 if (curproxy == &defproxy) {
1854 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1855 return -1;
1856 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001857 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1858 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001859
1860 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
1861 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1862 return 0;
1863 }
1864
1865 if (*(args[1]) == 0) {
1866 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1867 return -1;
1868 }
1869
1870 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
1871 }
1872 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
1873 regex_t *preg;
1874
1875 if (*(args[1]) == 0 || *(args[2]) == 0) {
1876 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1877 file, linenum, args[0]);
1878 return -1;
1879 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001880 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1881 return 0;
1882
Willy Tarreaubaaee002006-06-26 02:48:02 +02001883 preg = calloc(1, sizeof(regex_t));
1884 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1885 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1886 return -1;
1887 }
1888
1889 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1890 if (err) {
1891 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1892 file, linenum, *err);
1893 return -1;
1894 }
1895 }
1896 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
1897 regex_t *preg;
1898 if (curproxy == &defproxy) {
1899 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1900 return -1;
1901 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001902 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1903 return 0;
1904
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905 if (*(args[1]) == 0) {
1906 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1907 return -1;
1908 }
1909
1910 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_REMOVE, 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], "rspdeny")) { /* block 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_DENY, 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], "rspirep")) { /* replace response header from a regex ignoring case */
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;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001958
1959 if (*(args[1]) == 0 || *(args[2]) == 0) {
1960 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1961 file, linenum, args[0]);
1962 return -1;
1963 }
1964
1965 preg = calloc(1, sizeof(regex_t));
1966 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1967 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1968 return -1;
1969 }
1970
1971 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1972 if (err) {
1973 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1974 file, linenum, *err);
1975 return -1;
1976 }
1977 }
1978 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
1979 regex_t *preg;
1980 if (curproxy == &defproxy) {
1981 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1982 return -1;
1983 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001984 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1985 return 0;
1986
Willy Tarreaubaaee002006-06-26 02:48:02 +02001987 if (*(args[1]) == 0) {
1988 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", 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_REMOVE, 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], "rspideny")) { /* block 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_DENY, 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], "rspadd")) { /* add response header */
2033 if (curproxy == &defproxy) {
2034 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2035 return -1;
2036 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002037 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2038 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002039
2040 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2041 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2042 return 0;
2043 }
2044
2045 if (*(args[1]) == 0) {
2046 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2047 return -1;
2048 }
2049
2050 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2051 }
2052 else if (!strcmp(args[0], "errorloc") ||
2053 !strcmp(args[0], "errorloc302") ||
2054 !strcmp(args[0], "errorloc303")) { /* error location */
2055 int errnum, errlen;
2056 char *err;
2057
2058 // if (curproxy == &defproxy) {
2059 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2060 // return -1;
2061 // }
2062
Willy Tarreau977b8e42006-12-29 14:19:17 +01002063 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2064 return 0;
2065
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002067 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002068 return -1;
2069 }
2070
2071 errnum = atol(args[1]);
2072 if (!strcmp(args[0], "errorloc303")) {
2073 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2074 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2075 } else {
2076 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2077 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2078 }
2079
Willy Tarreau0f772532006-12-23 20:51:41 +01002080 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2081 if (http_err_codes[rc] == errnum) {
2082 if (curproxy->errmsg[rc].str)
2083 free(curproxy->errmsg[rc].str);
2084 curproxy->errmsg[rc].str = err;
2085 curproxy->errmsg[rc].len = errlen;
2086 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002089
2090 if (rc >= HTTP_ERR_SIZE) {
2091 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2092 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093 free(err);
2094 }
2095 }
2096 else {
2097 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2098 return -1;
2099 }
2100 return 0;
2101}
2102
2103
2104/*
2105 * This function reads and parses the configuration file given in the argument.
2106 * returns 0 if OK, -1 if error.
2107 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002108int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109{
2110 char thisline[256];
2111 char *line;
2112 FILE *f;
2113 int linenum = 0;
2114 char *end;
Willy Tarreau540abe42007-05-02 20:50:16 +02002115 char *args[MAX_LINE_ARGS + 1];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116 int arg;
2117 int cfgerr = 0;
Willy Tarreau80587432006-12-24 17:47:20 +01002118 int nbchk, mininter;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002119 int confsect = CFG_NONE;
2120
2121 struct proxy *curproxy = NULL;
2122 struct server *newsrv = NULL;
2123
2124 if ((f=fopen(file,"r")) == NULL)
2125 return -1;
2126
2127 init_default_instance();
2128
2129 while (fgets(line = thisline, sizeof(thisline), f) != NULL) {
2130 linenum++;
2131
2132 end = line + strlen(line);
2133
2134 /* skip leading spaces */
2135 while (isspace((int)*line))
2136 line++;
2137
2138 arg = 0;
2139 args[arg] = line;
2140
2141 while (*line && arg < MAX_LINE_ARGS) {
2142 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2143 * C equivalent value. Other combinations left unchanged (eg: \1).
2144 */
2145 if (*line == '\\') {
2146 int skip = 0;
2147 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2148 *line = line[1];
2149 skip = 1;
2150 }
2151 else if (line[1] == 'r') {
2152 *line = '\r';
2153 skip = 1;
2154 }
2155 else if (line[1] == 'n') {
2156 *line = '\n';
2157 skip = 1;
2158 }
2159 else if (line[1] == 't') {
2160 *line = '\t';
2161 skip = 1;
2162 }
2163 else if (line[1] == 'x') {
2164 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2165 unsigned char hex1, hex2;
2166 hex1 = toupper(line[2]) - '0';
2167 hex2 = toupper(line[3]) - '0';
2168 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2169 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2170 *line = (hex1<<4) + hex2;
2171 skip = 3;
2172 }
2173 else {
2174 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2175 return -1;
2176 }
2177 }
2178 if (skip) {
2179 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2180 end -= skip;
2181 }
2182 line++;
2183 }
2184 else if (*line == '#' || *line == '\n' || *line == '\r') {
2185 /* end of string, end of loop */
2186 *line = 0;
2187 break;
2188 }
2189 else if (isspace((int)*line)) {
2190 /* a non-escaped space is an argument separator */
2191 *line++ = 0;
2192 while (isspace((int)*line))
2193 line++;
2194 args[++arg] = line;
2195 }
2196 else {
2197 line++;
2198 }
2199 }
2200
2201 /* empty line */
2202 if (!**args)
2203 continue;
2204
Willy Tarreau540abe42007-05-02 20:50:16 +02002205 /* zero out remaining args and ensure that at least one entry
2206 * is zeroed out.
2207 */
2208 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 args[arg] = line;
2210 }
2211
Willy Tarreau977b8e42006-12-29 14:19:17 +01002212 if (!strcmp(args[0], "listen") ||
2213 !strcmp(args[0], "frontend") ||
2214 !strcmp(args[0], "backend") ||
2215 !strcmp(args[0], "ruleset") ||
2216 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002217 confsect = CFG_LISTEN;
2218 else if (!strcmp(args[0], "global")) /* global config */
2219 confsect = CFG_GLOBAL;
2220 /* else it's a section keyword */
2221
2222 switch (confsect) {
2223 case CFG_LISTEN:
2224 if (cfg_parse_listen(file, linenum, args) < 0)
2225 return -1;
2226 break;
2227 case CFG_GLOBAL:
2228 if (cfg_parse_global(file, linenum, args) < 0)
2229 return -1;
2230 break;
2231 default:
2232 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2233 return -1;
2234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002235 }
2236 fclose(f);
2237
2238 /*
2239 * Now, check for the integrity of all that we have collected.
2240 */
2241
2242 /* will be needed further to delay some tasks */
2243 tv_now(&now);
2244
2245 if ((curproxy = proxy) == NULL) {
2246 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2247 file);
2248 return -1;
2249 }
2250
2251 while (curproxy != NULL) {
2252 if (curproxy->state == PR_STSTOPPED) {
2253 curproxy = curproxy->next;
2254 continue;
2255 }
2256
Willy Tarreau977b8e42006-12-29 14:19:17 +01002257 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2258 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 +01002259 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 cfgerr++;
2261 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002262 else if (curproxy->cap & PR_CAP_BE &&
2263 ((curproxy->mode != PR_MODE_HEALTH) &&
2264 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
2265 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2266 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 +01002267 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268 cfgerr++;
2269 }
2270 else if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
2271 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002272 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002273 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274 cfgerr++;
2275 }
2276#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2277 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002278 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002279 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002280 cfgerr++;
2281 }
2282#endif
2283 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002284 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002285 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 }
2287 }
2288 else if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2289 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002290 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002291 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 }
2293 if ((newsrv = curproxy->srv) != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002294 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002295 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296 }
2297 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002298 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002299 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 }
2301 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002302 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002303 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002304 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002305 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002306 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002307 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002308 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002309 if (curproxy->options & PR_O_BALANCE_UH) {
2310 curproxy->options &= ~PR_O_BALANCE;
2311 curproxy->options |= PR_O_BALANCE_RR;
2312
2313 Warning("parsing %s : URI hash will be ignored for %s '%s'. Falling back to round robin.\n",
2314 file, proxy_type_str(curproxy), curproxy->id);
2315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002316 }
2317 else if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
2318 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2319 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2320 file, curproxy->id);
2321 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002322 }
2323 }
2324
2325 /* if a default backend was specified, let's find it */
2326 if (curproxy->defbe.name) {
2327 struct proxy *target;
2328
2329 for (target = proxy; target != NULL; target = target->next) {
2330 if (strcmp(target->id, curproxy->defbe.name) == 0)
2331 break;
2332 }
2333 if (target == NULL) {
2334 Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n",
2335 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2336 cfgerr++;
2337 } else if (target == curproxy) {
2338 Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
2339 cfgerr++;
2340 } else if (!(target->cap & PR_CAP_BE)) {
2341 Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n",
2342 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2343 cfgerr++;
2344 } else if (target->mode != curproxy->mode) {
2345 Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
2346 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2347 cfgerr++;
2348 } else {
2349 free(curproxy->defbe.name);
2350 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 }
2352 }
2353
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002354 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002355 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2356 /* map jump target for ACT_SETBE in req_rep chain */
2357 struct hdr_exp *exp;
2358 struct proxy *target;
2359 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
2360 if (exp->action != ACT_SETBE)
2361 continue;
2362 for (target = proxy; target != NULL; target = target->next) {
2363 if (strcmp(target->id, exp->replace) == 0)
2364 break;
2365 }
2366 if (target == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002367 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002368 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaua496b602006-12-17 23:15:24 +01002369 cfgerr++;
2370 } else if (target == curproxy) {
2371 Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
2372 cfgerr++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002373 } else if (!(target->cap & PR_CAP_BE)) {
2374 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002375 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002376 cfgerr++;
2377 } else if (target->mode != PR_MODE_HTTP) {
2378 Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002379 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002380 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002381 } else {
2382 free((void *)exp->replace);
2383 exp->replace = (const char *)target;
2384 }
2385 }
2386 }
Willy Tarreau2738a142006-07-08 17:28:09 +02002387 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002388 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2389 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2390 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002391 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002392 " | While not properly invalid, you will certainly encounter various problems\n"
2393 " | with such a configuration. To fix this, please ensure that all following\n"
2394 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002395 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002396 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002397
2398 if (curproxy->options & PR_O_SSL3_CHK) {
2399 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2400 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2401 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2402 }
2403
Willy Tarreau86034312006-12-29 00:10:33 +01002404 /* for backwards compatibility with "listen" instances, if
2405 * fullconn is not set but maxconn is set, then maxconn
2406 * is used.
2407 */
2408 if (!curproxy->fullconn)
2409 curproxy->fullconn = curproxy->maxconn;
2410
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 /* first, we will invert the servers list order */
2412 newsrv = NULL;
2413 while (curproxy->srv) {
2414 struct server *next;
2415
2416 next = curproxy->srv->next;
2417 curproxy->srv->next = newsrv;
2418 newsrv = curproxy->srv;
2419 if (!next)
2420 break;
2421 curproxy->srv = next;
2422 }
2423
2424 /* now, newsrv == curproxy->srv */
2425 if (newsrv) {
2426 struct server *srv;
2427 int pgcd;
2428 int act, bck;
2429
2430 /* We will factor the weights to reduce the table,
2431 * using Euclide's largest common divisor algorithm
2432 */
Willy Tarreau417fae02007-03-25 21:16:40 +02002433 pgcd = newsrv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2435 int t, w;
2436
Willy Tarreau417fae02007-03-25 21:16:40 +02002437 w = srv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 while (w) {
2439 t = pgcd % w;
2440 pgcd = w;
2441 w = t;
2442 }
2443 }
2444
2445 act = bck = 0;
2446 for (srv = newsrv; srv; srv = srv->next) {
Willy Tarreau417fae02007-03-25 21:16:40 +02002447 srv->eweight = srv->uweight / pgcd;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 if (srv->state & SRV_BACKUP)
Willy Tarreau417fae02007-03-25 21:16:40 +02002449 bck += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 else
Willy Tarreau417fae02007-03-25 21:16:40 +02002451 act += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 }
2453
2454 /* this is the largest map we will ever need for this servers list */
2455 if (act < bck)
2456 act = bck;
2457
2458 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2459 /* recounts servers and their weights */
2460 recount_servers(curproxy);
2461 recalc_server_map(curproxy);
2462 }
2463
2464 if (curproxy->options & PR_O_LOGASAP)
2465 curproxy->to_log &= ~LW_BYTES;
2466
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 /*
2468 * If this server supports a maxconn parameter, it needs a dedicated
2469 * tasks to fill the emptied slots when a connection leaves.
2470 */
2471 newsrv = curproxy->srv;
2472 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002473 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 /* Only 'minconn' was specified, or it was higher than or equal
2475 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2476 * this will avoid further useless expensive computations.
2477 */
2478 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002479 } else if (newsrv->maxconn && !newsrv->minconn) {
2480 /* minconn was not specified, so we set it to maxconn */
2481 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002482 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2483 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002484 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002485 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002486 }
2487
2488 if (newsrv->maxconn > 0) {
2489 struct task *t;
2490
2491 if ((t = pool_alloc(task)) == NULL) {
2492 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2493 return -1;
2494 }
2495
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002496 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002497 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002498 t->state = TASK_IDLE;
2499 t->process = process_srv_queue;
2500 t->context = newsrv;
2501 newsrv->queue_mgt = t;
2502
2503 /* never run it unless specifically woken up */
2504 tv_eternity(&t->expire);
2505 task_queue(t);
2506 }
2507 newsrv = newsrv->next;
2508 }
2509
2510 /* now we'll start this proxy's health checks if any */
2511 /* 1- count the checkers to run simultaneously */
2512 nbchk = 0;
2513 mininter = 0;
2514 newsrv = curproxy->srv;
2515 while (newsrv != NULL) {
2516 if (newsrv->state & SRV_CHECKED) {
2517 if (!mininter || mininter > newsrv->inter)
2518 mininter = newsrv->inter;
2519 nbchk++;
2520 }
2521 newsrv = newsrv->next;
2522 }
2523
2524 /* 2- start them as far as possible from each others while respecting
2525 * their own intervals. For this, we will start them after their own
2526 * interval added to the min interval divided by the number of servers,
2527 * weighted by the server's position in the list.
2528 */
2529 if (nbchk > 0) {
2530 struct task *t;
2531 int srvpos;
2532
2533 newsrv = curproxy->srv;
2534 srvpos = 0;
2535 while (newsrv != NULL) {
2536 /* should this server be checked ? */
2537 if (newsrv->state & SRV_CHECKED) {
2538 if ((t = pool_alloc(task)) == NULL) {
2539 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2540 return -1;
2541 }
2542
Willy Tarreau964c9362007-01-07 00:38:00 +01002543 t->wq = NULL;
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002544 t->qlist.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 t->state = TASK_IDLE;
2546 t->process = process_chk;
2547 t->context = newsrv;
2548
2549 /* check this every ms */
Willy Tarreau42aae5c2007-04-29 17:43:56 +02002550 tv_ms_add(&t->expire, &now,
2551 newsrv->inter + mininter * srvpos / nbchk);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552 task_queue(t);
2553 //task_wakeup(&rq, t);
2554 srvpos++;
2555 }
2556 newsrv = newsrv->next;
2557 }
2558 }
2559
2560 curproxy = curproxy->next;
2561 }
2562 if (cfgerr > 0) {
2563 Alert("Errors found in configuration file, aborting.\n");
2564 return -1;
2565 }
2566 else
2567 return 0;
2568}
2569
2570
2571
2572/*
2573 * Local variables:
2574 * c-indent-level: 8
2575 * c-basic-offset: 8
2576 * End:
2577 */