blob: f3659f5030d25c82349fa5231eaaa74b13cdbdb1 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
4 * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
18
Willy Tarreau2dd0d472006-06-29 17:53:05 +020019#include <common/cfgparse.h>
20#include <common/config.h>
21#include <common/memory.h>
22#include <common/standard.h>
23#include <common/time.h>
24#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
26#include <types/capture.h>
27#include <types/global.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010028#include <types/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020029#include <types/polling.h>
30#include <types/proxy.h>
31#include <types/queue.h>
32
33#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010034#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035#include <proto/checks.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010036#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <proto/log.h>
38#include <proto/server.h>
39#include <proto/task.h>
40
41
Willy Tarreauf3c69202006-07-09 16:42:34 +020042/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
43 * ssl-hello-chk option to ensure that the remote server speaks SSL.
44 *
45 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
46 */
47const char sslv3_client_hello_pkt[] = {
48 "\x16" /* ContentType : 0x16 = Hanshake */
49 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
50 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
51 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
52 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
53 "\x03\x00" /* Hello Version : 0x0300 = v3 */
54 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
55 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
56 "\x00" /* Session ID length : empty (no session ID) */
57 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
58 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
59 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
60 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
61 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
62 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
63 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
64 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
65 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
66 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
67 "\x00\x38" "\x00\x39" "\x00\x3A"
68 "\x01" /* Compression Length : 0x01 = 1 byte for types */
69 "\x00" /* Compression Type : 0x00 = NULL compression */
70};
71
Willy Tarreaubaaee002006-06-26 02:48:02 +020072
73static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
74int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
75int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
76
77/*
78 * converts <str> to a list of listeners which are dynamically allocated.
79 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
80 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
81 * - <port> is a numerical port from 1 to 65535 ;
82 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
83 * This can be repeated as many times as necessary, separated by a coma.
84 * The <tail> argument is a pointer to a current list which should be appended
85 * to the tail of the new list. The pointer to the new list is returned.
86 */
87static struct listener *str2listener(char *str, struct listener *tail)
88{
89 struct listener *l;
90 char *c, *next, *range, *dupstr;
91 int port, end;
92
93 next = dupstr = strdup(str);
94
95 while (next && *next) {
96 struct sockaddr_storage ss;
97
98 str = next;
99 /* 1) look for the end of the first address */
100 if ((next = strrchr(str, ',')) != NULL) {
101 *next++ = 0;
102 }
103
104 /* 2) look for the addr/port delimiter, it's the last colon. */
105 if ((range = strrchr(str, ':')) == NULL) {
106 Alert("Missing port number: '%s'\n", str);
107 goto fail;
108 }
109
110 *range++ = 0;
111
112 if (strrchr(str, ':') != NULL) {
113 /* IPv6 address contains ':' */
114 memset(&ss, 0, sizeof(ss));
115 ss.ss_family = AF_INET6;
116
117 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
118 Alert("Invalid server address: '%s'\n", str);
119 goto fail;
120 }
121 }
122 else {
123 memset(&ss, 0, sizeof(ss));
124 ss.ss_family = AF_INET;
125
126 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
127 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
128 }
129 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
130 struct hostent *he;
131
132 if ((he = gethostbyname(str)) == NULL) {
133 Alert("Invalid server name: '%s'\n", str);
134 goto fail;
135 }
136 else
137 ((struct sockaddr_in *)&ss)->sin_addr =
138 *(struct in_addr *) *(he->h_addr_list);
139 }
140 }
141
142 /* 3) look for the port-end delimiter */
143 if ((c = strchr(range, '-')) != NULL) {
144 *c++ = 0;
145 end = atol(c);
146 }
147 else {
148 end = atol(range);
149 }
150
151 port = atol(range);
152
153 if (port < 1 || port > 65535) {
154 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
155 goto fail;
156 }
157
158 if (end < 1 || end > 65535) {
159 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
160 goto fail;
161 }
162
163 for (; port <= end; port++) {
164 l = (struct listener *)calloc(1, sizeof(struct listener));
165 l->next = tail;
166 tail = l;
167
168 l->fd = -1;
169 l->addr = ss;
170 if (ss.ss_family == AF_INET6)
171 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
172 else
173 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
174
175 } /* end for(port) */
176 } /* end while(next) */
177 free(dupstr);
178 return tail;
179 fail:
180 free(dupstr);
181 return NULL;
182}
183
184
185/*
186 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
187 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200188int cfg_parse_global(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189{
190
191 if (!strcmp(args[0], "global")) { /* new section */
192 /* no option, nothing special to do */
193 return 0;
194 }
195 else if (!strcmp(args[0], "daemon")) {
196 global.mode |= MODE_DAEMON;
197 }
198 else if (!strcmp(args[0], "debug")) {
199 global.mode |= MODE_DEBUG;
200 }
201 else if (!strcmp(args[0], "noepoll")) {
202 cfg_polling_mechanism &= ~POLL_USE_EPOLL;
203 }
204 else if (!strcmp(args[0], "nopoll")) {
205 cfg_polling_mechanism &= ~POLL_USE_POLL;
206 }
207 else if (!strcmp(args[0], "quiet")) {
208 global.mode |= MODE_QUIET;
209 }
210 else if (!strcmp(args[0], "stats")) {
211 global.mode |= MODE_STATS;
212 }
213 else if (!strcmp(args[0], "uid")) {
214 if (global.uid != 0) {
215 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
216 return 0;
217 }
218 if (*(args[1]) == 0) {
219 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
220 return -1;
221 }
222 global.uid = atol(args[1]);
223 }
224 else if (!strcmp(args[0], "gid")) {
225 if (global.gid != 0) {
226 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
227 return 0;
228 }
229 if (*(args[1]) == 0) {
230 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
231 return -1;
232 }
233 global.gid = atol(args[1]);
234 }
235 else if (!strcmp(args[0], "nbproc")) {
236 if (global.nbproc != 0) {
237 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
238 return 0;
239 }
240 if (*(args[1]) == 0) {
241 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
242 return -1;
243 }
244 global.nbproc = atol(args[1]);
245 }
246 else if (!strcmp(args[0], "maxconn")) {
247 if (global.maxconn != 0) {
248 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
249 return 0;
250 }
251 if (*(args[1]) == 0) {
252 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
253 return -1;
254 }
255 global.maxconn = atol(args[1]);
256#ifdef SYSTEM_MAXCONN
257 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
258 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);
259 global.maxconn = DEFAULT_MAXCONN;
260 }
261#endif /* SYSTEM_MAXCONN */
262 }
263 else if (!strcmp(args[0], "ulimit-n")) {
264 if (global.rlimit_nofile != 0) {
265 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
266 return 0;
267 }
268 if (*(args[1]) == 0) {
269 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
270 return -1;
271 }
272 global.rlimit_nofile = atol(args[1]);
273 }
274 else if (!strcmp(args[0], "chroot")) {
275 if (global.chroot != NULL) {
276 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
277 return 0;
278 }
279 if (*(args[1]) == 0) {
280 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
281 return -1;
282 }
283 global.chroot = strdup(args[1]);
284 }
285 else if (!strcmp(args[0], "pidfile")) {
286 if (global.pidfile != NULL) {
287 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
288 return 0;
289 }
290 if (*(args[1]) == 0) {
291 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
292 return -1;
293 }
294 global.pidfile = strdup(args[1]);
295 }
296 else if (!strcmp(args[0], "log")) { /* syslog server address */
297 struct sockaddr_in *sa;
298 int facility, level;
299
300 if (*(args[1]) == 0 || *(args[2]) == 0) {
301 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
302 return -1;
303 }
304
305 facility = get_log_facility(args[2]);
306 if (facility < 0) {
307 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
308 exit(1);
309 }
310
311 level = 7; /* max syslog level = debug */
312 if (*(args[3])) {
313 level = get_log_level(args[3]);
314 if (level < 0) {
315 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
316 exit(1);
317 }
318 }
319
320 sa = str2sa(args[1]);
321 if (!sa->sin_port)
322 sa->sin_port = htons(SYSLOG_PORT);
323
324 if (global.logfac1 == -1) {
325 global.logsrv1 = *sa;
326 global.logfac1 = facility;
327 global.loglev1 = level;
328 }
329 else if (global.logfac2 == -1) {
330 global.logsrv2 = *sa;
331 global.logfac2 = facility;
332 global.loglev2 = level;
333 }
334 else {
335 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
336 return -1;
337 }
338
339 }
340 else {
341 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
342 return -1;
343 }
344 return 0;
345}
346
347
348static void init_default_instance()
349{
350 memset(&defproxy, 0, sizeof(defproxy));
351 defproxy.mode = PR_MODE_TCP;
352 defproxy.state = PR_STNEW;
353 defproxy.maxconn = cfg_maxpconn;
354 defproxy.conn_retries = CONN_RETRIES;
355 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
356}
357
358/*
359 * parse a line in a <listen> section. Returns 0 if OK, -1 if error.
360 */
Willy Tarreaub17916e2006-10-15 15:17:57 +0200361int cfg_parse_listen(const char *file, int linenum, char **args)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200362{
363 static struct proxy *curproxy = NULL;
364 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200365 const char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200366 int rc;
367
368 if (!strcmp(args[0], "listen")) { /* new proxy */
369 if (!*args[1]) {
370 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
371 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
372 file, linenum, args[0]);
373 return -1;
374 }
375
376 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
377 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
378 return -1;
379 }
380
381 curproxy->next = proxy;
382 proxy = curproxy;
383 LIST_INIT(&curproxy->pendconns);
384
385 curproxy->id = strdup(args[1]);
386
387 /* parse the listener address if any */
388 if (*args[2]) {
389 curproxy->listen = str2listener(args[2], curproxy->listen);
390 if (!curproxy->listen)
391 return -1;
392 global.maxsock++;
393 }
394
395 /* set default values */
396 curproxy->state = defproxy.state;
397 curproxy->maxconn = defproxy.maxconn;
398 curproxy->conn_retries = defproxy.conn_retries;
399 curproxy->options = defproxy.options;
400
401 if (defproxy.check_req)
402 curproxy->check_req = strdup(defproxy.check_req);
403 curproxy->check_len = defproxy.check_len;
404
405 if (defproxy.cookie_name)
406 curproxy->cookie_name = strdup(defproxy.cookie_name);
407 curproxy->cookie_len = defproxy.cookie_len;
408
409 if (defproxy.capture_name)
410 curproxy->capture_name = strdup(defproxy.capture_name);
411 curproxy->capture_namelen = defproxy.capture_namelen;
412 curproxy->capture_len = defproxy.capture_len;
413
Willy Tarreaubaaee002006-06-26 02:48:02 +0200414
Willy Tarreau0f772532006-12-23 20:51:41 +0100415 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
416 if (defproxy.errmsg[rc].str)
417 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200419
420 curproxy->clitimeout = defproxy.clitimeout;
421 curproxy->contimeout = defproxy.contimeout;
422 curproxy->srvtimeout = defproxy.srvtimeout;
423 curproxy->mode = defproxy.mode;
424 curproxy->logfac1 = defproxy.logfac1;
425 curproxy->logsrv1 = defproxy.logsrv1;
426 curproxy->loglev1 = defproxy.loglev1;
427 curproxy->logfac2 = defproxy.logfac2;
428 curproxy->logsrv2 = defproxy.logsrv2;
429 curproxy->loglev2 = defproxy.loglev2;
430 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
431 curproxy->grace = defproxy.grace;
432 curproxy->uri_auth = defproxy.uri_auth;
433 curproxy->source_addr = defproxy.source_addr;
434 curproxy->mon_net = defproxy.mon_net;
435 curproxy->mon_mask = defproxy.mon_mask;
Willy Tarreau1c47f852006-07-09 08:22:27 +0200436
437 if (defproxy.monitor_uri)
438 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
439 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
440
Willy Tarreaubaaee002006-06-26 02:48:02 +0200441 return 0;
442 }
443 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
444 /* some variables may have already been initialized earlier */
445 if (defproxy.check_req) free(defproxy.check_req);
446 if (defproxy.cookie_name) free(defproxy.cookie_name);
447 if (defproxy.capture_name) free(defproxy.capture_name);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200448 if (defproxy.monitor_uri) free(defproxy.monitor_uri);
Willy Tarreau0f772532006-12-23 20:51:41 +0100449
450 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
451 if (defproxy.errmsg[rc].len)
452 free(defproxy.errmsg[rc].str);
453 }
454
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455 /* we cannot free uri_auth because it might already be used */
456 init_default_instance();
457 curproxy = &defproxy;
458 return 0;
459 }
460 else if (curproxy == NULL) {
461 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
462 return -1;
463 }
464
465 if (!strcmp(args[0], "bind")) { /* new listen addresses */
466 if (curproxy == &defproxy) {
467 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
468 return -1;
469 }
470
471 if (strchr(args[1], ':') == NULL) {
472 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
473 file, linenum, args[0]);
474 return -1;
475 }
476 curproxy->listen = str2listener(args[1], curproxy->listen);
477 if (!curproxy->listen)
478 return -1;
479 global.maxsock++;
480 return 0;
481 }
482 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
483 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
484 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
485 file, linenum, args[0]);
486 return -1;
487 }
488 /* flush useless bits */
489 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
490 return 0;
491 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200492 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
493 if (!*args[1]) {
494 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
495 file, linenum, args[0]);
496 return -1;
497 }
498
499 if (curproxy->monitor_uri != NULL)
500 free(curproxy->monitor_uri);
501
502 curproxy->monitor_uri_len = strlen(args[1]) + 2; /* include leading and trailing spaces */
503 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
504 memcpy(curproxy->monitor_uri + 1, args[1], curproxy->monitor_uri_len - 2);
505 curproxy->monitor_uri[curproxy->monitor_uri_len-1] = curproxy->monitor_uri[0] = ' ';
506 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
507
508 return 0;
509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200510 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
511 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
512 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
513 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
514 else {
515 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
516 return -1;
517 }
518 }
519 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
520 curproxy->state = PR_STSTOPPED;
521 }
522 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
523 curproxy->state = PR_STNEW;
524 }
525 else if (!strcmp(args[0], "cookie")) { /* cookie name */
526 int cur_arg;
527 // if (curproxy == &defproxy) {
528 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
529 // return -1;
530 // }
531
532 if (curproxy->cookie_name != NULL) {
533 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
534 // file, linenum);
535 // return 0;
536 free(curproxy->cookie_name);
537 }
538
539 if (*(args[1]) == 0) {
540 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
541 file, linenum, args[0]);
542 return -1;
543 }
544 curproxy->cookie_name = strdup(args[1]);
545 curproxy->cookie_len = strlen(curproxy->cookie_name);
546
547 cur_arg = 2;
548 while (*(args[cur_arg])) {
549 if (!strcmp(args[cur_arg], "rewrite")) {
550 curproxy->options |= PR_O_COOK_RW;
551 }
552 else if (!strcmp(args[cur_arg], "indirect")) {
553 curproxy->options |= PR_O_COOK_IND;
554 }
555 else if (!strcmp(args[cur_arg], "insert")) {
556 curproxy->options |= PR_O_COOK_INS;
557 }
558 else if (!strcmp(args[cur_arg], "nocache")) {
559 curproxy->options |= PR_O_COOK_NOC;
560 }
561 else if (!strcmp(args[cur_arg], "postonly")) {
562 curproxy->options |= PR_O_COOK_POST;
563 }
564 else if (!strcmp(args[cur_arg], "prefix")) {
565 curproxy->options |= PR_O_COOK_PFX;
566 }
567 else {
568 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly' options.\n",
569 file, linenum, args[0]);
570 return -1;
571 }
572 cur_arg++;
573 }
574 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
575 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
576 file, linenum);
577 return -1;
578 }
579
580 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
581 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
582 file, linenum);
583 return -1;
584 }
585 }/* end else if (!strcmp(args[0], "cookie")) */
586 else if (!strcmp(args[0], "appsession")) { /* cookie name */
587 // if (curproxy == &defproxy) {
588 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
589 // return -1;
590 // }
591
592 if (curproxy->appsession_name != NULL) {
593 // Alert("parsing [%s:%d] : cookie name already specified. Continuing.\n",
594 // file, linenum);
595 // return 0;
596 free(curproxy->appsession_name);
597 }
598
599 if (*(args[5]) == 0) {
600 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
601 file, linenum, args[0]);
602 return -1;
603 }
604 have_appsession = 1;
605 curproxy->appsession_name = strdup(args[1]);
606 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
607 curproxy->appsession_len = atoi(args[3]);
608 curproxy->appsession_timeout = atoi(args[5]);
609 rc = chtbl_init(&(curproxy->htbl_proxy), TBLSIZ, hashpjw, match_str, destroy);
610 if (rc) {
611 Alert("Error Init Appsession Hashtable.\n");
612 return -1;
613 }
614 } /* Url App Session */
615 else if (!strcmp(args[0], "capture")) {
616 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
617 // if (curproxy == &defproxy) {
618 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
619 // return -1;
620 // }
621
622 if (curproxy->capture_name != NULL) {
623 // Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
624 // file, linenum, args[0]);
625 // return 0;
626 free(curproxy->capture_name);
627 }
628
629 if (*(args[4]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
631 file, linenum, args[0]);
632 return -1;
633 }
634 curproxy->capture_name = strdup(args[2]);
635 curproxy->capture_namelen = strlen(curproxy->capture_name);
636 curproxy->capture_len = atol(args[4]);
637 if (curproxy->capture_len >= CAPTURE_LEN) {
638 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
639 file, linenum, CAPTURE_LEN - 1);
640 curproxy->capture_len = CAPTURE_LEN - 1;
641 }
642 curproxy->to_log |= LW_COOKIE;
643 }
644 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
645 struct cap_hdr *hdr;
646
647 if (curproxy == &defproxy) {
648 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
649 return -1;
650 }
651
652 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
653 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
654 file, linenum, args[0], args[1]);
655 return -1;
656 }
657
658 hdr = calloc(sizeof(struct cap_hdr), 1);
659 hdr->next = curproxy->req_cap;
660 hdr->name = strdup(args[3]);
661 hdr->namelen = strlen(args[3]);
662 hdr->len = atol(args[5]);
663 hdr->index = curproxy->nb_req_cap++;
664 curproxy->req_cap = hdr;
665 curproxy->to_log |= LW_REQHDR;
666 }
667 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
668 struct cap_hdr *hdr;
669
670 if (curproxy == &defproxy) {
671 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
672 return -1;
673 }
674
675 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
676 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
677 file, linenum, args[0], args[1]);
678 return -1;
679 }
680 hdr = calloc(sizeof(struct cap_hdr), 1);
681 hdr->next = curproxy->rsp_cap;
682 hdr->name = strdup(args[3]);
683 hdr->namelen = strlen(args[3]);
684 hdr->len = atol(args[5]);
685 hdr->index = curproxy->nb_rsp_cap++;
686 curproxy->rsp_cap = hdr;
687 curproxy->to_log |= LW_RSPHDR;
688 }
689 else {
690 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
691 file, linenum, args[0]);
692 return -1;
693 }
694 }
695 else if (!strcmp(args[0], "contimeout")) { /* connect timeout */
696 if (curproxy->contimeout != defproxy.contimeout) {
697 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
698 return 0;
699 }
700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
702 file, linenum, args[0]);
703 return -1;
704 }
705 curproxy->contimeout = atol(args[1]);
706 }
707 else if (!strcmp(args[0], "clitimeout")) { /* client timeout */
708 if (curproxy->clitimeout != defproxy.clitimeout) {
709 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n",
710 file, linenum, args[0]);
711 return 0;
712 }
713 if (*(args[1]) == 0) {
714 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
715 file, linenum, args[0]);
716 return -1;
717 }
718 curproxy->clitimeout = atol(args[1]);
719 }
720 else if (!strcmp(args[0], "srvtimeout")) { /* server timeout */
721 if (curproxy->srvtimeout != defproxy.srvtimeout) {
722 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
723 return 0;
724 }
725 if (*(args[1]) == 0) {
726 Alert("parsing [%s:%d] : '%s' expects an integer <time_in_ms> as argument.\n",
727 file, linenum, args[0]);
728 return -1;
729 }
730 curproxy->srvtimeout = atol(args[1]);
731 }
732 else if (!strcmp(args[0], "retries")) { /* connection retries */
733 if (*(args[1]) == 0) {
734 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
735 file, linenum, args[0]);
736 return -1;
737 }
738 curproxy->conn_retries = atol(args[1]);
739 }
740 else if (!strcmp(args[0], "stats")) {
741 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
742 curproxy->uri_auth = NULL; /* we must detach from the default config */
743
744 if (*(args[1]) == 0) {
745 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
746 return -1;
747 } else if (!strcmp(args[1], "uri")) {
748 if (*(args[2]) == 0) {
749 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
750 return -1;
751 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
752 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
753 return -1;
754 }
755 } else if (!strcmp(args[1], "realm")) {
756 if (*(args[2]) == 0) {
757 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
758 return -1;
759 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
760 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
761 return -1;
762 }
763 } else if (!strcmp(args[1], "auth")) {
764 if (*(args[2]) == 0) {
765 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
766 return -1;
767 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
768 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
769 return -1;
770 }
771 } else if (!strcmp(args[1], "scope")) {
772 if (*(args[2]) == 0) {
773 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
774 return -1;
775 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
776 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
777 return -1;
778 }
779 } else if (!strcmp(args[1], "enable")) {
780 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
781 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
782 return -1;
783 }
784 } else {
785 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'uri', 'realm', 'auth' or 'enable').\n",
786 file, linenum, args[0]);
787 return -1;
788 }
789 }
790 else if (!strcmp(args[0], "option")) {
791 if (*(args[1]) == 0) {
792 Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]);
793 return -1;
794 }
795 if (!strcmp(args[1], "redispatch"))
796 /* enable reconnections to dispatch */
797 curproxy->options |= PR_O_REDISP;
798#ifdef TPROXY
799 else if (!strcmp(args[1], "transparent"))
800 /* enable transparent proxy connections */
801 curproxy->options |= PR_O_TRANSP;
802#endif
803 else if (!strcmp(args[1], "keepalive"))
804 /* enable keep-alive */
805 curproxy->options |= PR_O_KEEPALIVE;
806 else if (!strcmp(args[1], "forwardfor"))
807 /* insert x-forwarded-for field */
808 curproxy->options |= PR_O_FWDFOR;
809 else if (!strcmp(args[1], "logasap"))
810 /* log as soon as possible, without waiting for the session to complete */
811 curproxy->options |= PR_O_LOGASAP;
812 else if (!strcmp(args[1], "abortonclose"))
813 /* abort connection if client closes during queue or connect() */
814 curproxy->options |= PR_O_ABRT_CLOSE;
815 else if (!strcmp(args[1], "httpclose"))
816 /* force connection: close in both directions in HTTP mode */
817 curproxy->options |= PR_O_HTTP_CLOSE;
818 else if (!strcmp(args[1], "forceclose"))
819 /* force connection: close in both directions in HTTP mode and enforce end of session */
820 curproxy->options |= PR_O_FORCE_CLO | PR_O_HTTP_CLOSE;
821 else if (!strcmp(args[1], "checkcache"))
822 /* require examination of cacheability of the 'set-cookie' field */
823 curproxy->options |= PR_O_CHK_CACHE;
824 else if (!strcmp(args[1], "httplog"))
825 /* generate a complete HTTP log */
826 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
827 else if (!strcmp(args[1], "tcplog"))
828 /* generate a detailed TCP log */
829 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
830 else if (!strcmp(args[1], "dontlognull")) {
831 /* don't log empty requests */
832 curproxy->options |= PR_O_NULLNOLOG;
833 }
834 else if (!strcmp(args[1], "tcpka")) {
835 /* enable TCP keep-alives on client and server sessions */
836 curproxy->options |= PR_O_TCP_CLI_KA | PR_O_TCP_SRV_KA;
837 }
838 else if (!strcmp(args[1], "clitcpka")) {
839 /* enable TCP keep-alives on client sessions */
840 curproxy->options |= PR_O_TCP_CLI_KA;
841 }
842 else if (!strcmp(args[1], "srvtcpka")) {
843 /* enable TCP keep-alives on server sessions */
844 curproxy->options |= PR_O_TCP_SRV_KA;
845 }
846 else if (!strcmp(args[1], "allbackups")) {
847 /* Use all backup servers simultaneously */
848 curproxy->options |= PR_O_USE_ALL_BK;
849 }
850 else if (!strcmp(args[1], "httpchk")) {
851 /* use HTTP request to check servers' health */
852 if (curproxy->check_req != NULL) {
853 free(curproxy->check_req);
854 }
855 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +0200856 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200857 if (!*args[2]) { /* no argument */
858 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
859 curproxy->check_len = strlen(DEF_CHECK_REQ);
860 } else if (!*args[3]) { /* one argument : URI */
861 int reqlen = strlen(args[2]) + strlen("OPTIONS / HTTP/1.0\r\n\r\n");
862 curproxy->check_req = (char *)malloc(reqlen);
863 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
864 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
865 } else { /* more arguments : METHOD URI [HTTP_VER] */
866 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
867 if (*args[4])
868 reqlen += strlen(args[4]);
869 else
870 reqlen += strlen("HTTP/1.0");
871
872 curproxy->check_req = (char *)malloc(reqlen);
873 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
874 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
875 }
Willy Tarreauf3c69202006-07-09 16:42:34 +0200876 }
877 else if (!strcmp(args[1], "ssl-hello-chk")) {
878 /* use SSLv3 CLIENT HELLO to check servers' health */
879 if (curproxy->check_req != NULL) {
880 free(curproxy->check_req);
881 }
882 curproxy->options &= ~PR_O_HTTP_CHK;
883 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884 }
885 else if (!strcmp(args[1], "persist")) {
886 /* persist on using the server specified by the cookie, even when it's down */
887 curproxy->options |= PR_O_PERSIST;
888 }
889 else {
890 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
891 return -1;
892 }
893 return 0;
894 }
895 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
896 /* enable reconnections to dispatch */
897 curproxy->options |= PR_O_REDISP;
898 }
899#ifdef TPROXY
900 else if (!strcmp(args[0], "transparent")) {
901 /* enable transparent proxy connections */
902 curproxy->options |= PR_O_TRANSP;
903 }
904#endif
905 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
906 if (*(args[1]) == 0) {
907 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
908 return -1;
909 }
910 curproxy->maxconn = atol(args[1]);
911 }
912 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
913 if (*(args[1]) == 0) {
914 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
915 return -1;
916 }
917 curproxy->grace = atol(args[1]);
918 }
919 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
920 if (curproxy == &defproxy) {
921 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
922 return -1;
923 }
924 if (strchr(args[1], ':') == NULL) {
925 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
926 return -1;
927 }
928 curproxy->dispatch_addr = *str2sa(args[1]);
929 }
930 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
931 if (*(args[1])) {
932 if (!strcmp(args[1], "roundrobin")) {
933 curproxy->options |= PR_O_BALANCE_RR;
934 }
935 else if (!strcmp(args[1], "source")) {
936 curproxy->options |= PR_O_BALANCE_SH;
937 }
938 else {
939 Alert("parsing [%s:%d] : '%s' only supports 'roundrobin' and 'source' options.\n", file, linenum, args[0]);
940 return -1;
941 }
942 }
943 else /* if no option is set, use round-robin by default */
944 curproxy->options |= PR_O_BALANCE_RR;
945 }
946 else if (!strcmp(args[0], "server")) { /* server address */
947 int cur_arg;
948 char *rport;
949 char *raddr;
950 short realport;
951 int do_check;
952
953 if (curproxy == &defproxy) {
954 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
955 return -1;
956 }
957
958 if (!*args[2]) {
959 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
960 file, linenum, args[0]);
961 return -1;
962 }
963 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
964 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
965 return -1;
966 }
967
968 /* the servers are linked backwards first */
969 newsrv->next = curproxy->srv;
970 curproxy->srv = newsrv;
971 newsrv->proxy = curproxy;
972
973 LIST_INIT(&newsrv->pendconns);
974 do_check = 0;
975 newsrv->state = SRV_RUNNING; /* early server setup */
976 newsrv->id = strdup(args[1]);
977
978 /* several ways to check the port component :
979 * - IP => port=+0, relative
980 * - IP: => port=+0, relative
981 * - IP:N => port=N, absolute
982 * - IP:+N => port=+N, relative
983 * - IP:-N => port=-N, relative
984 */
985 raddr = strdup(args[2]);
986 rport = strchr(raddr, ':');
987 if (rport) {
988 *rport++ = 0;
989 realport = atol(rport);
990 if (!isdigit((int)*rport))
991 newsrv->state |= SRV_MAPPORTS;
992 } else {
993 realport = 0;
994 newsrv->state |= SRV_MAPPORTS;
995 }
996
997 newsrv->addr = *str2sa(raddr);
998 newsrv->addr.sin_port = htons(realport);
999 free(raddr);
1000
1001 newsrv->curfd = -1; /* no health-check in progress */
1002 newsrv->inter = DEF_CHKINTR;
1003 newsrv->rise = DEF_RISETIME;
1004 newsrv->fall = DEF_FALLTIME;
1005 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
1006 cur_arg = 3;
1007 while (*args[cur_arg]) {
1008 if (!strcmp(args[cur_arg], "cookie")) {
1009 newsrv->cookie = strdup(args[cur_arg + 1]);
1010 newsrv->cklen = strlen(args[cur_arg + 1]);
1011 cur_arg += 2;
1012 }
1013 else if (!strcmp(args[cur_arg], "rise")) {
1014 newsrv->rise = atol(args[cur_arg + 1]);
1015 newsrv->health = newsrv->rise;
1016 cur_arg += 2;
1017 }
1018 else if (!strcmp(args[cur_arg], "fall")) {
1019 newsrv->fall = atol(args[cur_arg + 1]);
1020 cur_arg += 2;
1021 }
1022 else if (!strcmp(args[cur_arg], "inter")) {
1023 newsrv->inter = atol(args[cur_arg + 1]);
1024 cur_arg += 2;
1025 }
1026 else if (!strcmp(args[cur_arg], "port")) {
1027 newsrv->check_port = atol(args[cur_arg + 1]);
1028 cur_arg += 2;
1029 }
1030 else if (!strcmp(args[cur_arg], "backup")) {
1031 newsrv->state |= SRV_BACKUP;
1032 cur_arg ++;
1033 }
1034 else if (!strcmp(args[cur_arg], "weight")) {
1035 int w;
1036 w = atol(args[cur_arg + 1]);
1037 if (w < 1 || w > 256) {
1038 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
1039 file, linenum, newsrv->id, w);
1040 return -1;
1041 }
1042 newsrv->uweight = w - 1;
1043 cur_arg += 2;
1044 }
1045 else if (!strcmp(args[cur_arg], "minconn")) {
1046 newsrv->minconn = atol(args[cur_arg + 1]);
1047 cur_arg += 2;
1048 }
1049 else if (!strcmp(args[cur_arg], "maxconn")) {
1050 newsrv->maxconn = atol(args[cur_arg + 1]);
1051 cur_arg += 2;
1052 }
1053 else if (!strcmp(args[cur_arg], "check")) {
1054 global.maxsock++;
1055 do_check = 1;
1056 cur_arg += 1;
1057 }
1058 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
1059 if (!*args[cur_arg + 1]) {
1060 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1061 file, linenum, "source");
1062 return -1;
1063 }
1064 newsrv->state |= SRV_BIND_SRC;
1065 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
1066 cur_arg += 2;
Willy Tarreau77074d52006-11-12 23:57:19 +01001067#ifdef CONFIG_HAP_CTTPROXY
1068 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
1069 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
1070 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1071 file, linenum, "usesrc");
1072 return -1;
1073 }
1074 if (!*args[cur_arg + 1]) {
1075 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1076 file, linenum, "usesrc");
1077 return -1;
1078 }
1079 if (!strcmp(args[cur_arg + 1], "client")) {
1080 newsrv->state |= SRV_TPROXY_CLI;
1081 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
1082 newsrv->state |= SRV_TPROXY_CIP;
1083 } else {
1084 newsrv->state |= SRV_TPROXY_ADDR;
1085 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
1086 }
1087 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1088 cur_arg += 2;
1089 }
1090#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 }
1092 else {
1093 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'port', 'source', 'minconn', 'maxconn' and 'weight'.\n",
1094 file, linenum, newsrv->id);
1095 return -1;
1096 }
1097 }
1098
1099 if (do_check) {
1100 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
1101 newsrv->check_port = realport; /* by default */
1102 if (!newsrv->check_port) {
1103 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
1104 file, linenum, newsrv->id);
1105 return -1;
1106 }
1107 newsrv->state |= SRV_CHECKED;
1108 }
1109
1110 if (newsrv->state & SRV_BACKUP)
1111 curproxy->srv_bck++;
1112 else
1113 curproxy->srv_act++;
1114 }
1115 else if (!strcmp(args[0], "log")) { /* syslog server address */
1116 struct sockaddr_in *sa;
1117 int facility;
1118
1119 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
1120 curproxy->logfac1 = global.logfac1;
1121 curproxy->logsrv1 = global.logsrv1;
1122 curproxy->loglev1 = global.loglev1;
1123 curproxy->logfac2 = global.logfac2;
1124 curproxy->logsrv2 = global.logsrv2;
1125 curproxy->loglev2 = global.loglev2;
1126 }
1127 else if (*(args[1]) && *(args[2])) {
1128 int level;
1129
1130 facility = get_log_facility(args[2]);
1131 if (facility < 0) {
1132 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
1133 exit(1);
1134 }
1135
1136 level = 7; /* max syslog level = debug */
1137 if (*(args[3])) {
1138 level = get_log_level(args[3]);
1139 if (level < 0) {
1140 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
1141 exit(1);
1142 }
1143 }
1144
1145 sa = str2sa(args[1]);
1146 if (!sa->sin_port)
1147 sa->sin_port = htons(SYSLOG_PORT);
1148
1149 if (curproxy->logfac1 == -1) {
1150 curproxy->logsrv1 = *sa;
1151 curproxy->logfac1 = facility;
1152 curproxy->loglev1 = level;
1153 }
1154 else if (curproxy->logfac2 == -1) {
1155 curproxy->logsrv2 = *sa;
1156 curproxy->logfac2 = facility;
1157 curproxy->loglev2 = level;
1158 }
1159 else {
1160 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
1161 return -1;
1162 }
1163 }
1164 else {
1165 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
1166 file, linenum);
1167 return -1;
1168 }
1169 }
1170 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
1171 if (!*args[1]) {
1172 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
1173 file, linenum, "source");
1174 return -1;
1175 }
1176
1177 curproxy->source_addr = *str2sa(args[1]);
1178 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreau77074d52006-11-12 23:57:19 +01001179#ifdef CONFIG_HAP_CTTPROXY
1180 if (!strcmp(args[2], "usesrc")) { /* address to use outside */
1181 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
1182 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
1183 file, linenum, "usesrc");
1184 return -1;
1185 }
1186 if (!*args[3]) {
1187 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
1188 file, linenum, "usesrc");
1189 return -1;
1190 }
1191
1192 if (!strcmp(args[3], "client")) {
1193 curproxy->options |= PR_O_TPXY_CLI;
1194 } else if (!strcmp(args[3], "clientip")) {
1195 curproxy->options |= PR_O_TPXY_CIP;
1196 } else {
1197 curproxy->options |= PR_O_TPXY_ADDR;
1198 curproxy->tproxy_addr = *str2sa(args[3]);
1199 }
1200 global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
1201 }
1202#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 }
1204 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
1205 regex_t *preg;
1206 if (curproxy == &defproxy) {
1207 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1208 return -1;
1209 }
1210
1211 if (*(args[1]) == 0 || *(args[2]) == 0) {
1212 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1213 file, linenum, args[0]);
1214 return -1;
1215 }
1216
1217 preg = calloc(1, sizeof(regex_t));
1218 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1219 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1220 return -1;
1221 }
1222
1223 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1224 if (err) {
1225 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1226 file, linenum, *err);
1227 return -1;
1228 }
1229 }
1230 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
1231 regex_t *preg;
1232 if (curproxy == &defproxy) {
1233 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1234 return -1;
1235 }
1236
1237 if (*(args[1]) == 0) {
1238 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1239 return -1;
1240 }
1241
1242 preg = calloc(1, sizeof(regex_t));
1243 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1244 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1245 return -1;
1246 }
1247
1248 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1249 }
1250 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
1251 regex_t *preg;
1252 if (curproxy == &defproxy) {
1253 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1254 return -1;
1255 }
1256
1257 if (*(args[1]) == 0) {
1258 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1259 return -1;
1260 }
1261
1262 preg = calloc(1, sizeof(regex_t));
1263 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1264 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1265 return -1;
1266 }
1267
1268 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1269 }
1270 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
1271 regex_t *preg;
1272 if (curproxy == &defproxy) {
1273 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1274 return -1;
1275 }
1276
1277 if (*(args[1]) == 0) {
1278 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1279 return -1;
1280 }
1281
1282 preg = calloc(1, sizeof(regex_t));
1283 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1284 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1285 return -1;
1286 }
1287
1288 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1289 }
1290 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
1291 regex_t *preg;
1292 if (curproxy == &defproxy) {
1293 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1294 return -1;
1295 }
1296
1297 if (*(args[1]) == 0) {
1298 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1299 return -1;
1300 }
1301
1302 preg = calloc(1, sizeof(regex_t));
1303 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1304 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1305 return -1;
1306 }
1307
1308 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1309 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001310 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
1311 regex_t *preg;
1312 if (curproxy == &defproxy) {
1313 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1314 return -1;
1315 }
1316
1317 if (*(args[1]) == 0) {
1318 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1319 return -1;
1320 }
1321
1322 preg = calloc(1, sizeof(regex_t));
1323 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1324 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1325 return -1;
1326 }
1327
1328 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1329 }
Willy Tarreaua496b602006-12-17 23:15:24 +01001330 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
1331 regex_t *preg;
1332 if(curproxy == &defproxy) {
1333 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1334 return -1;
1335 }
1336
1337 if(*(args[1]) == 0 || *(args[2]) == 0) {
1338 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1339 file, linenum, args[0]);
1340 return -1;
1341 }
1342
1343 preg = calloc(1, sizeof(regex_t));
1344 if(regcomp(preg, args[1], REG_EXTENDED) != 0) {
1345 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1346 }
1347
1348 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1349 }
1350 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
1351 regex_t *preg;
1352 if(curproxy == &defproxy) {
1353 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1354 return -1;
1355 }
1356
1357 if(*(args[1]) == 0 || *(args[2]) == 0) {
1358 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
1359 file, linenum, args[0]);
1360 return -1;
1361 }
1362
1363 preg = calloc(1, sizeof(regex_t));
1364 if(regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1365 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1366 }
1367
1368 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
1369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
1371 regex_t *preg;
1372 if (curproxy == &defproxy) {
1373 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1374 return -1;
1375 }
1376
1377 if (*(args[1]) == 0 || *(args[2]) == 0) {
1378 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1379 file, linenum, args[0]);
1380 return -1;
1381 }
1382
1383 preg = calloc(1, sizeof(regex_t));
1384 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1385 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1386 return -1;
1387 }
1388
1389 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
1390 if (err) {
1391 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1392 file, linenum, *err);
1393 return -1;
1394 }
1395 }
1396 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
1397 regex_t *preg;
1398 if (curproxy == &defproxy) {
1399 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1400 return -1;
1401 }
1402
1403 if (*(args[1]) == 0) {
1404 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1405 return -1;
1406 }
1407
1408 preg = calloc(1, sizeof(regex_t));
1409 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1410 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1411 return -1;
1412 }
1413
1414 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
1415 }
1416 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
1417 regex_t *preg;
1418 if (curproxy == &defproxy) {
1419 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1420 return -1;
1421 }
1422
1423 if (*(args[1]) == 0) {
1424 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1425 return -1;
1426 }
1427
1428 preg = calloc(1, sizeof(regex_t));
1429 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1430 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1431 return -1;
1432 }
1433
1434 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
1435 }
1436 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
1437 regex_t *preg;
1438 if (curproxy == &defproxy) {
1439 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1440 return -1;
1441 }
1442
1443 if (*(args[1]) == 0) {
1444 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1445 return -1;
1446 }
1447
1448 preg = calloc(1, sizeof(regex_t));
1449 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1450 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1451 return -1;
1452 }
1453
1454 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
1455 }
1456 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
1457 regex_t *preg;
1458 if (curproxy == &defproxy) {
1459 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1460 return -1;
1461 }
1462
1463 if (*(args[1]) == 0) {
1464 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1465 return -1;
1466 }
1467
1468 preg = calloc(1, sizeof(regex_t));
1469 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1470 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1471 return -1;
1472 }
1473
1474 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
1475 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02001476 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
1477 regex_t *preg;
1478 if (curproxy == &defproxy) {
1479 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1480 return -1;
1481 }
1482
1483 if (*(args[1]) == 0) {
1484 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
1485 return -1;
1486 }
1487
1488 preg = calloc(1, sizeof(regex_t));
1489 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1490 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1491 return -1;
1492 }
1493
1494 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
1495 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001496 else if (!strcmp(args[0], "reqadd")) { /* add request header */
1497 if (curproxy == &defproxy) {
1498 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1499 return -1;
1500 }
1501
1502 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
1503 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1504 return 0;
1505 }
1506
1507 if (*(args[1]) == 0) {
1508 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1509 return -1;
1510 }
1511
1512 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
1513 }
1514 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
1515 regex_t *preg;
1516
1517 if (*(args[1]) == 0 || *(args[2]) == 0) {
1518 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1519 file, linenum, args[0]);
1520 return -1;
1521 }
1522
1523 preg = calloc(1, sizeof(regex_t));
1524 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1525 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1526 return -1;
1527 }
1528
1529 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1530 if (err) {
1531 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1532 file, linenum, *err);
1533 return -1;
1534 }
1535 }
1536 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
1537 regex_t *preg;
1538 if (curproxy == &defproxy) {
1539 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1540 return -1;
1541 }
1542
1543 if (*(args[1]) == 0) {
1544 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1545 return -1;
1546 }
1547
1548 preg = calloc(1, sizeof(regex_t));
1549 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1550 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1551 return -1;
1552 }
1553
1554 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
1555 if (err) {
1556 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1557 file, linenum, *err);
1558 return -1;
1559 }
1560 }
1561 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
1562 regex_t *preg;
1563 if (curproxy == &defproxy) {
1564 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1565 return -1;
1566 }
1567
1568 if (*(args[1]) == 0) {
1569 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1570 return -1;
1571 }
1572
1573 preg = calloc(1, sizeof(regex_t));
1574 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
1575 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1576 return -1;
1577 }
1578
1579 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
1580 if (err) {
1581 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1582 file, linenum, *err);
1583 return -1;
1584 }
1585 }
1586 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
1587 regex_t *preg;
1588 if (curproxy == &defproxy) {
1589 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1590 return -1;
1591 }
1592
1593 if (*(args[1]) == 0 || *(args[2]) == 0) {
1594 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
1595 file, linenum, args[0]);
1596 return -1;
1597 }
1598
1599 preg = calloc(1, sizeof(regex_t));
1600 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1601 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1602 return -1;
1603 }
1604
1605 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
1606 if (err) {
1607 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1608 file, linenum, *err);
1609 return -1;
1610 }
1611 }
1612 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
1613 regex_t *preg;
1614 if (curproxy == &defproxy) {
1615 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1616 return -1;
1617 }
1618
1619 if (*(args[1]) == 0) {
1620 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1621 return -1;
1622 }
1623
1624 preg = calloc(1, sizeof(regex_t));
1625 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1626 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1627 return -1;
1628 }
1629
1630 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
1631 if (err) {
1632 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1633 file, linenum, *err);
1634 return -1;
1635 }
1636 }
1637 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
1638 regex_t *preg;
1639 if (curproxy == &defproxy) {
1640 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1641 return -1;
1642 }
1643
1644 if (*(args[1]) == 0) {
1645 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
1646 return -1;
1647 }
1648
1649 preg = calloc(1, sizeof(regex_t));
1650 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
1651 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
1652 return -1;
1653 }
1654
1655 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
1656 if (err) {
1657 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
1658 file, linenum, *err);
1659 return -1;
1660 }
1661 }
1662 else if (!strcmp(args[0], "rspadd")) { /* add response header */
1663 if (curproxy == &defproxy) {
1664 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1665 return -1;
1666 }
1667
1668 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
1669 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
1670 return 0;
1671 }
1672
1673 if (*(args[1]) == 0) {
1674 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
1675 return -1;
1676 }
1677
1678 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
1679 }
1680 else if (!strcmp(args[0], "errorloc") ||
1681 !strcmp(args[0], "errorloc302") ||
1682 !strcmp(args[0], "errorloc303")) { /* error location */
1683 int errnum, errlen;
1684 char *err;
1685
1686 // if (curproxy == &defproxy) {
1687 // Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1688 // return -1;
1689 // }
1690
1691 if (*(args[2]) == 0) {
Willy Tarreau0f772532006-12-23 20:51:41 +01001692 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001693 return -1;
1694 }
1695
1696 errnum = atol(args[1]);
1697 if (!strcmp(args[0], "errorloc303")) {
1698 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
1699 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
1700 } else {
1701 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
1702 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
1703 }
1704
Willy Tarreau0f772532006-12-23 20:51:41 +01001705 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
1706 if (http_err_codes[rc] == errnum) {
1707 if (curproxy->errmsg[rc].str)
1708 free(curproxy->errmsg[rc].str);
1709 curproxy->errmsg[rc].str = err;
1710 curproxy->errmsg[rc].len = errlen;
1711 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 }
Willy Tarreau0f772532006-12-23 20:51:41 +01001714
1715 if (rc >= HTTP_ERR_SIZE) {
1716 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
1717 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001718 free(err);
1719 }
1720 }
1721 else {
1722 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "listen");
1723 return -1;
1724 }
1725 return 0;
1726}
1727
1728
1729/*
1730 * This function reads and parses the configuration file given in the argument.
1731 * returns 0 if OK, -1 if error.
1732 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02001733int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001734{
1735 char thisline[256];
1736 char *line;
1737 FILE *f;
1738 int linenum = 0;
1739 char *end;
1740 char *args[MAX_LINE_ARGS];
1741 int arg;
1742 int cfgerr = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001743 int nbchk, mininter, rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001744 int confsect = CFG_NONE;
1745
1746 struct proxy *curproxy = NULL;
1747 struct server *newsrv = NULL;
1748
1749 if ((f=fopen(file,"r")) == NULL)
1750 return -1;
1751
1752 init_default_instance();
1753
1754 while (fgets(line = thisline, sizeof(thisline), f) != NULL) {
1755 linenum++;
1756
1757 end = line + strlen(line);
1758
1759 /* skip leading spaces */
1760 while (isspace((int)*line))
1761 line++;
1762
1763 arg = 0;
1764 args[arg] = line;
1765
1766 while (*line && arg < MAX_LINE_ARGS) {
1767 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
1768 * C equivalent value. Other combinations left unchanged (eg: \1).
1769 */
1770 if (*line == '\\') {
1771 int skip = 0;
1772 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
1773 *line = line[1];
1774 skip = 1;
1775 }
1776 else if (line[1] == 'r') {
1777 *line = '\r';
1778 skip = 1;
1779 }
1780 else if (line[1] == 'n') {
1781 *line = '\n';
1782 skip = 1;
1783 }
1784 else if (line[1] == 't') {
1785 *line = '\t';
1786 skip = 1;
1787 }
1788 else if (line[1] == 'x') {
1789 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
1790 unsigned char hex1, hex2;
1791 hex1 = toupper(line[2]) - '0';
1792 hex2 = toupper(line[3]) - '0';
1793 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
1794 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
1795 *line = (hex1<<4) + hex2;
1796 skip = 3;
1797 }
1798 else {
1799 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
1800 return -1;
1801 }
1802 }
1803 if (skip) {
1804 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
1805 end -= skip;
1806 }
1807 line++;
1808 }
1809 else if (*line == '#' || *line == '\n' || *line == '\r') {
1810 /* end of string, end of loop */
1811 *line = 0;
1812 break;
1813 }
1814 else if (isspace((int)*line)) {
1815 /* a non-escaped space is an argument separator */
1816 *line++ = 0;
1817 while (isspace((int)*line))
1818 line++;
1819 args[++arg] = line;
1820 }
1821 else {
1822 line++;
1823 }
1824 }
1825
1826 /* empty line */
1827 if (!**args)
1828 continue;
1829
1830 /* zero out remaining args */
1831 while (++arg < MAX_LINE_ARGS) {
1832 args[arg] = line;
1833 }
1834
1835 if (!strcmp(args[0], "listen") || !strcmp(args[0], "defaults")) /* new proxy */
1836 confsect = CFG_LISTEN;
1837 else if (!strcmp(args[0], "global")) /* global config */
1838 confsect = CFG_GLOBAL;
1839 /* else it's a section keyword */
1840
1841 switch (confsect) {
1842 case CFG_LISTEN:
1843 if (cfg_parse_listen(file, linenum, args) < 0)
1844 return -1;
1845 break;
1846 case CFG_GLOBAL:
1847 if (cfg_parse_global(file, linenum, args) < 0)
1848 return -1;
1849 break;
1850 default:
1851 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
1852 return -1;
1853 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001854 }
1855 fclose(f);
1856
1857 /*
1858 * Now, check for the integrity of all that we have collected.
1859 */
1860
1861 /* will be needed further to delay some tasks */
1862 tv_now(&now);
1863
1864 if ((curproxy = proxy) == NULL) {
1865 Alert("parsing %s : no <listen> line. Nothing to do !\n",
1866 file);
1867 return -1;
1868 }
1869
1870 while (curproxy != NULL) {
Willy Tarreau97a738f2006-12-17 18:02:30 +01001871 curproxy->fiprm = curproxy->beprm = curproxy;
1872
Willy Tarreaubaaee002006-06-26 02:48:02 +02001873 if (curproxy->state == PR_STSTOPPED) {
1874 curproxy = curproxy->next;
1875 continue;
1876 }
1877
1878 if (curproxy->listen == NULL) {
1879 Alert("parsing %s : listener %s has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n", file, curproxy->id);
1880 cfgerr++;
1881 }
1882 else if ((curproxy->mode != PR_MODE_HEALTH) &&
1883 !(curproxy->options & (PR_O_TRANSP | PR_O_BALANCE)) &&
1884 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
1885 Alert("parsing %s : listener %s has no dispatch address and is not in transparent or balance mode.\n",
1886 file, curproxy->id);
1887 cfgerr++;
1888 }
1889 else if ((curproxy->mode != PR_MODE_HEALTH) && (curproxy->options & PR_O_BALANCE)) {
1890 if (curproxy->options & PR_O_TRANSP) {
1891 Alert("parsing %s : listener %s cannot use both transparent and balance mode.\n",
1892 file, curproxy->id);
1893 cfgerr++;
1894 }
1895#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
1896 else if (curproxy->srv == NULL) {
1897 Alert("parsing %s : listener %s needs at least 1 server in balance mode.\n",
1898 file, curproxy->id);
1899 cfgerr++;
1900 }
1901#endif
1902 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
1903 Warning("parsing %s : dispatch address of listener %s will be ignored in balance mode.\n",
1904 file, curproxy->id);
1905 }
1906 }
1907 else if (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HEALTH) { /* TCP PROXY or HEALTH CHECK */
1908 if (curproxy->cookie_name != NULL) {
1909 Warning("parsing %s : cookie will be ignored for listener %s.\n",
1910 file, curproxy->id);
1911 }
1912 if ((newsrv = curproxy->srv) != NULL) {
1913 Warning("parsing %s : servers will be ignored for listener %s.\n",
1914 file, curproxy->id);
1915 }
1916 if (curproxy->rsp_exp != NULL) {
1917 Warning("parsing %s : server regular expressions will be ignored for listener %s.\n",
1918 file, curproxy->id);
1919 }
1920 if (curproxy->req_exp != NULL) {
1921 Warning("parsing %s : client regular expressions will be ignored for listener %s.\n",
1922 file, curproxy->id);
1923 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001924 if (curproxy->monitor_uri != NULL) {
1925 Warning("parsing %s : monitor-uri will be ignored for listener %s.\n",
1926 file, curproxy->id);
1927 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001928 }
1929 else if (curproxy->mode == PR_MODE_HTTP) { /* HTTP PROXY */
1930 if ((curproxy->cookie_name != NULL) && ((newsrv = curproxy->srv) == NULL)) {
1931 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
1932 file, curproxy->id);
1933 cfgerr++;
1934 }
1935 }
1936
Willy Tarreaua496b602006-12-17 23:15:24 +01001937 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
1938 /* map jump target for ACT_SETBE in req_rep chain */
1939 struct hdr_exp *exp;
1940 struct proxy *target;
1941 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
1942 if (exp->action != ACT_SETBE)
1943 continue;
1944 for (target = proxy; target != NULL; target = target->next) {
1945 if (strcmp(target->id, exp->replace) == 0)
1946 break;
1947 }
1948 if (target == NULL) {
1949 Alert("parsing %s : backend '%s' in HTTP proxy %s was not found !\n",
1950 file, exp->replace, curproxy->id);
1951 cfgerr++;
1952 } else if (target == curproxy) {
1953 Alert("parsing %s : loop detected for backend %s !\n", file, exp->replace);
1954 cfgerr++;
1955 } else {
1956 free((void *)exp->replace);
1957 exp->replace = (const char *)target;
1958 }
1959 }
1960 }
Willy Tarreau2738a142006-07-08 17:28:09 +02001961 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
1962 (!curproxy->clitimeout || !curproxy->contimeout || !curproxy->srvtimeout)) {
1963 Warning("parsing %s : missing timeouts for listener '%s'.\n"
1964 " | While not properly invalid, you will certainly encounter various problems\n"
1965 " | with such a configuration. To fix this, please ensure that all following\n"
1966 " | values are set to a non-zero value: clitimeout, contimeout, srvtimeout.\n",
1967 file, curproxy->id);
1968 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001969
1970 if (curproxy->options & PR_O_SSL3_CHK) {
1971 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
1972 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
1973 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
1974 }
1975
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976 /* first, we will invert the servers list order */
1977 newsrv = NULL;
1978 while (curproxy->srv) {
1979 struct server *next;
1980
1981 next = curproxy->srv->next;
1982 curproxy->srv->next = newsrv;
1983 newsrv = curproxy->srv;
1984 if (!next)
1985 break;
1986 curproxy->srv = next;
1987 }
1988
1989 /* now, newsrv == curproxy->srv */
1990 if (newsrv) {
1991 struct server *srv;
1992 int pgcd;
1993 int act, bck;
1994
1995 /* We will factor the weights to reduce the table,
1996 * using Euclide's largest common divisor algorithm
1997 */
1998 pgcd = newsrv->uweight + 1;
1999 for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
2000 int t, w;
2001
2002 w = srv->uweight + 1;
2003 while (w) {
2004 t = pgcd % w;
2005 pgcd = w;
2006 w = t;
2007 }
2008 }
2009
2010 act = bck = 0;
2011 for (srv = newsrv; srv; srv = srv->next) {
2012 srv->eweight = ((srv->uweight + 1) / pgcd) - 1;
2013 if (srv->state & SRV_BACKUP)
2014 bck += srv->eweight + 1;
2015 else
2016 act += srv->eweight + 1;
2017 }
2018
2019 /* this is the largest map we will ever need for this servers list */
2020 if (act < bck)
2021 act = bck;
2022
2023 curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
2024 /* recounts servers and their weights */
2025 recount_servers(curproxy);
2026 recalc_server_map(curproxy);
2027 }
2028
2029 if (curproxy->options & PR_O_LOGASAP)
2030 curproxy->to_log &= ~LW_BYTES;
2031
Willy Tarreau0f772532006-12-23 20:51:41 +01002032 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2033 if (!http_err_msgs[rc]) {
2034 Alert("Internal error: no message defined for HTTP return code %d. Aborting.\n");
2035 abort();
2036 }
2037 if (!curproxy->errmsg[rc].str) {
2038 curproxy->errmsg[rc].str = strdup(http_err_msgs[rc]);
2039 curproxy->errmsg[rc].len = strlen(http_err_msgs[rc]);
2040 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041 }
2042
2043 /*
2044 * If this server supports a maxconn parameter, it needs a dedicated
2045 * tasks to fill the emptied slots when a connection leaves.
2046 */
2047 newsrv = curproxy->srv;
2048 while (newsrv != NULL) {
2049 if (newsrv->minconn >= newsrv->maxconn) {
2050 /* Only 'minconn' was specified, or it was higher than or equal
2051 * to 'maxconn'. Let's turn this into maxconn and clean it, as
2052 * this will avoid further useless expensive computations.
2053 */
2054 newsrv->maxconn = newsrv->minconn;
2055 newsrv->minconn = 0;
2056 }
2057
2058 if (newsrv->maxconn > 0) {
2059 struct task *t;
2060
2061 if ((t = pool_alloc(task)) == NULL) {
2062 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2063 return -1;
2064 }
2065
2066 t->next = t->prev = t->rqnext = NULL; /* task not in run queue yet */
2067 t->wq = LIST_HEAD(wait_queue[1]); /* already assigned to the eternity queue */
2068 t->state = TASK_IDLE;
2069 t->process = process_srv_queue;
2070 t->context = newsrv;
2071 newsrv->queue_mgt = t;
2072
2073 /* never run it unless specifically woken up */
2074 tv_eternity(&t->expire);
2075 task_queue(t);
2076 }
2077 newsrv = newsrv->next;
2078 }
2079
2080 /* now we'll start this proxy's health checks if any */
2081 /* 1- count the checkers to run simultaneously */
2082 nbchk = 0;
2083 mininter = 0;
2084 newsrv = curproxy->srv;
2085 while (newsrv != NULL) {
2086 if (newsrv->state & SRV_CHECKED) {
2087 if (!mininter || mininter > newsrv->inter)
2088 mininter = newsrv->inter;
2089 nbchk++;
2090 }
2091 newsrv = newsrv->next;
2092 }
2093
2094 /* 2- start them as far as possible from each others while respecting
2095 * their own intervals. For this, we will start them after their own
2096 * interval added to the min interval divided by the number of servers,
2097 * weighted by the server's position in the list.
2098 */
2099 if (nbchk > 0) {
2100 struct task *t;
2101 int srvpos;
2102
2103 newsrv = curproxy->srv;
2104 srvpos = 0;
2105 while (newsrv != NULL) {
2106 /* should this server be checked ? */
2107 if (newsrv->state & SRV_CHECKED) {
2108 if ((t = pool_alloc(task)) == NULL) {
2109 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2110 return -1;
2111 }
2112
2113 t->next = t->prev = t->rqnext = NULL; /* task not in run queue yet */
2114 t->wq = LIST_HEAD(wait_queue[0]); /* but already has a wait queue assigned */
2115 t->state = TASK_IDLE;
2116 t->process = process_chk;
2117 t->context = newsrv;
2118
2119 /* check this every ms */
2120 tv_delayfrom(&t->expire, &now,
2121 newsrv->inter + mininter * srvpos / nbchk);
2122 task_queue(t);
2123 //task_wakeup(&rq, t);
2124 srvpos++;
2125 }
2126 newsrv = newsrv->next;
2127 }
2128 }
2129
2130 curproxy = curproxy->next;
2131 }
2132 if (cfgerr > 0) {
2133 Alert("Errors found in configuration file, aborting.\n");
2134 return -1;
2135 }
2136 else
2137 return 0;
2138}
2139
2140
2141
2142/*
2143 * Local variables:
2144 * c-indent-level: 8
2145 * c-basic-offset: 8
2146 * End:
2147 */