blob: 516547445264773e939a0e0309d3cbdb77e91c3b [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]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200827 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200828 hdr->index = curproxy->nb_req_cap++;
829 curproxy->req_cap = hdr;
830 curproxy->to_log |= LW_REQHDR;
831 }
832 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
833 struct cap_hdr *hdr;
834
835 if (curproxy == &defproxy) {
836 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
837 return -1;
838 }
839
840 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
841 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
842 file, linenum, args[0], args[1]);
843 return -1;
844 }
845 hdr = calloc(sizeof(struct cap_hdr), 1);
846 hdr->next = curproxy->rsp_cap;
847 hdr->name = strdup(args[3]);
848 hdr->namelen = strlen(args[3]);
849 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +0200850 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200851 hdr->index = curproxy->nb_rsp_cap++;
852 curproxy->rsp_cap = hdr;
853 curproxy->to_log |= LW_RSPHDR;
854 }
855 else {
856 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
857 file, linenum, args[0]);
858 return -1;
859 }
860 }
861 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200862 if (!__tv_iseq(&curproxy->contimeout, &defproxy.contimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200863 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
864 return 0;
865 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100866 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
867 return 0;
868
Willy Tarreaubaaee002006-06-26 02:48:02 +0200869 if (*(args[1]) == 0) {
870 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
871 file, linenum, args[0]);
872 return -1;
873 }
Willy Tarreaud825eef2007-05-12 22:35:00 +0200874 __tv_from_ms(&curproxy->contimeout, atol(args[1]));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200875 }
876 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200877 if (!__tv_iseq(&curproxy->clitimeout, &defproxy.clitimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200878 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
879 file, linenum, args[0]);
880 return 0;
881 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100882 else if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
883 return 0;
884
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885 if (*(args[1]) == 0) {
886 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
887 file, linenum, args[0]);
888 return -1;
889 }
Willy Tarreaud825eef2007-05-12 22:35:00 +0200890 __tv_from_ms(&curproxy->clitimeout, atol(args[1]));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891 }
892 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
Willy Tarreaud825eef2007-05-12 22:35:00 +0200893 if (!__tv_iseq(&curproxy->srvtimeout, &defproxy.srvtimeout)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200894 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
895 return 0;
896 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100897 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
898 return 0;
899
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 if (*(args[1]) == 0) {
901 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
902 file, linenum, args[0]);
903 return -1;
904 }
Willy Tarreaud825eef2007-05-12 22:35:00 +0200905 __tv_from_ms(&curproxy->srvtimeout, atol(args[1]));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906 }
907 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100908 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
909 return 0;
910
Willy Tarreaubaaee002006-06-26 02:48:02 +0200911 if (*(args[1]) == 0) {
912 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
913 file, linenum, args[0]);
914 return -1;
915 }
916 curproxy->conn_retries = atol(args[1]);
917 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200918 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
919 int pol = ACL_COND_NONE;
920 struct acl_cond *cond;
921
922 if (!strcmp(args[1], "if"))
923 pol = ACL_COND_IF;
924 else if (!strcmp(args[1], "unless"))
925 pol = ACL_COND_UNLESS;
926
927 if (pol == ACL_COND_NONE) {
928 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
929 file, linenum, args[0]);
930 return -1;
931 }
932
933 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
934 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
935 file, linenum);
936 return -1;
937 }
938 LIST_ADDQ(&curproxy->block_cond, &cond->list);
939 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100941 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
942 return 0;
943
Willy Tarreaubaaee002006-06-26 02:48:02 +0200944 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
945 curproxy->uri_auth = NULL; /* we must detach from the default config */
946
947 if (*(args[1]) == 0) {
948 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
949 return -1;
950 } else if (!strcmp(args[1], "uri")) {
951 if (*(args[2]) == 0) {
952 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
953 return -1;
954 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
955 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
956 return -1;
957 }
958 } else if (!strcmp(args[1], "realm")) {
959 if (*(args[2]) == 0) {
960 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
961 return -1;
962 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
963 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
964 return -1;
965 }
966 } else if (!strcmp(args[1], "auth")) {
967 if (*(args[2]) == 0) {
968 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
969 return -1;
970 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
971 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
972 return -1;
973 }
974 } else if (!strcmp(args[1], "scope")) {
975 if (*(args[2]) == 0) {
976 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
977 return -1;
978 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
979 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
980 return -1;
981 }
982 } else if (!strcmp(args[1], "enable")) {
983 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
984 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
985 return -1;
986 }
987 } else {
988 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'uri', 'realm', 'auth' or 'enable').\n",
989 file, linenum, args[0]);
990 return -1;
991 }
992 }
993 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100994 int optnum;
995
Willy Tarreaubaaee002006-06-26 02:48:02 +0200996 if (*(args[1]) == 0) {
997 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
998 return -1;
999 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001000
1001 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1002 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1003 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1004 return 0;
1005 curproxy->options |= cfg_opts[optnum].val;
Willy Tarreau4fee4e92007-01-06 21:09:17 +01001006 global.last_checks |= cfg_opts[optnum].checks;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001007 return 0;
1008 }
1009 }
1010
1011 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001012 /* generate a complete HTTP log */
1013 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1014 else if (!strcmp(args[1], "tcplog"))
1015 /* generate a detailed TCP log */
1016 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017 else if (!strcmp(args[1], "tcpka")) {
1018 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001019 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1020 return 0;
1021
1022 if (curproxy->cap & PR_CAP_FE)
1023 curproxy->options |= PR_O_TCP_CLI_KA;
1024 if (curproxy->cap & PR_CAP_BE)
1025 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026 }
1027 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001028 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1029 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001030 /* use HTTP request to check servers' health */
1031 if (curproxy->check_req != NULL) {
1032 free(curproxy->check_req);
1033 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001034 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001035 curproxy->options &= ~PR_O_SMTP_CHK;
1036 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037 if (!*args[2]) { /* no argument */
1038 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1039 curproxy->check_len = strlen(DEF_CHECK_REQ);
1040 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001041 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 curproxy->check_req = (char *)malloc(reqlen);
1043 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1044 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1045 } else { /* more arguments : METHOD URI [HTTP_VER] */
1046 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1047 if (*args[4])
1048 reqlen += strlen(args[4]);
1049 else
1050 reqlen += strlen("HTTP/1.0");
1051
1052 curproxy->check_req = (char *)malloc(reqlen);
1053 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1054 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1055 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001056 }
1057 else if (!strcmp(args[1], "ssl-hello-chk")) {
1058 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001059 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1060 return 0;
1061
Willy Tarreauf3c69202006-07-09 16:42:34 +02001062 if (curproxy->check_req != NULL) {
1063 free(curproxy->check_req);
1064 }
1065 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001066 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001067 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 }
Willy Tarreau23677902007-05-08 23:50:35 +02001069 else if (!strcmp(args[1], "smtpchk")) {
1070 /* use SMTP request to check servers' health */
1071 if (curproxy->check_req != NULL) {
1072 free(curproxy->check_req);
1073 }
1074 curproxy->options &= ~PR_O_HTTP_CHK;
1075 curproxy->options &= ~PR_O_SSL3_CHK;
1076 curproxy->options |= PR_O_SMTP_CHK;
1077
1078 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1079 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1080 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1081 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1082 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1083 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1084 curproxy->check_req = (char *)malloc(reqlen);
1085 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1086 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1087 } else {
1088 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1089 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1090 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1091 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1092 }
1093 }
1094 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001095 else if (!strcmp(args[1], "forwardfor")) {
1096 /* insert x-forwarded-for field, but not for the
1097 * IP address listed as an except.
1098 */
1099 if (*(args[2])) {
1100 if (!strcmp(args[2], "except")) {
1101 if (!*args[3] || !str2net(args[3], &curproxy->except_net, &curproxy->except_mask)) {
1102 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1103 file, linenum, args[0]);
1104 return -1;
1105 }
1106 /* flush useless bits */
1107 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
1108 } else {
1109 Alert("parsing [%s:%d] : '%s' only supports optional 'except' address[/mask].\n",
1110 file, linenum, args[0]);
1111 return -1;
1112 }
1113 }
1114 curproxy->options |= PR_O_FWDFOR;
1115 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 else {
1117 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1118 return -1;
1119 }
1120 return 0;
1121 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001122 else if (!strcmp(args[0], "default_backend")) {
1123 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1124 return 0;
1125
1126 if (*(args[1]) == 0) {
1127 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1128 return -1;
1129 }
1130 if (curproxy->defbe.name)
1131 free(curproxy->defbe.name);
1132 curproxy->defbe.name = strdup(args[1]);
1133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001134 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001135 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1136 return 0;
1137
Willy Tarreaubaaee002006-06-26 02:48:02 +02001138 /* enable reconnections to dispatch */
1139 curproxy->options |= PR_O_REDISP;
1140 }
1141#ifdef TPROXY
1142 else if (!strcmp(args[0], "transparent")) {
1143 /* enable transparent proxy connections */
1144 curproxy->options |= PR_O_TRANSP;
1145 }
1146#endif
1147 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001148 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1149 return 0;
1150
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151 if (*(args[1]) == 0) {
1152 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1153 return -1;
1154 }
1155 curproxy->maxconn = atol(args[1]);
1156 }
Willy Tarreau86034312006-12-29 00:10:33 +01001157 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001158 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1159 return 0;
1160
Willy Tarreau86034312006-12-29 00:10:33 +01001161 if (*(args[1]) == 0) {
1162 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1163 return -1;
1164 }
1165 curproxy->fullconn = atol(args[1]);
1166 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1168 if (*(args[1]) == 0) {
1169 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1170 return -1;
1171 }
1172 curproxy->grace = atol(args[1]);
1173 }
1174 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1175 if (curproxy == &defproxy) {
1176 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1177 return -1;
1178 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001179 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1180 return 0;
1181
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182 if (strchr(args[1], ':') == NULL) {
1183 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1184 return -1;
1185 }
1186 curproxy->dispatch_addr = *str2sa(args[1]);
1187 }
1188 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001189 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1190 return 0;
1191
Willy Tarreaubaaee002006-06-26 02:48:02 +02001192 if (*(args[1])) {
1193 if (!strcmp(args[1], "roundrobin")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001194 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001195 curproxy->options |= PR_O_BALANCE_RR;
1196 }
1197 else if (!strcmp(args[1], "source")) {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001198 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001199 curproxy->options |= PR_O_BALANCE_SH;
1200 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001201 else if (!strcmp(args[1], "uri")) {
1202 curproxy->options &= ~PR_O_BALANCE;
1203 curproxy->options |= PR_O_BALANCE_UH;
1204 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 else {
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001206 Alert("parsing [%s:%d] : '%s' only supports 'roundrobin', 'source' and 'uri' options.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001207 return -1;
1208 }
1209 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001210 else {/* if no option is set, use round-robin by default */
1211 curproxy->options &= ~PR_O_BALANCE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001212 curproxy->options |= PR_O_BALANCE_RR;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001214 }
1215 else if (!strcmp(args[0], "server")) { /* server address */
1216 int cur_arg;
1217 char *rport;
1218 char *raddr;
1219 short realport;
1220 int do_check;
1221
1222 if (curproxy == &defproxy) {
1223 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1224 return -1;
1225 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001226 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1227 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228
1229 if (!*args[2]) {
1230 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1231 file, linenum, args[0]);
1232 return -1;
1233 }
1234 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1235 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1236 return -1;
1237 }
1238
1239 /* the servers are linked backwards first */
1240 newsrv->next = curproxy->srv;
1241 curproxy->srv = newsrv;
1242 newsrv->proxy = curproxy;
1243
1244 LIST_INIT(&newsrv->pendconns);
1245 do_check = 0;
1246 newsrv->state = SRV_RUNNING; /* early server setup */
1247 newsrv->id = strdup(args[1]);
1248
1249 /* several ways to check the port component :
1250 * - IP => port=+0, relative
1251 * - IP: => port=+0, relative
1252 * - IP:N => port=N, absolute
1253 * - IP:+N => port=+N, relative
1254 * - IP:-N => port=-N, relative
1255 */
1256 raddr = strdup(args[2]);
1257 rport = strchr(raddr, ':');
1258 if (rport) {
1259 *rport++ = 0;
1260 realport = atol(rport);
1261 if (!isdigit((int)*rport))
1262 newsrv->state |= SRV_MAPPORTS;
1263 } else {
1264 realport = 0;
1265 newsrv->state |= SRV_MAPPORTS;
1266 }
1267
1268 newsrv->addr = *str2sa(raddr);
1269 newsrv->addr.sin_port = htons(realport);
1270 free(raddr);
1271
1272 newsrv->curfd = -1; /* no health-check in progress */
1273 newsrv->inter = DEF_CHKINTR;
1274 newsrv->rise = DEF_RISETIME;
1275 newsrv->fall = DEF_FALLTIME;
1276 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001277 newsrv->uweight = 1;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001278
Willy Tarreaubaaee002006-06-26 02:48:02 +02001279 cur_arg = 3;
1280 while (*args[cur_arg]) {
1281 if (!strcmp(args[cur_arg], "cookie")) {
1282 newsrv->cookie = strdup(args[cur_arg + 1]);
1283 newsrv->cklen = strlen(args[cur_arg + 1]);
1284 cur_arg += 2;
1285 }
1286 else if (!strcmp(args[cur_arg], "rise")) {
1287 newsrv->rise = atol(args[cur_arg + 1]);
1288 newsrv->health = newsrv->rise;
1289 cur_arg += 2;
1290 }
1291 else if (!strcmp(args[cur_arg], "fall")) {
1292 newsrv->fall = atol(args[cur_arg + 1]);
1293 cur_arg += 2;
1294 }
1295 else if (!strcmp(args[cur_arg], "inter")) {
1296 newsrv->inter = atol(args[cur_arg + 1]);
1297 cur_arg += 2;
1298 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001299 else if (!strcmp(args[cur_arg], "addr")) {
1300 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02001301 cur_arg += 2;
1302 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001303 else if (!strcmp(args[cur_arg], "port")) {
1304 newsrv->check_port = atol(args[cur_arg + 1]);
1305 cur_arg += 2;
1306 }
1307 else if (!strcmp(args[cur_arg], "backup")) {
1308 newsrv->state |= SRV_BACKUP;
1309 cur_arg ++;
1310 }
1311 else if (!strcmp(args[cur_arg], "weight")) {
1312 int w;
1313 w = atol(args[cur_arg + 1]);
1314 if (w < 1 || w > 256) {
1315 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1316 file, linenum, newsrv->id, w);
1317 return -1;
1318 }
Willy Tarreau417fae02007-03-25 21:16:40 +02001319 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001320 cur_arg += 2;
1321 }
1322 else if (!strcmp(args[cur_arg], "minconn")) {
1323 newsrv->minconn = atol(args[cur_arg + 1]);
1324 cur_arg += 2;
1325 }
1326 else if (!strcmp(args[cur_arg], "maxconn")) {
1327 newsrv->maxconn = atol(args[cur_arg + 1]);
1328 cur_arg += 2;
1329 }
1330 else if (!strcmp(args[cur_arg], "check")) {
1331 global.maxsock++;
1332 do_check = 1;
1333 cur_arg += 1;
1334 }
1335 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1336 if (!*args[cur_arg + 1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001337#ifdef CONFIG_HAP_CTTPROXY
1338 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1339 file, linenum, "source", "usesrc");
1340#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001341 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1342 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001343#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001344 return -1;
1345 }
1346 newsrv->state |= SRV_BIND_SRC;
1347 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1348 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001349 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001350#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001351 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001352 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
1353 file, linenum, "usesrc", "source");
Willy Tarreau77074d52006-11-12 23:57:19 +01001354 return -1;
1355 }
1356 if (!*args[cur_arg + 1]) {
1357 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1358 file, linenum, "usesrc");
1359 return -1;
1360 }
1361 if (!strcmp(args[cur_arg + 1], "client")) {
1362 newsrv->state |= SRV_TPROXY_CLI;
1363 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1364 newsrv->state |= SRV_TPROXY_CIP;
1365 } else {
1366 newsrv->state |= SRV_TPROXY_ADDR;
1367 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1368 }
1369 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1370 cur_arg += 2;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001371#else /* no CTTPROXY support */
1372 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1373 file, linenum, "usesrc");
1374 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001375#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001376 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001377 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001378#ifdef CONFIG_HAP_CTTPROXY
1379 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
1380 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1381 file, linenum, "usesrc", "source");
1382 return -1;
1383 }
1384#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 else {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001386 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 +02001387 file, linenum, newsrv->id);
1388 return -1;
1389 }
1390 }
1391
1392 if (do_check) {
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001393 if (!newsrv->check_port && newsrv->check_addr.sin_port)
1394 newsrv->check_port = newsrv->check_addr.sin_port;
1395
Willy Tarreaubaaee002006-06-26 02:48:02 +02001396 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1397 newsrv->check_port = realport; /* by default */
1398 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01001399 /* not yet valid, because no port was set on
1400 * the server either. We'll check if we have
1401 * a known port on the first listener.
1402 */
1403 struct listener *l;
1404 l = curproxy->listen;
1405 if (l) {
1406 int port;
1407 port = (l->addr.ss_family == AF_INET6)
1408 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
1409 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
1410 newsrv->check_port = port;
1411 }
1412 }
1413 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1415 file, linenum, newsrv->id);
1416 return -1;
1417 }
1418 newsrv->state |= SRV_CHECKED;
1419 }
1420
1421 if (newsrv->state & SRV_BACKUP)
1422 curproxy->srv_bck++;
1423 else
1424 curproxy->srv_act++;
1425 }
1426 else if (!strcmp(args[0], "log")) { /* syslog server address */
1427 struct sockaddr_in *sa;
1428 int facility;
1429
1430 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1431 curproxy->logfac1 = global.logfac1;
1432 curproxy->logsrv1 = global.logsrv1;
1433 curproxy->loglev1 = global.loglev1;
1434 curproxy->logfac2 = global.logfac2;
1435 curproxy->logsrv2 = global.logsrv2;
1436 curproxy->loglev2 = global.loglev2;
1437 }
1438 else if (*(args[1]) && *(args[2])) {
1439 int level;
1440
1441 facility = get_log_facility(args[2]);
1442 if (facility < 0) {
1443 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1444 exit(1);
1445 }
1446
1447 level = 7; /* max syslog level = debug */
1448 if (*(args[3])) {
1449 level = get_log_level(args[3]);
1450 if (level < 0) {
1451 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1452 exit(1);
1453 }
1454 }
1455
1456 sa = str2sa(args[1]);
1457 if (!sa->sin_port)
1458 sa->sin_port = htons(SYSLOG_PORT);
1459
1460 if (curproxy->logfac1 == -1) {
1461 curproxy->logsrv1 = *sa;
1462 curproxy->logfac1 = facility;
1463 curproxy->loglev1 = level;
1464 }
1465 else if (curproxy->logfac2 == -1) {
1466 curproxy->logsrv2 = *sa;
1467 curproxy->logfac2 = facility;
1468 curproxy->loglev2 = level;
1469 }
1470 else {
1471 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1472 return -1;
1473 }
1474 }
1475 else {
1476 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1477 file, linenum);
1478 return -1;
1479 }
1480 }
1481 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001482 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1483 return 0;
1484
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485 if (!*args[1]) {
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001486#ifdef CONFIG_HAP_CTTPROXY
1487 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
1488 file, linenum, "source", "usesrc");
1489#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1491 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001492#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493 return -1;
1494 }
1495
1496 curproxy->source_addr = *str2sa(args[1]);
1497 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001498 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001499#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreau77074d52006-11-12 23:57:19 +01001500 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1501 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1502 file, linenum, "usesrc");
1503 return -1;
1504 }
1505 if (!*args[3]) {
1506 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1507 file, linenum, "usesrc");
1508 return -1;
1509 }
1510
1511 if (!strcmp(args[3], "client")) {
1512 curproxy->options |= PR_O_TPXY_CLI;
1513 } else if (!strcmp(args[3], "clientip")) {
1514 curproxy->options |= PR_O_TPXY_CIP;
1515 } else {
1516 curproxy->options |= PR_O_TPXY_ADDR;
1517 curproxy->tproxy_addr = *str2sa(args[3]);
1518 }
1519 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001520#else /* no CTTPROXY support */
1521 Alert("parsing [%s:%d] : '%s' not allowed here because support for cttproxy was not compiled in.\n",
1522 file, linenum, "usesrc");
1523 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01001524#endif
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001525 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001526 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01001527#ifdef CONFIG_HAP_CTTPROXY
1528 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
1529 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
1530 file, linenum, "usesrc", "source");
1531 return -1;
1532 }
1533#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001534 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1535 regex_t *preg;
1536 if (curproxy == &defproxy) {
1537 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1538 return -1;
1539 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001540 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1541 return 0;
1542
Willy Tarreaubaaee002006-06-26 02:48:02 +02001543 if (*(args[1]) == 0 || *(args[2]) == 0) {
1544 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1545 file, linenum, args[0]);
1546 return -1;
1547 }
1548
1549 preg = calloc(1, sizeof(regex_t));
1550 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1551 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1552 return -1;
1553 }
1554
1555 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1556 if (err) {
1557 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1558 file, linenum, *err);
1559 return -1;
1560 }
1561 }
1562 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1563 regex_t *preg;
1564 if (curproxy == &defproxy) {
1565 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1566 return -1;
1567 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001568 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1569 return 0;
1570
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 if (*(args[1]) == 0) {
1572 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1573 return -1;
1574 }
1575
1576 preg = calloc(1, sizeof(regex_t));
1577 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1578 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1579 return -1;
1580 }
1581
1582 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1583 }
1584 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1585 regex_t *preg;
1586 if (curproxy == &defproxy) {
1587 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1588 return -1;
1589 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001590 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1591 return 0;
1592
Willy Tarreaubaaee002006-06-26 02:48:02 +02001593 if (*(args[1]) == 0) {
1594 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1595 return -1;
1596 }
1597
1598 preg = calloc(1, sizeof(regex_t));
1599 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1600 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1601 return -1;
1602 }
1603
1604 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1605 }
1606 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1607 regex_t *preg;
1608 if (curproxy == &defproxy) {
1609 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1610 return -1;
1611 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001612 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1613 return 0;
1614
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615 if (*(args[1]) == 0) {
1616 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1617 return -1;
1618 }
1619
1620 preg = calloc(1, sizeof(regex_t));
1621 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1622 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1623 return -1;
1624 }
1625
1626 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1627 }
1628 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1629 regex_t *preg;
1630 if (curproxy == &defproxy) {
1631 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1632 return -1;
1633 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001634 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1635 return 0;
1636
Willy Tarreaubaaee002006-06-26 02:48:02 +02001637 if (*(args[1]) == 0) {
1638 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1639 return -1;
1640 }
1641
1642 preg = calloc(1, sizeof(regex_t));
1643 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1644 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1645 return -1;
1646 }
1647
1648 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1649 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001650 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1651 regex_t *preg;
1652 if (curproxy == &defproxy) {
1653 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1654 return -1;
1655 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001656 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1657 return 0;
1658
Willy Tarreaub8750a82006-09-03 09:56:00 +02001659 if (*(args[1]) == 0) {
1660 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1661 return -1;
1662 }
1663
1664 preg = calloc(1, sizeof(regex_t));
1665 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1666 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1667 return -1;
1668 }
1669
1670 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1671 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001672 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1673 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001674 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001675 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1676 return -1;
1677 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001678 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1679 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001680
Willy Tarreau977b8e42006-12-29 14:19:17 +01001681 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001682 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1683 file, linenum, args[0]);
1684 return -1;
1685 }
1686
1687 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001688 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001689 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1690 }
1691
1692 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1693 }
1694 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1695 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001696 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001697 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1698 return -1;
1699 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001700 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1701 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01001702
Willy Tarreau977b8e42006-12-29 14:19:17 +01001703 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001704 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1705 file, linenum, args[0]);
1706 return -1;
1707 }
1708
1709 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01001710 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01001711 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1712 }
1713
1714 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1715 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001716 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1717 regex_t *preg;
1718 if (curproxy == &defproxy) {
1719 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1720 return -1;
1721 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001722 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1723 return 0;
1724
Willy Tarreaubaaee002006-06-26 02:48:02 +02001725 if (*(args[1]) == 0 || *(args[2]) == 0) {
1726 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1727 file, linenum, args[0]);
1728 return -1;
1729 }
1730
1731 preg = calloc(1, sizeof(regex_t));
1732 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1733 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1734 return -1;
1735 }
1736
1737 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1738 if (err) {
1739 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1740 file, linenum, *err);
1741 return -1;
1742 }
1743 }
1744 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1745 regex_t *preg;
1746 if (curproxy == &defproxy) {
1747 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1748 return -1;
1749 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001750 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1751 return 0;
1752
Willy Tarreaubaaee002006-06-26 02:48:02 +02001753 if (*(args[1]) == 0) {
1754 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1755 return -1;
1756 }
1757
1758 preg = calloc(1, sizeof(regex_t));
1759 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1760 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1761 return -1;
1762 }
1763
1764 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1765 }
1766 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1767 regex_t *preg;
1768 if (curproxy == &defproxy) {
1769 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1770 return -1;
1771 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001772 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1773 return 0;
1774
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775 if (*(args[1]) == 0) {
1776 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1777 return -1;
1778 }
1779
1780 preg = calloc(1, sizeof(regex_t));
1781 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1782 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1783 return -1;
1784 }
1785
1786 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1787 }
1788 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1789 regex_t *preg;
1790 if (curproxy == &defproxy) {
1791 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1792 return -1;
1793 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001794 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1795 return 0;
1796
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797 if (*(args[1]) == 0) {
1798 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1799 return -1;
1800 }
1801
1802 preg = calloc(1, sizeof(regex_t));
1803 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1804 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1805 return -1;
1806 }
1807
1808 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1809 }
1810 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1811 regex_t *preg;
1812 if (curproxy == &defproxy) {
1813 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1814 return -1;
1815 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001816 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1817 return 0;
1818
Willy Tarreaubaaee002006-06-26 02:48:02 +02001819 if (*(args[1]) == 0) {
1820 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1821 return -1;
1822 }
1823
1824 preg = calloc(1, sizeof(regex_t));
1825 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1826 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1827 return -1;
1828 }
1829
1830 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1831 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001832 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1833 regex_t *preg;
1834 if (curproxy == &defproxy) {
1835 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1836 return -1;
1837 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001838 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1839 return 0;
1840
Willy Tarreaub8750a82006-09-03 09:56:00 +02001841 if (*(args[1]) == 0) {
1842 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1843 return -1;
1844 }
1845
1846 preg = calloc(1, sizeof(regex_t));
1847 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1848 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1849 return -1;
1850 }
1851
1852 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1853 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001854 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1855 if (curproxy == &defproxy) {
1856 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1857 return -1;
1858 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001859 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1860 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001861
1862 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
1863 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1864 return 0;
1865 }
1866
1867 if (*(args[1]) == 0) {
1868 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1869 return -1;
1870 }
1871
1872 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
1873 }
1874 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
1875 regex_t *preg;
1876
1877 if (*(args[1]) == 0 || *(args[2]) == 0) {
1878 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1879 file, linenum, args[0]);
1880 return -1;
1881 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001882 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1883 return 0;
1884
Willy Tarreaubaaee002006-06-26 02:48:02 +02001885 preg = calloc(1, sizeof(regex_t));
1886 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1887 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1888 return -1;
1889 }
1890
1891 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1892 if (err) {
1893 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1894 file, linenum, *err);
1895 return -1;
1896 }
1897 }
1898 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
1899 regex_t *preg;
1900 if (curproxy == &defproxy) {
1901 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1902 return -1;
1903 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001904 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1905 return 0;
1906
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907 if (*(args[1]) == 0) {
1908 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1909 return -1;
1910 }
1911
1912 preg = calloc(1, sizeof(regex_t));
1913 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1914 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1915 return -1;
1916 }
1917
1918 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
1919 if (err) {
1920 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1921 file, linenum, *err);
1922 return -1;
1923 }
1924 }
1925 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
1926 regex_t *preg;
1927 if (curproxy == &defproxy) {
1928 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1929 return -1;
1930 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001931 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1932 return 0;
1933
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934 if (*(args[1]) == 0) {
1935 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1936 return -1;
1937 }
1938
1939 preg = calloc(1, sizeof(regex_t));
1940 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1941 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1942 return -1;
1943 }
1944
1945 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
1946 if (err) {
1947 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1948 file, linenum, *err);
1949 return -1;
1950 }
1951 }
1952 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
1953 regex_t *preg;
1954 if (curproxy == &defproxy) {
1955 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1956 return -1;
1957 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001958 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1959 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001960
1961 if (*(args[1]) == 0 || *(args[2]) == 0) {
1962 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1963 file, linenum, args[0]);
1964 return -1;
1965 }
1966
1967 preg = calloc(1, sizeof(regex_t));
1968 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1969 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1970 return -1;
1971 }
1972
1973 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1974 if (err) {
1975 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1976 file, linenum, *err);
1977 return -1;
1978 }
1979 }
1980 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
1981 regex_t *preg;
1982 if (curproxy == &defproxy) {
1983 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1984 return -1;
1985 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001986 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1987 return 0;
1988
Willy Tarreaubaaee002006-06-26 02:48:02 +02001989 if (*(args[1]) == 0) {
1990 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1991 return -1;
1992 }
1993
1994 preg = calloc(1, sizeof(regex_t));
1995 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1996 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1997 return -1;
1998 }
1999
2000 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2001 if (err) {
2002 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2003 file, linenum, *err);
2004 return -1;
2005 }
2006 }
2007 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2008 regex_t *preg;
2009 if (curproxy == &defproxy) {
2010 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2011 return -1;
2012 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002013 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2014 return 0;
2015
Willy Tarreaubaaee002006-06-26 02:48:02 +02002016 if (*(args[1]) == 0) {
2017 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2018 return -1;
2019 }
2020
2021 preg = calloc(1, sizeof(regex_t));
2022 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2023 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2024 return -1;
2025 }
2026
2027 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2028 if (err) {
2029 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2030 file, linenum, *err);
2031 return -1;
2032 }
2033 }
2034 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2035 if (curproxy == &defproxy) {
2036 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2037 return -1;
2038 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002039 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2040 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041
2042 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2043 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2044 return 0;
2045 }
2046
2047 if (*(args[1]) == 0) {
2048 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2049 return -1;
2050 }
2051
2052 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2053 }
2054 else if (!strcmp(args[0], "errorloc") ||
2055 !strcmp(args[0], "errorloc302") ||
2056 !strcmp(args[0], "errorloc303")) { /* error location */
2057 int errnum, errlen;
2058 char *err;
2059
2060 // if (curproxy == &defproxy) {
2061 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2062 // return -1;
2063 // }
2064
Willy Tarreau977b8e42006-12-29 14:19:17 +01002065 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2066 return 0;
2067
Willy Tarreaubaaee002006-06-26 02:48:02 +02002068 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01002069 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002070 return -1;
2071 }
2072
2073 errnum = atol(args[1]);
2074 if (!strcmp(args[0], "errorloc303")) {
2075 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2076 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2077 } else {
2078 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2079 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2080 }
2081
Willy Tarreau0f772532006-12-23 20:51:41 +01002082 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2083 if (http_err_codes[rc] == errnum) {
2084 if (curproxy->errmsg[rc].str)
2085 free(curproxy->errmsg[rc].str);
2086 curproxy->errmsg[rc].str = err;
2087 curproxy->errmsg[rc].len = errlen;
2088 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002089 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002090 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002091
2092 if (rc >= HTTP_ERR_SIZE) {
2093 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2094 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 free(err);
2096 }
2097 }
2098 else {
2099 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
2100 return -1;
2101 }
2102 return 0;
2103}
2104
2105
2106/*
2107 * This function reads and parses the configuration file given in the argument.
2108 * returns 0 if OK, -1 if error.
2109 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02002110int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111{
2112 char thisline[256];
2113 char *line;
2114 FILE *f;
2115 int linenum = 0;
2116 char *end;
Willy Tarreau540abe42007-05-02 20:50:16 +02002117 char *args[MAX_LINE_ARGS + 1];
Willy Tarreaubaaee002006-06-26 02:48:02 +02002118 int arg;
2119 int cfgerr = 0;
Willy Tarreau80587432006-12-24 17:47:20 +01002120 int nbchk, mininter;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002121 int confsect = CFG_NONE;
2122
2123 struct proxy *curproxy = NULL;
2124 struct server *newsrv = NULL;
2125
2126 if ((f=fopen(file,"r")) == NULL)
2127 return -1;
2128
2129 init_default_instance();
2130
2131 while (fgets(line = thisline, sizeof(thisline), f) != NULL) {
2132 linenum++;
2133
2134 end = line + strlen(line);
2135
2136 /* skip leading spaces */
2137 while (isspace((int)*line))
2138 line++;
2139
2140 arg = 0;
2141 args[arg] = line;
2142
2143 while (*line && arg < MAX_LINE_ARGS) {
2144 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
2145 * C equivalent value. Other combinations left unchanged (eg: \1).
2146 */
2147 if (*line == '\\') {
2148 int skip = 0;
2149 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
2150 *line = line[1];
2151 skip = 1;
2152 }
2153 else if (line[1] == 'r') {
2154 *line = '\r';
2155 skip = 1;
2156 }
2157 else if (line[1] == 'n') {
2158 *line = '\n';
2159 skip = 1;
2160 }
2161 else if (line[1] == 't') {
2162 *line = '\t';
2163 skip = 1;
2164 }
2165 else if (line[1] == 'x') {
2166 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
2167 unsigned char hex1, hex2;
2168 hex1 = toupper(line[2]) - '0';
2169 hex2 = toupper(line[3]) - '0';
2170 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
2171 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
2172 *line = (hex1<<4) + hex2;
2173 skip = 3;
2174 }
2175 else {
2176 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
2177 return -1;
2178 }
2179 }
2180 if (skip) {
2181 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
2182 end -= skip;
2183 }
2184 line++;
2185 }
2186 else if (*line == '#' || *line == '\n' || *line == '\r') {
2187 /* end of string, end of loop */
2188 *line = 0;
2189 break;
2190 }
2191 else if (isspace((int)*line)) {
2192 /* a non-escaped space is an argument separator */
2193 *line++ = 0;
2194 while (isspace((int)*line))
2195 line++;
2196 args[++arg] = line;
2197 }
2198 else {
2199 line++;
2200 }
2201 }
2202
2203 /* empty line */
2204 if (!**args)
2205 continue;
2206
Willy Tarreau540abe42007-05-02 20:50:16 +02002207 /* zero out remaining args and ensure that at least one entry
2208 * is zeroed out.
2209 */
2210 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002211 args[arg] = line;
2212 }
2213
Willy Tarreau977b8e42006-12-29 14:19:17 +01002214 if (!strcmp(args[0], "listen") ||
2215 !strcmp(args[0], "frontend") ||
2216 !strcmp(args[0], "backend") ||
2217 !strcmp(args[0], "ruleset") ||
2218 !strcmp(args[0], "defaults")) /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002219 confsect = CFG_LISTEN;
2220 else if (!strcmp(args[0], "global")) /* global config */
2221 confsect = CFG_GLOBAL;
2222 /* else it's a section keyword */
2223
2224 switch (confsect) {
2225 case CFG_LISTEN:
2226 if (cfg_parse_listen(file, linenum, args) < 0)
2227 return -1;
2228 break;
2229 case CFG_GLOBAL:
2230 if (cfg_parse_global(file, linenum, args) < 0)
2231 return -1;
2232 break;
2233 default:
2234 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
2235 return -1;
2236 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002237 }
2238 fclose(f);
2239
2240 /*
2241 * Now, check for the integrity of all that we have collected.
2242 */
2243
2244 /* will be needed further to delay some tasks */
2245 tv_now(&now);
2246
2247 if ((curproxy = proxy) == NULL) {
2248 Alert("parsing %s : no <listen> line. Nothing to do !\n",
2249 file);
2250 return -1;
2251 }
2252
2253 while (curproxy != NULL) {
2254 if (curproxy->state == PR_STSTOPPED) {
2255 curproxy = curproxy->next;
2256 continue;
2257 }
2258
Willy Tarreau977b8e42006-12-29 14:19:17 +01002259 if (curproxy->cap & PR_CAP_FE && curproxy->listen == NULL) {
2260 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 +01002261 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002262 cfgerr++;
2263 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002264 else if (curproxy->cap & PR_CAP_BE &&
2265 ((curproxy->mode != PR_MODE_HEALTH) &&
2266 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
2267 (*(int *)&curproxy->dispatch_addr.sin_addr == 0))) {
2268 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 +01002269 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 cfgerr++;
2271 }
2272 else if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
2273 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002274 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002275 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 cfgerr++;
2277 }
2278#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
2279 else if (curproxy->srv == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002280 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002281 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 cfgerr++;
2283 }
2284#endif
2285 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002286 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002287 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 }
2289 }
2290 else if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
2291 if (curproxy->cookie_name != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002292 Warning("parsing %s : cookie will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002293 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 }
2295 if ((newsrv = curproxy->srv) != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002296 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002297 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 }
2299 if (curproxy->rsp_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002300 Warning("parsing %s : server regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002301 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002302 }
2303 if (curproxy->req_exp != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002304 Warning("parsing %s : client regular expressions will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002305 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002307 if (curproxy->monitor_uri != NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002308 Warning("parsing %s : monitor-uri will be ignored for %s '%s'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002309 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002310 }
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002311 if (curproxy->options & PR_O_BALANCE_UH) {
2312 curproxy->options &= ~PR_O_BALANCE;
2313 curproxy->options |= PR_O_BALANCE_RR;
2314
2315 Warning("parsing %s : URI hash will be ignored for %s '%s'. Falling back to round robin.\n",
2316 file, proxy_type_str(curproxy), curproxy->id);
2317 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002318 }
2319 else if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
2320 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
2321 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
2322 file, curproxy->id);
2323 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002324 }
2325 }
2326
2327 /* if a default backend was specified, let's find it */
2328 if (curproxy->defbe.name) {
2329 struct proxy *target;
2330
2331 for (target = proxy; target != NULL; target = target->next) {
2332 if (strcmp(target->id, curproxy->defbe.name) == 0)
2333 break;
2334 }
2335 if (target == NULL) {
2336 Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n",
2337 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2338 cfgerr++;
2339 } else if (target == curproxy) {
2340 Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name);
2341 cfgerr++;
2342 } else if (!(target->cap & PR_CAP_BE)) {
2343 Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n",
2344 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2345 cfgerr++;
2346 } else if (target->mode != curproxy->mode) {
2347 Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n",
2348 file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id);
2349 cfgerr++;
2350 } else {
2351 free(curproxy->defbe.name);
2352 curproxy->defbe.be = target;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 }
2354 }
2355
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002356 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01002357 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
2358 /* map jump target for ACT_SETBE in req_rep chain */
2359 struct hdr_exp *exp;
2360 struct proxy *target;
2361 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
2362 if (exp->action != ACT_SETBE)
2363 continue;
2364 for (target = proxy; target != NULL; target = target->next) {
2365 if (strcmp(target->id, exp->replace) == 0)
2366 break;
2367 }
2368 if (target == NULL) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002369 Alert("parsing %s : backend '%s' in HTTP %s '%s' was not found !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002370 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaua496b602006-12-17 23:15:24 +01002371 cfgerr++;
2372 } else if (target == curproxy) {
2373 Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
2374 cfgerr++;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002375 } else if (!(target->cap & PR_CAP_BE)) {
2376 Alert("parsing %s : target '%s' in HTTP %s '%s' has no backend capability !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002377 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002378 cfgerr++;
2379 } else if (target->mode != PR_MODE_HTTP) {
2380 Alert("parsing %s : backend '%s' in HTTP %s '%s' is not HTTP (use 'mode http') !\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002381 file, exp->replace, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002382 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01002383 } else {
2384 free((void *)exp->replace);
2385 exp->replace = (const char *)target;
2386 }
2387 }
2388 }
Willy Tarreau2738a142006-07-08 17:28:09 +02002389 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud825eef2007-05-12 22:35:00 +02002390 (((curproxy->cap & PR_CAP_FE) && !tv_isset(&curproxy->clitimeout)) ||
2391 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
2392 (!tv_isset(&curproxy->contimeout) || !tv_isset(&curproxy->srvtimeout))))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002393 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02002394 " | While not properly invalid, you will certainly encounter various problems\n"
2395 " | with such a configuration. To fix this, please ensure that all following\n"
2396 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002397 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02002398 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002399
2400 if (curproxy->options & PR_O_SSL3_CHK) {
2401 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
2402 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
2403 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
2404 }
2405
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002406 /* The small pools required for the capture lists */
2407 if (curproxy->nb_req_cap)
2408 curproxy->req_cap_pool = create_pool("ptrcap",
2409 curproxy->nb_req_cap * sizeof(char *),
2410 MEM_F_SHARED);
2411 if (curproxy->nb_rsp_cap)
2412 curproxy->rsp_cap_pool = create_pool("ptrcap",
2413 curproxy->nb_rsp_cap * sizeof(char *),
2414 MEM_F_SHARED);
2415
Willy Tarreau1d4154a2007-05-13 22:57:02 +02002416 curproxy->hdr_idx_pool = create_pool("hdr_idx",
2417 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
2418 MEM_F_SHARED);
2419
Willy Tarreau86034312006-12-29 00:10:33 +01002420 /* for backwards compatibility with "listen" instances, if
2421 * fullconn is not set but maxconn is set, then maxconn
2422 * is used.
2423 */
2424 if (!curproxy->fullconn)
2425 curproxy->fullconn = curproxy->maxconn;
2426
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 /* first, we will invert the servers list order */
2428 newsrv = NULL;
2429 while (curproxy->srv) {
2430 struct server *next;
2431
2432 next = curproxy->srv->next;
2433 curproxy->srv->next = newsrv;
2434 newsrv = curproxy->srv;
2435 if (!next)
2436 break;
2437 curproxy->srv = next;
2438 }
2439
2440 /* now, newsrv == curproxy->srv */
2441 if (newsrv) {
2442 struct server *srv;
2443 int pgcd;
2444 int act, bck;
2445
2446 /* We will factor the weights to reduce the table,
2447 * using Euclide's largest common divisor algorithm
2448 */
Willy Tarreau417fae02007-03-25 21:16:40 +02002449 pgcd = newsrv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2451 int t, w;
2452
Willy Tarreau417fae02007-03-25 21:16:40 +02002453 w = srv->uweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454 while (w) {
2455 t = pgcd % w;
2456 pgcd = w;
2457 w = t;
2458 }
2459 }
2460
2461 act = bck = 0;
2462 for (srv = newsrv; srv; srv = srv->next) {
Willy Tarreau417fae02007-03-25 21:16:40 +02002463 srv->eweight = srv->uweight / pgcd;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002464 if (srv->state & SRV_BACKUP)
Willy Tarreau417fae02007-03-25 21:16:40 +02002465 bck += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 else
Willy Tarreau417fae02007-03-25 21:16:40 +02002467 act += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 }
2469
2470 /* this is the largest map we will ever need for this servers list */
2471 if (act < bck)
2472 act = bck;
2473
2474 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2475 /* recounts servers and their weights */
2476 recount_servers(curproxy);
2477 recalc_server_map(curproxy);
2478 }
2479
2480 if (curproxy->options & PR_O_LOGASAP)
2481 curproxy->to_log &= ~LW_BYTES;
2482
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483 /*
2484 * If this server supports a maxconn parameter, it needs a dedicated
2485 * tasks to fill the emptied slots when a connection leaves.
2486 */
2487 newsrv = curproxy->srv;
2488 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01002489 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002490 /* Only 'minconn' was specified, or it was higher than or equal
2491 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2492 * this will avoid further useless expensive computations.
2493 */
2494 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01002495 } else if (newsrv->maxconn && !newsrv->minconn) {
2496 /* minconn was not specified, so we set it to maxconn */
2497 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002498 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
2499 Alert("parsing %s, %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01002500 file, proxy_type_str(curproxy), curproxy->id, linenum);
Willy Tarreau86034312006-12-29 00:10:33 +01002501 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002502 }
2503
2504 if (newsrv->maxconn > 0) {
2505 struct task *t;
2506
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002507 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002508 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2509 return -1;
2510 }
2511
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002512 t->qlist.p = NULL;
Willy Tarreau964c9362007-01-07 00:38:00 +01002513 t->wq = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 t->state = TASK_IDLE;
2515 t->process = process_srv_queue;
2516 t->context = newsrv;
2517 newsrv->queue_mgt = t;
2518
2519 /* never run it unless specifically woken up */
2520 tv_eternity(&t->expire);
2521 task_queue(t);
2522 }
2523 newsrv = newsrv->next;
2524 }
2525
2526 /* now we'll start this proxy's health checks if any */
2527 /* 1- count the checkers to run simultaneously */
2528 nbchk = 0;
2529 mininter = 0;
2530 newsrv = curproxy->srv;
2531 while (newsrv != NULL) {
2532 if (newsrv->state & SRV_CHECKED) {
2533 if (!mininter || mininter > newsrv->inter)
2534 mininter = newsrv->inter;
2535 nbchk++;
2536 }
2537 newsrv = newsrv->next;
2538 }
2539
2540 /* 2- start them as far as possible from each others while respecting
2541 * their own intervals. For this, we will start them after their own
2542 * interval added to the min interval divided by the number of servers,
2543 * weighted by the server's position in the list.
2544 */
2545 if (nbchk > 0) {
2546 struct task *t;
2547 int srvpos;
2548
2549 newsrv = curproxy->srv;
2550 srvpos = 0;
2551 while (newsrv != NULL) {
2552 /* should this server be checked ? */
2553 if (newsrv->state & SRV_CHECKED) {
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02002554 if ((t = pool_alloc2(pool2_task)) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2556 return -1;
2557 }
2558
Willy Tarreau964c9362007-01-07 00:38:00 +01002559 t->wq = NULL;
Willy Tarreau96bcfd72007-04-29 10:41:56 +02002560 t->qlist.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 t->state = TASK_IDLE;
2562 t->process = process_chk;
2563 t->context = newsrv;
2564
2565 /* check this every ms */
Willy Tarreau42aae5c2007-04-29 17:43:56 +02002566 tv_ms_add(&t->expire, &now,
2567 newsrv->inter + mininter * srvpos / nbchk);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 task_queue(t);
2569 //task_wakeup(&rq, t);
2570 srvpos++;
2571 }
2572 newsrv = newsrv->next;
2573 }
2574 }
2575
2576 curproxy = curproxy->next;
2577 }
2578 if (cfgerr > 0) {
2579 Alert("Errors found in configuration file, aborting.\n");
2580 return -1;
2581 }
2582 else
2583 return 0;
2584}
2585
2586
2587
2588/*
2589 * Local variables:
2590 * c-indent-level: 8
2591 * c-basic-offset: 8
2592 * End:
2593 */