blob: ec15fbad2166b1e3bd795891c5fd441beb799b34 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 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 Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020047#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020048#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010049#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020050#include <proto/lb_fwlc.h>
51#include <proto/lb_fwrr.h>
52#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010055#include <proto/protocols.h>
56#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020061#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010063#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010065#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066
67
Willy Tarreauf3c69202006-07-09 16:42:34 +020068/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
69 * ssl-hello-chk option to ensure that the remote server speaks SSL.
70 *
71 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
72 */
73const char sslv3_client_hello_pkt[] = {
74 "\x16" /* ContentType : 0x16 = Hanshake */
75 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
76 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
77 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
78 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
79 "\x03\x00" /* Hello Version : 0x0300 = v3 */
80 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
81 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
82 "\x00" /* Session ID length : empty (no session ID) */
83 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
84 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
85 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
86 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
87 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
88 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
89 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
90 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
91 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
92 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
93 "\x00\x38" "\x00\x39" "\x00\x3A"
94 "\x01" /* Compression Length : 0x01 = 1 byte for types */
95 "\x00" /* Compression Type : 0x00 = NULL compression */
96};
97
Willy Tarreau3842f002009-06-14 11:39:52 +020098/* various keyword modifiers */
99enum kw_mod {
100 KWM_STD = 0, /* normal */
101 KWM_NO, /* "no" prefixed before the keyword */
102 KWM_DEF, /* "default" prefixed before the keyword */
103};
104
Willy Tarreau13943ab2006-12-31 00:24:10 +0100105/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100106struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100107 const char *name;
108 unsigned int val;
109 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100110 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100111 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100112};
113
114/* proxy->options */
115static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100117 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
118 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
119 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
120 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
121 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
122 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
123 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
127 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
128 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
129 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
130 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
131 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
132 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100133#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100134 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100135#else
136 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100137#endif
138
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100139 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100140};
141
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142/* proxy->options2 */
143static const struct cfg_opt cfg_opts2[] =
144{
145#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100146 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
147 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
148 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100149#else
150 { "splice-request", 0, 0, 0, 0 },
151 { "splice-response", 0, 0, 0, 0 },
152 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100153#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
155 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
156 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
157 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
158 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
159 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
160 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
161 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
162 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
163 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200164 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200165 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100166 { NULL, 0, 0, 0 }
167};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168
Willy Tarreau6daf3432008-01-22 16:44:08 +0100169static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200170static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
171int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100172int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200173
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200174/* List head of all known configuration keywords */
175static struct cfg_kw_list cfg_keywords = {
176 .list = LIST_HEAD_INIT(cfg_keywords.list)
177};
178
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179/*
180 * converts <str> to a list of listeners which are dynamically allocated.
181 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
182 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
183 * - <port> is a numerical port from 1 to 65535 ;
184 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
185 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200186 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100188static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189{
190 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100191 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200192 int port, end;
193
194 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200195
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 while (next && *next) {
197 struct sockaddr_storage ss;
198
199 str = next;
200 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100201 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202 *next++ = 0;
203 }
204
Emeric Bruned760922010-10-22 17:59:25 +0200205 if (*str == '/') {
206 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
207 /* so compute max path */
208 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
209 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210
Emeric Bruned760922010-10-22 17:59:25 +0200211 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100212 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
213 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200214 goto fail;
215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200218 ss.ss_family = AF_UNIX;
219 if (global.unix_bind.prefix) {
220 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
221 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 }
Emeric Bruned760922010-10-22 17:59:25 +0200223 else {
224 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
225 }
226 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 }
228 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100229 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100231 ss2 = str2sa_range(str, &port, &end);
232 if (!ss2) {
233 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
234 file, line, str);
235 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200236 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100238 if (!port) {
239 Alert("parsing [%s:%d] : missing port number: '%s'\n",
240 file, line, str);
241 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100244 /* OK the address looks correct */
245 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Emeric Bruned760922010-10-22 17:59:25 +0200247 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100248 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
249 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200250 goto fail;
251 }
252
253 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100254 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
255 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200256 goto fail;
257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200258 }
259
260 for (; port <= end; port++) {
261 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200262 l->next = curproxy->listen;
263 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264
265 l->fd = -1;
266 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100267 l->state = LI_INIT;
268
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100269 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100271 tcpv4_add_listener(l);
272 }
Emeric Bruned760922010-10-22 17:59:25 +0200273 else if (ss.ss_family == AF_INET6) {
274 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
275 tcpv6_add_listener(l);
276 }
277 else {
278 l->perm.ux.gid = l->perm.ux.uid = -1;
279 l->perm.ux.mode = 0;
280 uxst_add_listener(l);
281 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200282
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200283 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100284 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285 } /* end for(port) */
286 } /* end while(next) */
287 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200288 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 fail:
290 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200291 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292}
293
Willy Tarreau977b8e42006-12-29 14:19:17 +0100294/*
295 * Sends a warning if proxy <proxy> does not have at least one of the
296 * capabilities in <cap>. An optionnal <hint> may be added at the end
297 * of the warning to help the user. Returns 1 if a warning was emitted
298 * or 0 if the condition is valid.
299 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100300int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100301{
302 char *msg;
303
304 switch (cap) {
305 case PR_CAP_BE: msg = "no backend"; break;
306 case PR_CAP_FE: msg = "no frontend"; break;
307 case PR_CAP_RS: msg = "no ruleset"; break;
308 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
309 default: msg = "not enough"; break;
310 }
311
312 if (!(proxy->cap & cap)) {
313 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100314 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100315 return 1;
316 }
317 return 0;
318}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319
Willy Tarreau61d18892009-03-31 10:49:21 +0200320/* Report a warning if a rule is placed after a 'block' rule.
321 * Return 1 if the warning has been emitted, otherwise 0.
322 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100323int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200324{
325 if (!LIST_ISEMPTY(&proxy->block_cond)) {
326 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
327 file, line, arg);
328 return 1;
329 }
330 return 0;
331}
332
333/* Report a warning if a rule is placed after a reqrewrite rule.
334 * Return 1 if the warning has been emitted, otherwise 0.
335 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100336int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200337{
338 if (proxy->req_exp) {
339 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
340 file, line, arg);
341 return 1;
342 }
343 return 0;
344}
345
346/* Report a warning if a rule is placed after a reqadd rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100349int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200350{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100351 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200352 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
359/* Report a warning if a rule is placed after a redirect rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
364 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
372/* Report a warning if a rule is placed after a 'use_backend' rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
377 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
385/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100386int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200387{
388 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
389 warnif_rule_after_reqadd(proxy, file, line, arg) ||
390 warnif_rule_after_redirect(proxy, file, line, arg) ||
391 warnif_rule_after_use_backend(proxy, file, line, arg);
392}
393
394/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100395int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200396{
397 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_redirect(proxy, file, line, arg) ||
406 warnif_rule_after_use_backend(proxy, file, line, arg);
407}
408
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100409/* Report it if a request ACL condition uses some response-only parameters. It
410 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
411 * Note that <cond> may be NULL and then will be ignored.
412 */
413static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
414{
415 struct acl *acl;
416
417 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
418 return 0;
419
420 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
421 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
422 file, line, acl ? acl->name : "(unknown)");
423 return ERR_WARN;
424}
425
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100426/* Report it if a request ACL condition uses some request-only volatile parameters.
427 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
428 * Note that <cond> may be NULL and then will be ignored.
429 */
430static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
431{
432 struct acl *acl;
433
434 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
435 return 0;
436
437 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
438 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
439 file, line, acl ? acl->name : "(unknown)");
440 return ERR_WARN;
441}
442
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100443
Willy Tarreaubaaee002006-06-26 02:48:02 +0200444/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200445 * parse a line in a <global> section. Returns the error code, 0 if OK, or
446 * any combination of :
447 * - ERR_ABORT: must abort ASAP
448 * - ERR_FATAL: we can continue parsing but not start the service
449 * - ERR_WARN: a warning has been emitted
450 * - ERR_ALERT: an alert has been emitted
451 * Only the two first ones can stop processing, the two others are just
452 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200454int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455{
Willy Tarreau058e9072009-07-20 09:30:05 +0200456 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200457 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200458
459 if (!strcmp(args[0], "global")) { /* new section */
460 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 }
463 else if (!strcmp(args[0], "daemon")) {
464 global.mode |= MODE_DAEMON;
465 }
466 else if (!strcmp(args[0], "debug")) {
467 global.mode |= MODE_DEBUG;
468 }
469 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100470 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200471 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200472 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100473 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200474 }
475 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100476 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200478 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100479 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200480 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100481 else if (!strcmp(args[0], "nosplice")) {
482 global.tune.options &= ~GTUNE_USE_SPLICE;
483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200484 else if (!strcmp(args[0], "quiet")) {
485 global.mode |= MODE_QUIET;
486 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200487 else if (!strcmp(args[0], "tune.maxpollevents")) {
488 if (global.tune.maxpollevents != 0) {
489 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200490 err_code |= ERR_ALERT;
491 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200492 }
493 if (*(args[1]) == 0) {
494 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200495 err_code |= ERR_ALERT | ERR_FATAL;
496 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200497 }
498 global.tune.maxpollevents = atol(args[1]);
499 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100500 else if (!strcmp(args[0], "tune.maxaccept")) {
501 if (global.tune.maxaccept != 0) {
502 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200503 err_code |= ERR_ALERT;
504 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100505 }
506 if (*(args[1]) == 0) {
507 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200508 err_code |= ERR_ALERT | ERR_FATAL;
509 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100510 }
511 global.tune.maxaccept = atol(args[1]);
512 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200513 else if (!strcmp(args[0], "tune.chksize")) {
514 if (*(args[1]) == 0) {
515 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
516 err_code |= ERR_ALERT | ERR_FATAL;
517 goto out;
518 }
519 global.tune.chksize = atol(args[1]);
520 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200521 else if (!strcmp(args[0], "tune.bufsize")) {
522 if (*(args[1]) == 0) {
523 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
524 err_code |= ERR_ALERT | ERR_FATAL;
525 goto out;
526 }
527 global.tune.bufsize = atol(args[1]);
528 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
529 global.tune.maxrewrite = global.tune.bufsize / 2;
530 }
531 else if (!strcmp(args[0], "tune.maxrewrite")) {
532 if (*(args[1]) == 0) {
533 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
534 err_code |= ERR_ALERT | ERR_FATAL;
535 goto out;
536 }
537 global.tune.maxrewrite = atol(args[1]);
538 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
539 global.tune.maxrewrite = global.tune.bufsize / 2;
540 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100541 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
542 if (global.tune.client_rcvbuf != 0) {
543 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
544 err_code |= ERR_ALERT;
545 goto out;
546 }
547 if (*(args[1]) == 0) {
548 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT | ERR_FATAL;
550 goto out;
551 }
552 global.tune.client_rcvbuf = atol(args[1]);
553 }
554 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
555 if (global.tune.server_rcvbuf != 0) {
556 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
557 err_code |= ERR_ALERT;
558 goto out;
559 }
560 if (*(args[1]) == 0) {
561 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
562 err_code |= ERR_ALERT | ERR_FATAL;
563 goto out;
564 }
565 global.tune.server_rcvbuf = atol(args[1]);
566 }
567 else if (!strcmp(args[0], "tune.sndbuf.client")) {
568 if (global.tune.client_sndbuf != 0) {
569 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
570 err_code |= ERR_ALERT;
571 goto out;
572 }
573 if (*(args[1]) == 0) {
574 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
575 err_code |= ERR_ALERT | ERR_FATAL;
576 goto out;
577 }
578 global.tune.client_sndbuf = atol(args[1]);
579 }
580 else if (!strcmp(args[0], "tune.sndbuf.server")) {
581 if (global.tune.server_sndbuf != 0) {
582 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
583 err_code |= ERR_ALERT;
584 goto out;
585 }
586 if (*(args[1]) == 0) {
587 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
588 err_code |= ERR_ALERT | ERR_FATAL;
589 goto out;
590 }
591 global.tune.server_sndbuf = atol(args[1]);
592 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200593 else if (!strcmp(args[0], "tune.pipesize")) {
594 if (*(args[1]) == 0) {
595 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT | ERR_FATAL;
597 goto out;
598 }
599 global.tune.pipesize = atol(args[1]);
600 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200601 else if (!strcmp(args[0], "tune.http.maxhdr")) {
602 if (*(args[1]) == 0) {
603 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
604 err_code |= ERR_ALERT | ERR_FATAL;
605 goto out;
606 }
607 global.tune.max_http_hdr = atol(args[1]);
608 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200609 else if (!strcmp(args[0], "uid")) {
610 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200611 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200612 err_code |= ERR_ALERT;
613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200614 }
615 if (*(args[1]) == 0) {
616 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200617 err_code |= ERR_ALERT | ERR_FATAL;
618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200619 }
620 global.uid = atol(args[1]);
621 }
622 else if (!strcmp(args[0], "gid")) {
623 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200624 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200625 err_code |= ERR_ALERT;
626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200627 }
628 if (*(args[1]) == 0) {
629 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200630 err_code |= ERR_ALERT | ERR_FATAL;
631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632 }
633 global.gid = atol(args[1]);
634 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200635 /* user/group name handling */
636 else if (!strcmp(args[0], "user")) {
637 struct passwd *ha_user;
638 if (global.uid != 0) {
639 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200640 err_code |= ERR_ALERT;
641 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200642 }
643 errno = 0;
644 ha_user = getpwnam(args[1]);
645 if (ha_user != NULL) {
646 global.uid = (int)ha_user->pw_uid;
647 }
648 else {
649 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200650 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200651 }
652 }
653 else if (!strcmp(args[0], "group")) {
654 struct group *ha_group;
655 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200656 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200657 err_code |= ERR_ALERT;
658 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200659 }
660 errno = 0;
661 ha_group = getgrnam(args[1]);
662 if (ha_group != NULL) {
663 global.gid = (int)ha_group->gr_gid;
664 }
665 else {
666 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200667 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200668 }
669 }
670 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671 else if (!strcmp(args[0], "nbproc")) {
672 if (global.nbproc != 0) {
673 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200674 err_code |= ERR_ALERT;
675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676 }
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200681 }
682 global.nbproc = atol(args[1]);
683 }
684 else if (!strcmp(args[0], "maxconn")) {
685 if (global.maxconn != 0) {
686 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT;
688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200689 }
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200694 }
695 global.maxconn = atol(args[1]);
696#ifdef SYSTEM_MAXCONN
697 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
698 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);
699 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200700 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 }
702#endif /* SYSTEM_MAXCONN */
703 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200704 else if (!strcmp(args[0], "maxconnrate")) {
705 if (global.cps_lim != 0) {
706 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
707 err_code |= ERR_ALERT;
708 goto out;
709 }
710 if (*(args[1]) == 0) {
711 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715 global.cps_lim = atol(args[1]);
716 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100717 else if (!strcmp(args[0], "maxpipes")) {
718 if (global.maxpipes != 0) {
719 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200720 err_code |= ERR_ALERT;
721 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100722 }
723 if (*(args[1]) == 0) {
724 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200725 err_code |= ERR_ALERT | ERR_FATAL;
726 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100727 }
728 global.maxpipes = atol(args[1]);
729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200730 else if (!strcmp(args[0], "ulimit-n")) {
731 if (global.rlimit_nofile != 0) {
732 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200733 err_code |= ERR_ALERT;
734 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200735 }
736 if (*(args[1]) == 0) {
737 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200738 err_code |= ERR_ALERT | ERR_FATAL;
739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200740 }
741 global.rlimit_nofile = atol(args[1]);
742 }
743 else if (!strcmp(args[0], "chroot")) {
744 if (global.chroot != NULL) {
745 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200746 err_code |= ERR_ALERT;
747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748 }
749 if (*(args[1]) == 0) {
750 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200751 err_code |= ERR_ALERT | ERR_FATAL;
752 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200753 }
754 global.chroot = strdup(args[1]);
755 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200756 else if (!strcmp(args[0], "description")) {
757 int i, len=0;
758 char *d;
759
760 if (!*args[1]) {
761 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
762 file, linenum, args[0]);
763 err_code |= ERR_ALERT | ERR_FATAL;
764 goto out;
765 }
766
767 for(i=1; *args[i]; i++)
768 len += strlen(args[i])+1;
769
770 if (global.desc)
771 free(global.desc);
772
773 global.desc = d = (char *)calloc(1, len);
774
775 d += sprintf(d, "%s", args[1]);
776 for(i=2; *args[i]; i++)
777 d += sprintf(d, " %s", args[i]);
778 }
779 else if (!strcmp(args[0], "node")) {
780 int i;
781 char c;
782
783 for (i=0; args[1][i]; i++) {
784 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100785 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
786 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200787 break;
788 }
789
790 if (!i || args[1][i]) {
791 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
792 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
793 file, linenum, args[0]);
794 err_code |= ERR_ALERT | ERR_FATAL;
795 goto out;
796 }
797
798 if (global.node)
799 free(global.node);
800
801 global.node = strdup(args[1]);
802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200803 else if (!strcmp(args[0], "pidfile")) {
804 if (global.pidfile != NULL) {
805 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200806 err_code |= ERR_ALERT;
807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200808 }
809 if (*(args[1]) == 0) {
810 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200811 err_code |= ERR_ALERT | ERR_FATAL;
812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200813 }
814 global.pidfile = strdup(args[1]);
815 }
Emeric Bruned760922010-10-22 17:59:25 +0200816 else if (!strcmp(args[0], "unix-bind")) {
817 int cur_arg = 1;
818 while (*(args[cur_arg])) {
819 if (!strcmp(args[cur_arg], "prefix")) {
820 if (global.unix_bind.prefix != NULL) {
821 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
822 err_code |= ERR_ALERT;
823 cur_arg += 2;
824 continue;
825 }
826
827 if (*(args[cur_arg+1]) == 0) {
828 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
831 }
832 global.unix_bind.prefix = strdup(args[cur_arg+1]);
833 cur_arg += 2;
834 continue;
835 }
836
837 if (!strcmp(args[cur_arg], "mode")) {
838
839 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
840 cur_arg += 2;
841 continue;
842 }
843
844 if (!strcmp(args[cur_arg], "uid")) {
845
846 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
847 cur_arg += 2;
848 continue;
849 }
850
851 if (!strcmp(args[cur_arg], "gid")) {
852
853 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
854 cur_arg += 2;
855 continue;
856 }
857
858 if (!strcmp(args[cur_arg], "user")) {
859 struct passwd *user;
860
861 user = getpwnam(args[cur_arg + 1]);
862 if (!user) {
863 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
864 file, linenum, args[0], args[cur_arg + 1 ]);
865 err_code |= ERR_ALERT | ERR_FATAL;
866 goto out;
867 }
868
869 global.unix_bind.ux.uid = user->pw_uid;
870 cur_arg += 2;
871 continue;
872 }
873
874 if (!strcmp(args[cur_arg], "group")) {
875 struct group *group;
876
877 group = getgrnam(args[cur_arg + 1]);
878 if (!group) {
879 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
880 file, linenum, args[0], args[cur_arg + 1 ]);
881 err_code |= ERR_ALERT | ERR_FATAL;
882 goto out;
883 }
884
885 global.unix_bind.ux.gid = group->gr_gid;
886 cur_arg += 2;
887 continue;
888 }
889
Willy Tarreaub48f9582011-09-05 01:17:06 +0200890 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200891 file, linenum, args[0]);
892 err_code |= ERR_ALERT | ERR_FATAL;
893 goto out;
894 }
895 }
William Lallemand0f99e342011-10-12 17:50:54 +0200896 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
897 /* delete previous herited or defined syslog servers */
898 struct logsrv *back;
899 struct logsrv *tmp;
900
901 if (*(args[1]) != 0) {
902 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
903 err_code |= ERR_ALERT | ERR_FATAL;
904 goto out;
905 }
906
907 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
908 LIST_DEL(&tmp->list);
909 free(tmp);
910 }
911 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200912 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200913 struct logsrv *logsrv;
914
Willy Tarreaubaaee002006-06-26 02:48:02 +0200915 if (*(args[1]) == 0 || *(args[2]) == 0) {
916 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 }
William Lallemand0f99e342011-10-12 17:50:54 +0200920
921 logsrv = calloc(1, sizeof(struct logsrv));
922
923 logsrv->facility = get_log_facility(args[2]);
924 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200925 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200926 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200927 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200928 }
929
William Lallemand0f99e342011-10-12 17:50:54 +0200930 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200932 logsrv->level = get_log_level(args[3]);
933 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200936 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938 }
939
William Lallemand0f99e342011-10-12 17:50:54 +0200940 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200941 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200942 logsrv->minlvl = get_log_level(args[4]);
943 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200944 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200945 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200946 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200947 }
948 }
949
Robert Tsai81ae1952007-12-05 10:47:29 +0100950 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100951 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100952 if (!sk) {
953 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100954 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100955 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200956 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100957 goto out;
958 }
William Lallemand0f99e342011-10-12 17:50:54 +0200959 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100960 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100961 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100962 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100963 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
964 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200965 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100966 goto out;
967 }
William Lallemand0f99e342011-10-12 17:50:54 +0200968 logsrv->addr = *sk;
969 if (!get_host_port(&logsrv->addr))
970 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100971 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200972
William Lallemand0f99e342011-10-12 17:50:54 +0200973 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200974 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100975 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
976 char *name;
977 int len;
978
979 if (global.log_send_hostname != NULL) {
980 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
981 err_code |= ERR_ALERT;
982 goto out;
983 }
984
985 if (*(args[1]))
986 name = args[1];
987 else
988 name = hostname;
989
990 len = strlen(name);
991
992 /* We'll add a space after the name to respect the log format */
993 free(global.log_send_hostname);
994 global.log_send_hostname = malloc(len + 2);
995 snprintf(global.log_send_hostname, len + 2, "%s ", name);
996 }
Kevinm48936af2010-12-22 16:08:21 +0000997 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
998 if (*(args[1]) == 0) {
999 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1000 err_code |= ERR_ALERT | ERR_FATAL;
1001 goto out;
1002 }
1003 free(global.log_tag);
1004 global.log_tag = strdup(args[1]);
1005 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001006 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1007 if (global.spread_checks != 0) {
1008 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001009 err_code |= ERR_ALERT;
1010 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001011 }
1012 if (*(args[1]) == 0) {
1013 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001014 err_code |= ERR_ALERT | ERR_FATAL;
1015 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001016 }
1017 global.spread_checks = atol(args[1]);
1018 if (global.spread_checks < 0 || global.spread_checks > 50) {
1019 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001020 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001021 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001022 }
1023 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001024 struct cfg_kw_list *kwl;
1025 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001026 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001027
1028 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1029 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1030 if (kwl->kw[index].section != CFG_GLOBAL)
1031 continue;
1032 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1033 /* prepare error message just in case */
1034 snprintf(trash, sizeof(trash),
1035 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001036 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001037 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001038 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001039 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001040 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001041 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001042 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001043 err_code |= ERR_WARN;
1044 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001045 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001046 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001047 }
1048 }
1049 }
1050
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001052 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001054
Willy Tarreau058e9072009-07-20 09:30:05 +02001055 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001056 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001057 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058}
1059
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001060void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001061{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001062 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001063 defproxy.mode = PR_MODE_TCP;
1064 defproxy.state = PR_STNEW;
1065 defproxy.maxconn = cfg_maxpconn;
1066 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001067
1068 defproxy.defsrv.inter = DEF_CHKINTR;
1069 defproxy.defsrv.fastinter = 0;
1070 defproxy.defsrv.downinter = 0;
1071 defproxy.defsrv.rise = DEF_RISETIME;
1072 defproxy.defsrv.fall = DEF_FALLTIME;
1073 defproxy.defsrv.check_port = 0;
1074 defproxy.defsrv.maxqueue = 0;
1075 defproxy.defsrv.minconn = 0;
1076 defproxy.defsrv.maxconn = 0;
1077 defproxy.defsrv.slowstart = 0;
1078 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1079 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1080 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081}
1082
Willy Tarreauade5ec42010-01-28 19:33:49 +01001083
1084static int create_cond_regex_rule(const char *file, int line,
1085 struct proxy *px, int dir, int action, int flags,
1086 const char *cmd, const char *reg, const char *repl,
1087 const char **cond_start)
1088{
1089 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001090 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001091 const char *err;
1092 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001093 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001094
1095 if (px == &defproxy) {
1096 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1097 err_code |= ERR_ALERT | ERR_FATAL;
1098 goto err;
1099 }
1100
1101 if (*reg == 0) {
1102 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1103 err_code |= ERR_ALERT | ERR_FATAL;
1104 goto err;
1105 }
1106
1107 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1108 err_code |= ERR_WARN;
1109
Willy Tarreau5321c422010-01-28 20:35:13 +01001110 if (cond_start &&
1111 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001112 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1113 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1114 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001115 err_code |= ERR_ALERT | ERR_FATAL;
1116 goto err;
1117 }
1118 }
1119 else if (cond_start && **cond_start) {
1120 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1121 file, line, cmd, *cond_start);
1122 err_code |= ERR_ALERT | ERR_FATAL;
1123 goto err;
1124 }
1125
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001126 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001127 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001128 else
1129 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001130
Willy Tarreauade5ec42010-01-28 19:33:49 +01001131 preg = calloc(1, sizeof(regex_t));
1132 if (!preg) {
1133 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1134 err_code = ERR_ALERT | ERR_FATAL;
1135 goto err;
1136 }
1137
1138 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1139 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1140 err_code = ERR_ALERT | ERR_FATAL;
1141 goto err;
1142 }
1143
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001144 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001145 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001146 if (repl && err) {
1147 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1148 file, line, cmd, *err);
1149 err_code |= ERR_ALERT | ERR_FATAL;
1150 goto err;
1151 }
1152
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001153 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001154 err_code |= ERR_WARN;
1155
Willy Tarreauf4068b62012-05-08 17:37:49 +02001156 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001157 return err_code;
1158 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001159 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001160 free(preg);
1161 return err_code;
1162}
1163
Willy Tarreaubaaee002006-06-26 02:48:02 +02001164/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001165 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001166 * Returns the error code, 0 if OK, or any combination of :
1167 * - ERR_ABORT: must abort ASAP
1168 * - ERR_FATAL: we can continue parsing but not start the service
1169 * - ERR_WARN: a warning has been emitted
1170 * - ERR_ALERT: an alert has been emitted
1171 * Only the two first ones can stop processing, the two others are just
1172 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001174int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1175{
1176 static struct peers *curpeers = NULL;
1177 struct peer *newpeer = NULL;
1178 const char *err;
1179 int err_code = 0;
1180
1181 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1182
1183 err = invalid_char(args[1]);
1184 if (err) {
1185 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1186 file, linenum, *err, args[0], args[1]);
1187 err_code |= ERR_ALERT | ERR_FATAL;
1188 }
1189
1190 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1191 /*
1192 * If there are two proxies with the same name only following
1193 * combinations are allowed:
1194 */
1195 if (strcmp(curpeers->id, args[1]) == 0) {
1196 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1197 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1198 err_code |= ERR_WARN;
1199 }
1200 }
1201
1202 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1203 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1204 err_code |= ERR_ALERT | ERR_ABORT;
1205 goto out;
1206 }
1207
1208 curpeers->next = peers;
1209 peers = curpeers;
1210 curpeers->conf.file = file;
1211 curpeers->conf.line = linenum;
1212 curpeers->last_change = now.tv_sec;
1213 curpeers->id = strdup(args[1]);
1214 }
1215 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1216 char *rport, *raddr;
1217 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001218 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001219
1220 if (!*args[2]) {
1221 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1222 file, linenum, args[0]);
1223 err_code |= ERR_ALERT | ERR_FATAL;
1224 goto out;
1225 }
1226
1227 err = invalid_char(args[1]);
1228 if (err) {
1229 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1230 file, linenum, *err, args[1]);
1231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
1233 }
1234
1235 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1236 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1237 err_code |= ERR_ALERT | ERR_ABORT;
1238 goto out;
1239 }
1240
1241 /* the peers are linked backwards first */
1242 curpeers->count++;
1243 newpeer->next = curpeers->remote;
1244 curpeers->remote = newpeer;
1245 newpeer->peers = curpeers;
1246 newpeer->conf.file = file;
1247 newpeer->conf.line = linenum;
1248
1249 newpeer->last_change = now.tv_sec;
1250 newpeer->id = strdup(args[1]);
1251
1252 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001253 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001254 if (rport) {
1255 *rport++ = 0;
1256 realport = atol(rport);
1257 }
1258 if (!realport) {
1259 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263
Willy Tarreaufab5a432011-03-04 15:31:53 +01001264 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001265 free(raddr);
1266 if (!sk) {
1267 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1268 err_code |= ERR_ALERT | ERR_FATAL;
1269 goto out;
1270 }
1271 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001272 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
1273
1274 if (!sk) {
1275 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1276 file, linenum, newpeer->addr.ss_family, args[2]);
1277 err_code |= ERR_ALERT | ERR_FATAL;
1278 goto out;
1279 }
1280
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001281 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001282
1283 if (strcmp(newpeer->id, localpeer) == 0) {
1284 /* Current is local peer, it define a frontend */
1285 newpeer->local = 1;
1286
1287 if (!curpeers->peers_fe) {
1288 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1289 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1290 err_code |= ERR_ALERT | ERR_ABORT;
1291 goto out;
1292 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001293
Willy Tarreau237250c2011-07-29 01:49:03 +02001294 init_new_proxy(curpeers->peers_fe);
1295 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001296
1297 curpeers->peers_fe->last_change = now.tv_sec;
1298 curpeers->peers_fe->id = strdup(args[1]);
1299 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001300 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001301 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1302 curpeers->peers_fe->timeout.connect = 5000;
1303 curpeers->peers_fe->accept = peer_accept;
1304 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001305 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001306 err_code |= ERR_FATAL;
1307 goto out;
1308 }
1309 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1310 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1311 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1312 curpeers->peers_fe->listen->accept = session_accept;
1313 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1314 curpeers->peers_fe->listen->handler = process_session;
1315 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001316 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1317 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001318 }
1319 }
1320 } /* neither "peer" nor "peers" */
1321 else if (*args[0] != 0) {
1322 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1323 err_code |= ERR_ALERT | ERR_FATAL;
1324 goto out;
1325 }
1326
1327out:
1328 return err_code;
1329}
1330
1331
Willy Tarreau3842f002009-06-14 11:39:52 +02001332int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001333{
1334 static struct proxy *curproxy = NULL;
1335 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001336 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001337 int rc;
1338 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001339 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001340 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001341 struct logsrv *tmplogsrv;
1342 struct logformat_node *tmplf;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001343 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001344
Willy Tarreau977b8e42006-12-29 14:19:17 +01001345 if (!strcmp(args[0], "listen"))
1346 rc = PR_CAP_LISTEN;
1347 else if (!strcmp(args[0], "frontend"))
1348 rc = PR_CAP_FE | PR_CAP_RS;
1349 else if (!strcmp(args[0], "backend"))
1350 rc = PR_CAP_BE | PR_CAP_RS;
1351 else if (!strcmp(args[0], "ruleset"))
1352 rc = PR_CAP_RS;
1353 else
1354 rc = PR_CAP_NONE;
1355
1356 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357 if (!*args[1]) {
1358 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1359 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1360 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001361 err_code |= ERR_ALERT | ERR_ABORT;
1362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001364
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001365 err = invalid_char(args[1]);
1366 if (err) {
1367 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1368 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001369 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001370 }
1371
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001372 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1373 /*
1374 * If there are two proxies with the same name only following
1375 * combinations are allowed:
1376 *
1377 * listen backend frontend ruleset
1378 * listen - - - -
1379 * backend - - OK -
1380 * frontend - OK - -
1381 * ruleset - - - -
1382 */
1383
1384 if (!strcmp(curproxy->id, args[1]) &&
1385 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1386 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001387 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1388 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1389 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001390 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001391 }
1392 }
1393
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1395 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001396 err_code |= ERR_ALERT | ERR_ABORT;
1397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001399
Willy Tarreau97cb7802010-01-03 20:23:58 +01001400 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 curproxy->next = proxy;
1402 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001403 curproxy->conf.file = file;
1404 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001405 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001406 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001407 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001408
1409 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001410 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001411 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001412 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001413 err_code |= ERR_FATAL;
1414 goto out;
1415 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001416 new = curproxy->listen;
1417 while (new != last) {
1418 new->conf.file = file;
1419 new->conf.line = linenum;
1420 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001421 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001422 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001423 }
1424
1425 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001426 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001427 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001428
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001430 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001431 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001432 curproxy->no_options = defproxy.no_options;
1433 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001434 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001435 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001436 curproxy->except_net = defproxy.except_net;
1437 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001438 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001439 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001440
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001441 if (defproxy.fwdfor_hdr_len) {
1442 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1443 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1444 }
1445
Willy Tarreaub86db342009-11-30 11:50:16 +01001446 if (defproxy.orgto_hdr_len) {
1447 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1448 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1449 }
1450
Mark Lamourinec2247f02012-01-04 13:02:01 -05001451 if (defproxy.server_id_hdr_len) {
1452 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1453 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1454 }
1455
Willy Tarreau977b8e42006-12-29 14:19:17 +01001456 if (curproxy->cap & PR_CAP_FE) {
1457 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001458 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001459 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001460
1461 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001462 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1463 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001464
1465 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1466 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467
Willy Tarreau977b8e42006-12-29 14:19:17 +01001468 if (curproxy->cap & PR_CAP_BE) {
1469 curproxy->fullconn = defproxy.fullconn;
1470 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001471
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001472 if (defproxy.check_req) {
1473 curproxy->check_req = calloc(1, defproxy.check_len);
1474 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1475 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001476 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001477
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001478 if (defproxy.expect_str) {
1479 curproxy->expect_str = strdup(defproxy.expect_str);
1480 if (defproxy.expect_regex) {
1481 /* note: this regex is known to be valid */
1482 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1483 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1484 }
1485 }
1486
Willy Tarreau977b8e42006-12-29 14:19:17 +01001487 if (defproxy.cookie_name)
1488 curproxy->cookie_name = strdup(defproxy.cookie_name);
1489 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001490 if (defproxy.cookie_domain)
1491 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001492
Willy Tarreau31936852010-10-06 16:59:56 +02001493 if (defproxy.cookie_maxidle)
1494 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1495
1496 if (defproxy.cookie_maxlife)
1497 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1498
Emeric Brun647caf12009-06-30 17:57:00 +02001499 if (defproxy.rdp_cookie_name)
1500 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1501 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1502
Willy Tarreau01732802007-11-01 22:48:15 +01001503 if (defproxy.url_param_name)
1504 curproxy->url_param_name = strdup(defproxy.url_param_name);
1505 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001506
Benoitaffb4812009-03-25 13:02:10 +01001507 if (defproxy.hh_name)
1508 curproxy->hh_name = strdup(defproxy.hh_name);
1509 curproxy->hh_len = defproxy.hh_len;
1510 curproxy->hh_match_domain = defproxy.hh_match_domain;
1511
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001512 if (defproxy.iface_name)
1513 curproxy->iface_name = strdup(defproxy.iface_name);
1514 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001515 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001516
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001517 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001518 if (defproxy.capture_name)
1519 curproxy->capture_name = strdup(defproxy.capture_name);
1520 curproxy->capture_namelen = defproxy.capture_namelen;
1521 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523
Willy Tarreau977b8e42006-12-29 14:19:17 +01001524 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001525 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001526 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001527 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001528 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001529 curproxy->uri_auth = defproxy.uri_auth;
1530 curproxy->mon_net = defproxy.mon_net;
1531 curproxy->mon_mask = defproxy.mon_mask;
1532 if (defproxy.monitor_uri)
1533 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1534 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001535 if (defproxy.defbe.name)
1536 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001537 }
1538
1539 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001540 curproxy->timeout.connect = defproxy.timeout.connect;
1541 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001542 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001543 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001544 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001545 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001546 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001547 curproxy->source_addr = defproxy.source_addr;
1548 }
1549
Willy Tarreaubaaee002006-06-26 02:48:02 +02001550 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001551
1552 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001553 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001554 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001555 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001556 LIST_INIT(&node->list);
1557 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1558 }
1559
William Lallemand723b73a2012-02-08 16:37:49 +01001560 /* copy default log_format to curproxy */
1561 list_for_each_entry(tmplf, &defproxy.logformat, list) {
1562 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1563 memcpy(node, tmplf, sizeof(struct logformat_node));
1564 LIST_INIT(&node->list);
1565 LIST_ADDQ(&curproxy->logformat, &node->list);
1566 }
1567
William Lallemanda73203e2012-03-12 12:48:57 +01001568 /* copy default unique_id to curproxy */
1569 list_for_each_entry(tmplf, &defproxy.format_unique_id, list) {
1570 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1571 memcpy(node, tmplf, sizeof(struct logformat_node));
1572 LIST_INIT(&node->list);
1573 LIST_ADDQ(&curproxy->format_unique_id, &node->list);
1574 }
1575
1576 /* copy default header unique id */
1577 if (defproxy.header_unique_id)
1578 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1579
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001581 curproxy->conf.used_listener_id = EB_ROOT;
1582 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001583
Willy Tarreau93893792009-07-23 13:19:11 +02001584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001585 }
1586 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1587 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001588 /* FIXME-20070101: we should do this too at the end of the
1589 * config parsing to free all default values.
1590 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001591 free(defproxy.check_req);
1592 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001593 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001594 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001595 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001596 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001597 free(defproxy.capture_name);
1598 free(defproxy.monitor_uri);
1599 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001600 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001601 free(defproxy.fwdfor_hdr_name);
1602 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001603 free(defproxy.orgto_hdr_name);
1604 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001605 free(defproxy.server_id_hdr_name);
1606 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001607 free(defproxy.expect_str);
1608 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001609
Willy Tarreaua534fea2008-08-03 12:19:50 +02001610 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001611 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001612
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613 /* we cannot free uri_auth because it might already be used */
1614 init_default_instance();
1615 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001616 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001618 }
1619 else if (curproxy == NULL) {
1620 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001621 err_code |= ERR_ALERT | ERR_FATAL;
1622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 }
1624
Willy Tarreau977b8e42006-12-29 14:19:17 +01001625
1626 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001627 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001628 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001629 int cur_arg;
1630
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 if (curproxy == &defproxy) {
1632 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001633 err_code |= ERR_ALERT | ERR_FATAL;
1634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001636 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001637 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638
Emeric Bruned760922010-10-22 17:59:25 +02001639 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001640 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001641 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001642 err_code |= ERR_ALERT | ERR_FATAL;
1643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001645
1646 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001647
1648 /* NOTE: the following line might create several listeners if there
1649 * are comma-separated IPs or port ranges. So all further processing
1650 * will have to be applied to all listeners created after last_listen.
1651 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001652 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001653 err_code |= ERR_ALERT | ERR_FATAL;
1654 goto out;
1655 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001656
Willy Tarreau90a570f2009-10-04 20:54:54 +02001657 new_listen = curproxy->listen;
1658 while (new_listen != last_listen) {
1659 new_listen->conf.file = file;
1660 new_listen->conf.line = linenum;
1661 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001662 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001663 }
1664
Emeric Bruned760922010-10-22 17:59:25 +02001665 /* Set default global rights and owner for unix bind */
1666 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1667 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1668 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001669 cur_arg = 2;
1670 while (*(args[cur_arg])) {
1671 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1672#ifdef SO_BINDTODEVICE
1673 struct listener *l;
1674
Emeric Bruned760922010-10-22 17:59:25 +02001675 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1676 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1677 file, linenum, args[0], args[cur_arg]);
1678 err_code |= ERR_ALERT | ERR_FATAL;
1679 goto out;
1680 }
1681
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001682 if (!*args[cur_arg + 1]) {
1683 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1684 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001685 err_code |= ERR_ALERT | ERR_FATAL;
1686 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001687 }
1688
1689 for (l = curproxy->listen; l != last_listen; l = l->next)
1690 l->interface = strdup(args[cur_arg + 1]);
1691
1692 global.last_checks |= LSTCHK_NETADM;
1693
1694 cur_arg += 2;
1695 continue;
1696#else
1697 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1698 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001699 err_code |= ERR_ALERT | ERR_FATAL;
1700 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001701#endif
1702 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001703 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1704#ifdef TCP_MAXSEG
1705 struct listener *l;
1706 int mss;
1707
Emeric Bruned760922010-10-22 17:59:25 +02001708 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1709 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1710 file, linenum, args[0], args[cur_arg]);
1711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
1713 }
1714
Willy Tarreaube1b9182009-06-14 18:48:19 +02001715 if (!*args[cur_arg + 1]) {
1716 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1717 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001718 err_code |= ERR_ALERT | ERR_FATAL;
1719 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001720 }
1721
Willy Tarreau48a7e722010-12-24 15:26:39 +01001722 mss = atoi(args[cur_arg + 1]);
1723 if (!mss || abs(mss) > 65535) {
1724 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001725 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001726 err_code |= ERR_ALERT | ERR_FATAL;
1727 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001728 }
1729
1730 for (l = curproxy->listen; l != last_listen; l = l->next)
1731 l->maxseg = mss;
1732
1733 cur_arg += 2;
1734 continue;
1735#else
1736 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1737 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001738 err_code |= ERR_ALERT | ERR_FATAL;
1739 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001740#endif
1741 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001742
1743 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1744#ifdef TCP_DEFER_ACCEPT
1745 struct listener *l;
1746
1747 for (l = curproxy->listen; l != last_listen; l = l->next)
1748 l->options |= LI_O_DEF_ACCEPT;
1749
1750 cur_arg ++;
1751 continue;
1752#else
1753 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1754 file, linenum, args[0], args[cur_arg]);
1755 err_code |= ERR_ALERT | ERR_FATAL;
1756 goto out;
1757#endif
1758 }
1759
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001760 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001761#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001762 struct listener *l;
1763
Emeric Bruned760922010-10-22 17:59:25 +02001764 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1765 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1766 file, linenum, args[0], args[cur_arg]);
1767 err_code |= ERR_ALERT | ERR_FATAL;
1768 goto out;
1769 }
1770
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001771 for (l = curproxy->listen; l != last_listen; l = l->next)
1772 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001773
1774 cur_arg ++;
1775 continue;
1776#else
1777 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1778 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001779 err_code |= ERR_ALERT | ERR_FATAL;
1780 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001781#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001782 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001783
Willy Tarreau8a956912010-10-15 14:27:08 +02001784 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1785 struct listener *l;
1786
1787 for (l = curproxy->listen; l != last_listen; l = l->next)
1788 l->options |= LI_O_ACC_PROXY;
1789
1790 cur_arg ++;
1791 continue;
1792 }
1793
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001794 if (!strcmp(args[cur_arg], "name")) {
1795 struct listener *l;
1796
1797 for (l = curproxy->listen; l != last_listen; l = l->next)
1798 l->name = strdup(args[cur_arg + 1]);
1799
1800 cur_arg += 2;
1801 continue;
1802 }
1803
1804 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001805 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001806 struct listener *l;
1807
1808 if (curproxy->listen->next != last_listen) {
1809 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1810 file, linenum, args[cur_arg]);
1811 err_code |= ERR_ALERT | ERR_FATAL;
1812 goto out;
1813 }
1814
1815 if (!*args[cur_arg + 1]) {
1816 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1817 file, linenum, args[cur_arg]);
1818 err_code |= ERR_ALERT | ERR_FATAL;
1819 goto out;
1820 }
1821
1822 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001823 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001824
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001825 if (curproxy->listen->luid <= 0) {
1826 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001827 file, linenum);
1828 err_code |= ERR_ALERT | ERR_FATAL;
1829 goto out;
1830 }
1831
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001832 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1833 if (node) {
1834 l = container_of(node, struct listener, conf.id);
1835 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1836 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1837 err_code |= ERR_ALERT | ERR_FATAL;
1838 goto out;
1839 }
1840 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1841
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001842 cur_arg += 2;
1843 continue;
1844 }
1845
Emeric Bruned760922010-10-22 17:59:25 +02001846 if (!strcmp(args[cur_arg], "mode")) {
1847
1848 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1849 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1850 file, linenum, args[0], args[cur_arg]);
1851 err_code |= ERR_ALERT | ERR_FATAL;
1852 goto out;
1853 }
1854
1855 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1856
1857 cur_arg += 2;
1858 continue;
1859 }
1860
1861 if (!strcmp(args[cur_arg], "uid")) {
1862
1863 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1864 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1865 file, linenum, args[0], args[cur_arg]);
1866 err_code |= ERR_ALERT | ERR_FATAL;
1867 goto out;
1868 }
1869
1870 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1871 cur_arg += 2;
1872 continue;
1873 }
1874
1875 if (!strcmp(args[cur_arg], "gid")) {
1876
1877 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1878 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1879 file, linenum, args[0], args[cur_arg]);
1880 err_code |= ERR_ALERT | ERR_FATAL;
1881 goto out;
1882 }
1883
1884 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1885 cur_arg += 2;
1886 continue;
1887 }
1888
1889 if (!strcmp(args[cur_arg], "user")) {
1890 struct passwd *user;
1891
1892 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1893 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1894 file, linenum, args[0], args[cur_arg]);
1895 err_code |= ERR_ALERT | ERR_FATAL;
1896 goto out;
1897 }
1898 user = getpwnam(args[cur_arg + 1]);
1899 if (!user) {
1900 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1901 file, linenum, args[0], args[cur_arg + 1 ]);
1902 err_code |= ERR_ALERT | ERR_FATAL;
1903 goto out;
1904 }
1905
1906 curproxy->listen->perm.ux.uid = user->pw_uid;
1907 cur_arg += 2;
1908 continue;
1909 }
1910
1911 if (!strcmp(args[cur_arg], "group")) {
1912 struct group *group;
1913
1914 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1915 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1916 file, linenum, args[0], args[cur_arg]);
1917 err_code |= ERR_ALERT | ERR_FATAL;
1918 goto out;
1919 }
1920 group = getgrnam(args[cur_arg + 1]);
1921 if (!group) {
1922 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1923 file, linenum, args[0], args[cur_arg + 1 ]);
1924 err_code |= ERR_ALERT | ERR_FATAL;
1925 goto out;
1926 }
1927
1928 curproxy->listen->perm.ux.gid = group->gr_gid;
1929 cur_arg += 2;
1930 continue;
1931 }
1932
Willy Tarreaub48f9582011-09-05 01:17:06 +02001933 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss', 'mode', 'uid', 'gid', 'user', 'group' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001934 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_ALERT | ERR_FATAL;
1936 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001937 }
Willy Tarreau93893792009-07-23 13:19:11 +02001938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939 }
1940 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1941 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1942 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1943 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001944 err_code |= ERR_ALERT | ERR_FATAL;
1945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001947 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001948 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001949
Willy Tarreaubaaee002006-06-26 02:48:02 +02001950 /* flush useless bits */
1951 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001953 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001954 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001955 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001956 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001957
Willy Tarreau1c47f852006-07-09 08:22:27 +02001958 if (!*args[1]) {
1959 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1960 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001961 err_code |= ERR_ALERT | ERR_FATAL;
1962 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001963 }
1964
Willy Tarreaua534fea2008-08-03 12:19:50 +02001965 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001966 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001967 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001968 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001969 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1970
Willy Tarreau93893792009-07-23 13:19:11 +02001971 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001972 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1974 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1975 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1976 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1977 else {
1978 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001979 err_code |= ERR_ALERT | ERR_FATAL;
1980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981 }
1982 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001983 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001984 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001985
1986 if (curproxy == &defproxy) {
1987 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1988 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001989 err_code |= ERR_ALERT | ERR_FATAL;
1990 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001991 }
1992
1993 if (!*args[1]) {
1994 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1995 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001996 err_code |= ERR_ALERT | ERR_FATAL;
1997 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001998 }
1999
2000 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002001 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002002
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002003 if (curproxy->uuid <= 0) {
2004 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002005 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002006 err_code |= ERR_ALERT | ERR_FATAL;
2007 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002008 }
2009
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002010 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2011 if (node) {
2012 struct proxy *target = container_of(node, struct proxy, conf.id);
2013 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2014 file, linenum, proxy_type_str(curproxy), curproxy->id,
2015 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2016 err_code |= ERR_ALERT | ERR_FATAL;
2017 goto out;
2018 }
2019 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002020 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002021 else if (!strcmp(args[0], "description")) {
2022 int i, len=0;
2023 char *d;
2024
Cyril Bonté99ed3272010-01-24 23:29:44 +01002025 if (curproxy == &defproxy) {
2026 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2027 file, linenum, args[0]);
2028 err_code |= ERR_ALERT | ERR_FATAL;
2029 goto out;
2030 }
2031
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002032 if (!*args[1]) {
2033 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2034 file, linenum, args[0]);
2035 return -1;
2036 }
2037
2038 for(i=1; *args[i]; i++)
2039 len += strlen(args[i])+1;
2040
2041 d = (char *)calloc(1, len);
2042 curproxy->desc = d;
2043
2044 d += sprintf(d, "%s", args[1]);
2045 for(i=2; *args[i]; i++)
2046 d += sprintf(d, " %s", args[i]);
2047
2048 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2050 curproxy->state = PR_STSTOPPED;
2051 }
2052 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2053 curproxy->state = PR_STNEW;
2054 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002055 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2056 int cur_arg = 1;
2057 unsigned int set = 0;
2058
2059 while (*args[cur_arg]) {
2060 int u;
2061 if (strcmp(args[cur_arg], "all") == 0) {
2062 set = 0;
2063 break;
2064 }
2065 else if (strcmp(args[cur_arg], "odd") == 0) {
2066 set |= 0x55555555;
2067 }
2068 else if (strcmp(args[cur_arg], "even") == 0) {
2069 set |= 0xAAAAAAAA;
2070 }
2071 else {
2072 u = str2uic(args[cur_arg]);
2073 if (u < 1 || u > 32) {
2074 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2075 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002076 err_code |= ERR_ALERT | ERR_FATAL;
2077 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002078 }
2079 if (u > global.nbproc) {
2080 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2081 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002082 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002083 }
2084 set |= 1 << (u - 1);
2085 }
2086 cur_arg++;
2087 }
2088 curproxy->bind_proc = set;
2089 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002090 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002091 if (curproxy == &defproxy) {
2092 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002093 err_code |= ERR_ALERT | ERR_FATAL;
2094 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002095 }
2096
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002097 err = invalid_char(args[1]);
2098 if (err) {
2099 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2100 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002101 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002102 }
2103
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002104 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2105 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2106 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002107 err_code |= ERR_ALERT | ERR_FATAL;
2108 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002109 }
2110 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2112 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002113
Willy Tarreau977b8e42006-12-29 14:19:17 +01002114 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002115 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002116
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 if (*(args[1]) == 0) {
2118 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2119 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002122 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002123
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002124 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002125 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002126 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002127 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002128 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002129 curproxy->cookie_name = strdup(args[1]);
2130 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002131
Willy Tarreaubaaee002006-06-26 02:48:02 +02002132 cur_arg = 2;
2133 while (*(args[cur_arg])) {
2134 if (!strcmp(args[cur_arg], "rewrite")) {
2135 curproxy->options |= PR_O_COOK_RW;
2136 }
2137 else if (!strcmp(args[cur_arg], "indirect")) {
2138 curproxy->options |= PR_O_COOK_IND;
2139 }
2140 else if (!strcmp(args[cur_arg], "insert")) {
2141 curproxy->options |= PR_O_COOK_INS;
2142 }
2143 else if (!strcmp(args[cur_arg], "nocache")) {
2144 curproxy->options |= PR_O_COOK_NOC;
2145 }
2146 else if (!strcmp(args[cur_arg], "postonly")) {
2147 curproxy->options |= PR_O_COOK_POST;
2148 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002149 else if (!strcmp(args[cur_arg], "preserve")) {
2150 curproxy->options2 |= PR_O2_COOK_PSV;
2151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002152 else if (!strcmp(args[cur_arg], "prefix")) {
2153 curproxy->options |= PR_O_COOK_PFX;
2154 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002155 else if (!strcmp(args[cur_arg], "domain")) {
2156 if (!*args[cur_arg + 1]) {
2157 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2158 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002159 err_code |= ERR_ALERT | ERR_FATAL;
2160 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002161 }
2162
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002163 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002164 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002165 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2166 " dots nor does not start with a dot."
2167 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002168 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002169 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002170 }
2171
2172 err = invalid_domainchar(args[cur_arg + 1]);
2173 if (err) {
2174 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2175 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002178 }
2179
Willy Tarreau68a897b2009-12-03 23:28:34 +01002180 if (!curproxy->cookie_domain) {
2181 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2182 } else {
2183 /* one domain was already specified, add another one by
2184 * building the string which will be returned along with
2185 * the cookie.
2186 */
2187 char *new_ptr;
2188 int new_len = strlen(curproxy->cookie_domain) +
2189 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2190 new_ptr = malloc(new_len);
2191 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2192 free(curproxy->cookie_domain);
2193 curproxy->cookie_domain = new_ptr;
2194 }
Willy Tarreau31936852010-10-06 16:59:56 +02002195 cur_arg++;
2196 }
2197 else if (!strcmp(args[cur_arg], "maxidle")) {
2198 unsigned int maxidle;
2199 const char *res;
2200
2201 if (!*args[cur_arg + 1]) {
2202 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2203 file, linenum, args[cur_arg]);
2204 err_code |= ERR_ALERT | ERR_FATAL;
2205 goto out;
2206 }
2207
2208 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2209 if (res) {
2210 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2211 file, linenum, *res, args[cur_arg]);
2212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
2214 }
2215 curproxy->cookie_maxidle = maxidle;
2216 cur_arg++;
2217 }
2218 else if (!strcmp(args[cur_arg], "maxlife")) {
2219 unsigned int maxlife;
2220 const char *res;
2221
2222 if (!*args[cur_arg + 1]) {
2223 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2224 file, linenum, args[cur_arg]);
2225 err_code |= ERR_ALERT | ERR_FATAL;
2226 goto out;
2227 }
2228
2229 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2230 if (res) {
2231 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2232 file, linenum, *res, args[cur_arg]);
2233 err_code |= ERR_ALERT | ERR_FATAL;
2234 goto out;
2235 }
2236 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002237 cur_arg++;
2238 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002239 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002240 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002244 }
2245 cur_arg++;
2246 }
2247 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2248 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2249 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002250 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 }
2252
2253 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2254 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2255 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002256 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002258
2259 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2260 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2261 file, linenum);
2262 err_code |= ERR_ALERT | ERR_FATAL;
2263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002265 else if (!strcmp(args[0], "persist")) { /* persist */
2266 if (*(args[1]) == 0) {
2267 Alert("parsing [%s:%d] : missing persist method.\n",
2268 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002271 }
2272
2273 if (!strncmp(args[1], "rdp-cookie", 10)) {
2274 curproxy->options2 |= PR_O2_RDPC_PRST;
2275
Emeric Brunb982a3d2010-01-04 15:45:53 +01002276 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002277 const char *beg, *end;
2278
2279 beg = args[1] + 11;
2280 end = strchr(beg, ')');
2281
2282 if (!end || end == beg) {
2283 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2284 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002285 err_code |= ERR_ALERT | ERR_FATAL;
2286 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002287 }
2288
2289 free(curproxy->rdp_cookie_name);
2290 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2291 curproxy->rdp_cookie_len = end-beg;
2292 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002293 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002294 free(curproxy->rdp_cookie_name);
2295 curproxy->rdp_cookie_name = strdup("msts");
2296 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2297 }
2298 else { /* syntax */
2299 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2300 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002303 }
2304 }
2305 else {
2306 Alert("parsing [%s:%d] : unknown persist method.\n",
2307 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002308 err_code |= ERR_ALERT | ERR_FATAL;
2309 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002310 }
2311 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002313 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002314
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002315 if (curproxy == &defproxy) {
2316 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2317 err_code |= ERR_ALERT | ERR_FATAL;
2318 goto out;
2319 }
2320
Willy Tarreau977b8e42006-12-29 14:19:17 +01002321 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002322 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002323
Willy Tarreaubaaee002006-06-26 02:48:02 +02002324 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002325 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002327 err_code |= ERR_ALERT | ERR_FATAL;
2328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002329 }
2330 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002331 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002332 curproxy->appsession_name = strdup(args[1]);
2333 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2334 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002335 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2336 if (err) {
2337 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2338 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002341 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002342 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002343
Willy Tarreau51041c72007-09-09 21:56:53 +02002344 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2345 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002346 err_code |= ERR_ALERT | ERR_ABORT;
2347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002348 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002349
2350 cur_arg = 6;
2351 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002352 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2353 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002354 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002355 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002356 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002357 } else if (!strcmp(args[cur_arg], "prefix")) {
2358 curproxy->options2 |= PR_O2_AS_PFX;
2359 } else if (!strcmp(args[cur_arg], "mode")) {
2360 if (!*args[cur_arg + 1]) {
2361 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2362 file, linenum, args[0], args[cur_arg]);
2363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
2365 }
2366
2367 cur_arg++;
2368 if (!strcmp(args[cur_arg], "query-string")) {
2369 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2370 curproxy->options2 |= PR_O2_AS_M_QS;
2371 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2372 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2373 curproxy->options2 |= PR_O2_AS_M_PP;
2374 } else {
2375 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
2378 }
2379 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002380 cur_arg++;
2381 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002382 } /* Url App Session */
2383 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002384 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002385 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002386
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002388 if (curproxy == &defproxy) {
2389 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2390 err_code |= ERR_ALERT | ERR_FATAL;
2391 goto out;
2392 }
2393
Willy Tarreaubaaee002006-06-26 02:48:02 +02002394 if (*(args[4]) == 0) {
2395 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2396 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002400 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 curproxy->capture_name = strdup(args[2]);
2402 curproxy->capture_namelen = strlen(curproxy->capture_name);
2403 curproxy->capture_len = atol(args[4]);
2404 if (curproxy->capture_len >= CAPTURE_LEN) {
2405 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2406 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002407 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 curproxy->capture_len = CAPTURE_LEN - 1;
2409 }
2410 curproxy->to_log |= LW_COOKIE;
2411 }
2412 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2413 struct cap_hdr *hdr;
2414
2415 if (curproxy == &defproxy) {
2416 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 }
2420
2421 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2422 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2423 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 }
2427
2428 hdr = calloc(sizeof(struct cap_hdr), 1);
2429 hdr->next = curproxy->req_cap;
2430 hdr->name = strdup(args[3]);
2431 hdr->namelen = strlen(args[3]);
2432 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002433 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 hdr->index = curproxy->nb_req_cap++;
2435 curproxy->req_cap = hdr;
2436 curproxy->to_log |= LW_REQHDR;
2437 }
2438 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2439 struct cap_hdr *hdr;
2440
2441 if (curproxy == &defproxy) {
2442 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445 }
2446
2447 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2448 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2449 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002450 err_code |= ERR_ALERT | ERR_FATAL;
2451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 }
2453 hdr = calloc(sizeof(struct cap_hdr), 1);
2454 hdr->next = curproxy->rsp_cap;
2455 hdr->name = strdup(args[3]);
2456 hdr->namelen = strlen(args[3]);
2457 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002458 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002459 hdr->index = curproxy->nb_rsp_cap++;
2460 curproxy->rsp_cap = hdr;
2461 curproxy->to_log |= LW_RSPHDR;
2462 }
2463 else {
2464 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2465 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 }
2469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002471 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002472 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002473
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 if (*(args[1]) == 0) {
2475 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2476 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002479 }
2480 curproxy->conn_retries = atol(args[1]);
2481 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002482 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002483 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002484
2485 if (curproxy == &defproxy) {
2486 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
2489 }
2490
Willy Tarreauff011f22011-01-06 17:51:27 +01002491 if (!LIST_ISEMPTY(&curproxy->http_req_rules) && !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002492 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2493 file, linenum, args[0]);
2494 err_code |= ERR_WARN;
2495 }
2496
Willy Tarreauff011f22011-01-06 17:51:27 +01002497 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002498
Willy Tarreauff011f22011-01-06 17:51:27 +01002499 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002500 err_code |= ERR_ALERT | ERR_ABORT;
2501 goto out;
2502 }
2503
Willy Tarreauff011f22011-01-06 17:51:27 +01002504 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2505 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002506 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002507 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2508 /* set the header name and length into the proxy structure */
2509 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2510 err_code |= ERR_WARN;
2511
2512 if (!*args[1]) {
2513 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2514 file, linenum, args[0]);
2515 err_code |= ERR_ALERT | ERR_FATAL;
2516 goto out;
2517 }
2518
2519 /* set the desired header name */
2520 free(curproxy->server_id_hdr_name);
2521 curproxy->server_id_hdr_name = strdup(args[1]);
2522 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2523 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002524 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002525 if (curproxy == &defproxy) {
2526 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002527 err_code |= ERR_ALERT | ERR_FATAL;
2528 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002529 }
2530
Willy Tarreauef6494c2010-01-28 17:12:36 +01002531 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002532 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2533 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002534 err_code |= ERR_ALERT | ERR_FATAL;
2535 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002536 }
2537
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002538 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2539 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2540 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002541 err_code |= ERR_ALERT | ERR_FATAL;
2542 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002543 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002544
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002545 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002546 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002547 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002548 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002549 struct redirect_rule *rule;
2550 int cur_arg;
2551 int type = REDIRECT_TYPE_NONE;
2552 int code = 302;
2553 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002554 char *cookie = NULL;
2555 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002556 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002557
Cyril Bonté99ed3272010-01-24 23:29:44 +01002558 if (curproxy == &defproxy) {
2559 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
2562 }
2563
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002564 cur_arg = 1;
2565 while (*(args[cur_arg])) {
2566 if (!strcmp(args[cur_arg], "location")) {
2567 if (!*args[cur_arg + 1]) {
2568 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2569 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_ALERT | ERR_FATAL;
2571 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002572 }
2573
2574 type = REDIRECT_TYPE_LOCATION;
2575 cur_arg++;
2576 destination = args[cur_arg];
2577 }
2578 else if (!strcmp(args[cur_arg], "prefix")) {
2579 if (!*args[cur_arg + 1]) {
2580 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2581 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002582 err_code |= ERR_ALERT | ERR_FATAL;
2583 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002584 }
2585
2586 type = REDIRECT_TYPE_PREFIX;
2587 cur_arg++;
2588 destination = args[cur_arg];
2589 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002590 else if (!strcmp(args[cur_arg], "set-cookie")) {
2591 if (!*args[cur_arg + 1]) {
2592 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2593 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002596 }
2597
2598 cur_arg++;
2599 cookie = args[cur_arg];
2600 cookie_set = 1;
2601 }
2602 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2603 if (!*args[cur_arg + 1]) {
2604 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2605 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002606 err_code |= ERR_ALERT | ERR_FATAL;
2607 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002608 }
2609
2610 cur_arg++;
2611 cookie = args[cur_arg];
2612 cookie_set = 0;
2613 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002614 else if (!strcmp(args[cur_arg],"code")) {
2615 if (!*args[cur_arg + 1]) {
2616 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2617 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002618 err_code |= ERR_ALERT | ERR_FATAL;
2619 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002620 }
2621 cur_arg++;
2622 code = atol(args[cur_arg]);
2623 if (code < 301 || code > 303) {
2624 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2625 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002628 }
2629 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002630 else if (!strcmp(args[cur_arg],"drop-query")) {
2631 flags |= REDIRECT_FLAG_DROP_QS;
2632 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002633 else if (!strcmp(args[cur_arg],"append-slash")) {
2634 flags |= REDIRECT_FLAG_APPEND_SLASH;
2635 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002636 else if (strcmp(args[cur_arg], "if") == 0 ||
2637 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002638 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002639 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002640 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2641 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
2644 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002645 break;
2646 }
2647 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002648 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002649 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002652 }
2653 cur_arg++;
2654 }
2655
2656 if (type == REDIRECT_TYPE_NONE) {
2657 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2658 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002659 err_code |= ERR_ALERT | ERR_FATAL;
2660 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002661 }
2662
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002663 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2664 rule->cond = cond;
2665 rule->rdr_str = strdup(destination);
2666 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002667 if (cookie) {
2668 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002669 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002670 */
2671 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002672 if (cookie_set) {
2673 rule->cookie_str = malloc(rule->cookie_len + 10);
2674 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2675 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2676 rule->cookie_len += 9;
2677 } else {
2678 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002679 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002680 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2681 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002682 }
2683 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002684 rule->type = type;
2685 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002686 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002687 LIST_INIT(&rule->list);
2688 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002689 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2690 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002691 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002692 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002693 struct switching_rule *rule;
2694
Willy Tarreaub099aca2008-10-12 17:26:37 +02002695 if (curproxy == &defproxy) {
2696 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002699 }
2700
Willy Tarreau55ea7572007-06-17 19:56:27 +02002701 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002702 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002703
2704 if (*(args[1]) == 0) {
2705 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002708 }
2709
Willy Tarreauef6494c2010-01-28 17:12:36 +01002710 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002711 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2712 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002715 }
2716
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002717 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2718 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2719 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002720 err_code |= ERR_ALERT | ERR_FATAL;
2721 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002722 }
2723
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002724 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002725
Willy Tarreau55ea7572007-06-17 19:56:27 +02002726 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2727 rule->cond = cond;
2728 rule->be.name = strdup(args[1]);
2729 LIST_INIT(&rule->list);
2730 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2731 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002732 else if (strcmp(args[0], "use-server") == 0) {
2733 struct server_rule *rule;
2734
2735 if (curproxy == &defproxy) {
2736 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2737 err_code |= ERR_ALERT | ERR_FATAL;
2738 goto out;
2739 }
2740
2741 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2742 err_code |= ERR_WARN;
2743
2744 if (*(args[1]) == 0) {
2745 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2746 err_code |= ERR_ALERT | ERR_FATAL;
2747 goto out;
2748 }
2749
2750 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2751 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2752 file, linenum, args[0]);
2753 err_code |= ERR_ALERT | ERR_FATAL;
2754 goto out;
2755 }
2756
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002757 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2758 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2759 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002760 err_code |= ERR_ALERT | ERR_FATAL;
2761 goto out;
2762 }
2763
2764 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2765
2766 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2767 rule->cond = cond;
2768 rule->srv.name = strdup(args[1]);
2769 LIST_INIT(&rule->list);
2770 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2771 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2772 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002773 else if ((!strcmp(args[0], "force-persist")) ||
2774 (!strcmp(args[0], "ignore-persist"))) {
2775 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002776
2777 if (curproxy == &defproxy) {
2778 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2779 err_code |= ERR_ALERT | ERR_FATAL;
2780 goto out;
2781 }
2782
2783 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2784 err_code |= ERR_WARN;
2785
Willy Tarreauef6494c2010-01-28 17:12:36 +01002786 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002787 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2788 file, linenum, args[0]);
2789 err_code |= ERR_ALERT | ERR_FATAL;
2790 goto out;
2791 }
2792
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002793 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2794 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2795 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002796 err_code |= ERR_ALERT | ERR_FATAL;
2797 goto out;
2798 }
2799
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002800 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002801
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002802 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002803 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002804 if (!strcmp(args[0], "force-persist")) {
2805 rule->type = PERSIST_TYPE_FORCE;
2806 } else {
2807 rule->type = PERSIST_TYPE_IGNORE;
2808 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002809 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002810 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002811 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002812 else if (!strcmp(args[0], "stick-table")) {
2813 int myidx = 1;
2814
Emeric Brun32da3c42010-09-23 18:39:19 +02002815 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002816 curproxy->table.type = (unsigned int)-1;
2817 while (*args[myidx]) {
2818 const char *err;
2819
2820 if (strcmp(args[myidx], "size") == 0) {
2821 myidx++;
2822 if (!*(args[myidx])) {
2823 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2824 file, linenum, args[myidx-1]);
2825 err_code |= ERR_ALERT | ERR_FATAL;
2826 goto out;
2827 }
2828 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2829 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2830 file, linenum, *err, args[myidx-1]);
2831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
2833 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002834 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002835 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002836 else if (strcmp(args[myidx], "peers") == 0) {
2837 myidx++;
2838 if (!*(args[myidx])) {
2839 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2840 file, linenum, args[myidx-1]);
2841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
2843 }
2844 curproxy->table.peers.name = strdup(args[myidx++]);
2845 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002846 else if (strcmp(args[myidx], "expire") == 0) {
2847 myidx++;
2848 if (!*(args[myidx])) {
2849 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2850 file, linenum, args[myidx-1]);
2851 err_code |= ERR_ALERT | ERR_FATAL;
2852 goto out;
2853 }
2854 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2855 if (err) {
2856 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2857 file, linenum, *err, args[myidx-1]);
2858 err_code |= ERR_ALERT | ERR_FATAL;
2859 goto out;
2860 }
2861 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002862 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002863 }
2864 else if (strcmp(args[myidx], "nopurge") == 0) {
2865 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002866 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002867 }
2868 else if (strcmp(args[myidx], "type") == 0) {
2869 myidx++;
2870 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2871 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2872 file, linenum, args[myidx]);
2873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
2875 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002876 /* myidx already points to next arg */
2877 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002878 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002879 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002880 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002881
2882 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002883 nw = args[myidx];
2884 while (*nw) {
2885 /* the "store" keyword supports a comma-separated list */
2886 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002887 sa = NULL; /* store arg */
2888 while (*nw && *nw != ',') {
2889 if (*nw == '(') {
2890 *nw = 0;
2891 sa = ++nw;
2892 while (*nw != ')') {
2893 if (!*nw) {
2894 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2895 file, linenum, args[0], cw);
2896 err_code |= ERR_ALERT | ERR_FATAL;
2897 goto out;
2898 }
2899 nw++;
2900 }
2901 *nw = '\0';
2902 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002903 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002904 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002905 if (*nw)
2906 *nw++ = '\0';
2907 type = stktable_get_data_type(cw);
2908 if (type < 0) {
2909 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2910 file, linenum, args[0], cw);
2911 err_code |= ERR_ALERT | ERR_FATAL;
2912 goto out;
2913 }
Willy Tarreauac782882010-06-20 10:41:54 +02002914
2915 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2916 switch (err) {
2917 case PE_NONE: break;
2918 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002919 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2920 file, linenum, args[0], cw);
2921 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002922 break;
2923
2924 case PE_ARG_MISSING:
2925 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2926 file, linenum, args[0], cw);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
2929
2930 case PE_ARG_NOT_USED:
2931 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2932 file, linenum, args[0], cw);
2933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
2935
2936 default:
2937 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2938 file, linenum, args[0], cw);
2939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002941 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002942 }
2943 myidx++;
2944 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002945 else {
2946 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2947 file, linenum, args[myidx]);
2948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002950 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002951 }
2952
2953 if (!curproxy->table.size) {
2954 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2955 file, linenum);
2956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
2958 }
2959
2960 if (curproxy->table.type == (unsigned int)-1) {
2961 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2962 file, linenum);
2963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
2965 }
2966 }
2967 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002968 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002969 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002970 int myidx = 0;
2971 const char *name = NULL;
2972 int flags;
2973
2974 if (curproxy == &defproxy) {
2975 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
2978 }
2979
2980 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2981 err_code |= ERR_WARN;
2982 goto out;
2983 }
2984
2985 myidx++;
2986 if ((strcmp(args[myidx], "store") == 0) ||
2987 (strcmp(args[myidx], "store-request") == 0)) {
2988 myidx++;
2989 flags = STK_IS_STORE;
2990 }
2991 else if (strcmp(args[myidx], "store-response") == 0) {
2992 myidx++;
2993 flags = STK_IS_STORE | STK_ON_RSP;
2994 }
2995 else if (strcmp(args[myidx], "match") == 0) {
2996 myidx++;
2997 flags = STK_IS_MATCH;
2998 }
2999 else if (strcmp(args[myidx], "on") == 0) {
3000 myidx++;
3001 flags = STK_IS_MATCH | STK_IS_STORE;
3002 }
3003 else {
3004 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3005 err_code |= ERR_ALERT | ERR_FATAL;
3006 goto out;
3007 }
3008
3009 if (*(args[myidx]) == 0) {
3010 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
3013 }
3014
Willy Tarreau12785782012-04-27 21:37:17 +02003015 expr = sample_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003016 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003017 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
3020 }
3021
3022 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003023 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003024 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3025 file, linenum, args[0], expr->fetch->kw);
3026 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003027 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003028 goto out;
3029 }
3030 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003031 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003032 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3033 file, linenum, args[0], expr->fetch->kw);
3034 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003035 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003036 goto out;
3037 }
3038 }
3039
3040 if (strcmp(args[myidx], "table") == 0) {
3041 myidx++;
3042 name = args[myidx++];
3043 }
3044
Willy Tarreauef6494c2010-01-28 17:12:36 +01003045 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003046 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3047 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3048 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003049 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003050 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003051 goto out;
3052 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003053 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003054 else if (*(args[myidx])) {
3055 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3056 file, linenum, args[0], args[myidx]);
3057 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003058 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003059 goto out;
3060 }
Emeric Brun97679e72010-09-23 17:56:44 +02003061 if (flags & STK_ON_RSP)
3062 err_code |= warnif_cond_requires_req(cond, file, linenum);
3063 else
3064 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003065
Emeric Brunb982a3d2010-01-04 15:45:53 +01003066 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3067 rule->cond = cond;
3068 rule->expr = expr;
3069 rule->flags = flags;
3070 rule->table.name = name ? strdup(name) : NULL;
3071 LIST_INIT(&rule->list);
3072 if (flags & STK_ON_RSP)
3073 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3074 else
3075 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3076 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003078 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003079 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003080
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3082 curproxy->uri_auth = NULL; /* we must detach from the default config */
3083
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003084 if (!*args[1]) {
3085 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003086 } else if (!strcmp(args[1], "admin")) {
3087 struct stats_admin_rule *rule;
3088
3089 if (curproxy == &defproxy) {
3090 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
3093 }
3094
3095 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3096 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3097 err_code |= ERR_ALERT | ERR_ABORT;
3098 goto out;
3099 }
3100
3101 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3102 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3103 file, linenum, args[0], args[1]);
3104 err_code |= ERR_ALERT | ERR_FATAL;
3105 goto out;
3106 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003107 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3108 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3109 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
3113
3114 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3115
3116 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3117 rule->cond = cond;
3118 LIST_INIT(&rule->list);
3119 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 } else if (!strcmp(args[1], "uri")) {
3121 if (*(args[2]) == 0) {
3122 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3126 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003127 err_code |= ERR_ALERT | ERR_ABORT;
3128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 }
3130 } else if (!strcmp(args[1], "realm")) {
3131 if (*(args[2]) == 0) {
3132 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003133 err_code |= ERR_ALERT | ERR_FATAL;
3134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3136 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003137 err_code |= ERR_ALERT | ERR_ABORT;
3138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003140 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003141 unsigned interval;
3142
3143 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3144 if (err) {
3145 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3146 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003147 err_code |= ERR_ALERT | ERR_FATAL;
3148 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003149 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3150 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003151 err_code |= ERR_ALERT | ERR_ABORT;
3152 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003153 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003154 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003155 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003156
3157 if (curproxy == &defproxy) {
3158 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3159 err_code |= ERR_ALERT | ERR_FATAL;
3160 goto out;
3161 }
3162
3163 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3164 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3165 err_code |= ERR_ALERT | ERR_ABORT;
3166 goto out;
3167 }
3168
Willy Tarreauff011f22011-01-06 17:51:27 +01003169 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3170 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003171 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3172 file, linenum, args[0]);
3173 err_code |= ERR_WARN;
3174 }
3175
Willy Tarreauff011f22011-01-06 17:51:27 +01003176 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003177
Willy Tarreauff011f22011-01-06 17:51:27 +01003178 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003179 err_code |= ERR_ALERT | ERR_ABORT;
3180 goto out;
3181 }
3182
Willy Tarreauff011f22011-01-06 17:51:27 +01003183 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3184 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003185
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 } else if (!strcmp(args[1], "auth")) {
3187 if (*(args[2]) == 0) {
3188 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3192 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003193 err_code |= ERR_ALERT | ERR_ABORT;
3194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 }
3196 } else if (!strcmp(args[1], "scope")) {
3197 if (*(args[2]) == 0) {
3198 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3202 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003203 err_code |= ERR_ALERT | ERR_ABORT;
3204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003205 }
3206 } else if (!strcmp(args[1], "enable")) {
3207 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3208 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003209 err_code |= ERR_ALERT | ERR_ABORT;
3210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003212 } else if (!strcmp(args[1], "hide-version")) {
3213 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3214 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003215 err_code |= ERR_ALERT | ERR_ABORT;
3216 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003217 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003218 } else if (!strcmp(args[1], "show-legends")) {
3219 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3220 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3221 err_code |= ERR_ALERT | ERR_ABORT;
3222 goto out;
3223 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003224 } else if (!strcmp(args[1], "show-node")) {
3225
3226 if (*args[2]) {
3227 int i;
3228 char c;
3229
3230 for (i=0; args[2][i]; i++) {
3231 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003232 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3233 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003234 break;
3235 }
3236
3237 if (!i || args[2][i]) {
3238 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3239 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3240 file, linenum, args[0], args[1]);
3241 err_code |= ERR_ALERT | ERR_FATAL;
3242 goto out;
3243 }
3244 }
3245
3246 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3247 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3248 err_code |= ERR_ALERT | ERR_ABORT;
3249 goto out;
3250 }
3251 } else if (!strcmp(args[1], "show-desc")) {
3252 char *desc = NULL;
3253
3254 if (*args[2]) {
3255 int i, len=0;
3256 char *d;
3257
3258 for(i=2; *args[i]; i++)
3259 len += strlen(args[i])+1;
3260
3261 desc = d = (char *)calloc(1, len);
3262
3263 d += sprintf(d, "%s", args[2]);
3264 for(i=3; *args[i]; i++)
3265 d += sprintf(d, " %s", args[i]);
3266 }
3267
3268 if (!*args[2] && !global.desc)
3269 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3270 file, linenum, args[1]);
3271 else {
3272 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3273 free(desc);
3274 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3275 err_code |= ERR_ALERT | ERR_ABORT;
3276 goto out;
3277 }
3278 free(desc);
3279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003280 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003281stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003282 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003283 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003284 err_code |= ERR_ALERT | ERR_FATAL;
3285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 }
3287 }
3288 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003289 int optnum;
3290
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003291 if (*(args[1]) == '\0') {
3292 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3293 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003297
3298 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3299 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003300 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3301 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3302 file, linenum, cfg_opts[optnum].name);
3303 err_code |= ERR_ALERT | ERR_FATAL;
3304 goto out;
3305 }
Willy Tarreau93893792009-07-23 13:19:11 +02003306 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3307 err_code |= ERR_WARN;
3308 goto out;
3309 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003310
Willy Tarreau3842f002009-06-14 11:39:52 +02003311 curproxy->no_options &= ~cfg_opts[optnum].val;
3312 curproxy->options &= ~cfg_opts[optnum].val;
3313
3314 switch (kwm) {
3315 case KWM_STD:
3316 curproxy->options |= cfg_opts[optnum].val;
3317 break;
3318 case KWM_NO:
3319 curproxy->no_options |= cfg_opts[optnum].val;
3320 break;
3321 case KWM_DEF: /* already cleared */
3322 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003323 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003324
Willy Tarreau93893792009-07-23 13:19:11 +02003325 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003326 }
3327 }
3328
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003329 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3330 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003331 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3332 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3333 file, linenum, cfg_opts2[optnum].name);
3334 err_code |= ERR_ALERT | ERR_FATAL;
3335 goto out;
3336 }
Willy Tarreau93893792009-07-23 13:19:11 +02003337 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3338 err_code |= ERR_WARN;
3339 goto out;
3340 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003341
Willy Tarreau3842f002009-06-14 11:39:52 +02003342 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3343 curproxy->options2 &= ~cfg_opts2[optnum].val;
3344
3345 switch (kwm) {
3346 case KWM_STD:
3347 curproxy->options2 |= cfg_opts2[optnum].val;
3348 break;
3349 case KWM_NO:
3350 curproxy->no_options2 |= cfg_opts2[optnum].val;
3351 break;
3352 case KWM_DEF: /* already cleared */
3353 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003354 }
Willy Tarreau93893792009-07-23 13:19:11 +02003355 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003356 }
3357 }
3358
Willy Tarreau3842f002009-06-14 11:39:52 +02003359 if (kwm != KWM_STD) {
3360 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003361 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003362 err_code |= ERR_ALERT | ERR_FATAL;
3363 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003364 }
3365
Emeric Brun3a058f32009-06-30 18:26:00 +02003366 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003367 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003368 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003369 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003370 if (*(args[2]) != '\0') {
3371 if (!strcmp(args[2], "clf")) {
3372 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003373 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003374 } else {
3375 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003376 err_code |= ERR_ALERT | ERR_FATAL;
3377 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003378 }
3379 }
William Lallemand1d705562012-03-12 12:46:41 +01003380 parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode);
Emeric Brun3a058f32009-06-30 18:26:00 +02003381 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003382 else if (!strcmp(args[1], "tcplog")) {
3383 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 /* generate a detailed TCP log */
William Lallemandbddd4fd2012-02-27 11:23:10 +01003385 logformat = default_tcp_log_format;
William Lallemand1d705562012-03-12 12:46:41 +01003386 parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode);
William Lallemandbddd4fd2012-02-27 11:23:10 +01003387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003388 else if (!strcmp(args[1], "tcpka")) {
3389 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003390 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003391 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003392
3393 if (curproxy->cap & PR_CAP_FE)
3394 curproxy->options |= PR_O_TCP_CLI_KA;
3395 if (curproxy->cap & PR_CAP_BE)
3396 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397 }
3398 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003399 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_WARN;
3401
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003403 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003404 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003405 curproxy->options2 &= ~PR_O2_CHK_ANY;
3406 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003407 if (!*args[2]) { /* no argument */
3408 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3409 curproxy->check_len = strlen(DEF_CHECK_REQ);
3410 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003411 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 curproxy->check_req = (char *)malloc(reqlen);
3413 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003414 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003415 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003416 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003417 if (*args[4])
3418 reqlen += strlen(args[4]);
3419 else
3420 reqlen += strlen("HTTP/1.0");
3421
3422 curproxy->check_req = (char *)malloc(reqlen);
3423 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003424 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003425 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003426 }
3427 else if (!strcmp(args[1], "ssl-hello-chk")) {
3428 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003429 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003430 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003431
Willy Tarreaua534fea2008-08-03 12:19:50 +02003432 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003433 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003434 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003435 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003436 }
Willy Tarreau23677902007-05-08 23:50:35 +02003437 else if (!strcmp(args[1], "smtpchk")) {
3438 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003439 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003440 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003441 curproxy->options2 &= ~PR_O2_CHK_ANY;
3442 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003443
3444 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3445 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3446 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3447 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3448 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3449 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3450 curproxy->check_req = (char *)malloc(reqlen);
3451 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3452 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3453 } else {
3454 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3455 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3456 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3457 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3458 }
3459 }
3460 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003461 else if (!strcmp(args[1], "pgsql-check")) {
3462 /* use PostgreSQL request to check servers' health */
3463 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3464 err_code |= ERR_WARN;
3465
3466 free(curproxy->check_req);
3467 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003468 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003469 curproxy->options2 |= PR_O2_PGSQL_CHK;
3470
3471 if (*(args[2])) {
3472 int cur_arg = 2;
3473
3474 while (*(args[cur_arg])) {
3475 if (strcmp(args[cur_arg], "user") == 0) {
3476 char * packet;
3477 uint32_t packet_len;
3478 uint32_t pv;
3479
3480 /* suboption header - needs additional argument for it */
3481 if (*(args[cur_arg+1]) == 0) {
3482 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3483 file, linenum, args[0], args[1], args[cur_arg]);
3484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
3486 }
3487
3488 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3489 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3490 pv = htonl(0x30000); /* protocol version 3.0 */
3491
3492 packet = (char*) calloc(1, packet_len);
3493
3494 memcpy(packet + 4, &pv, 4);
3495
3496 /* copy "user" */
3497 memcpy(packet + 8, "user", 4);
3498
3499 /* copy username */
3500 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3501
3502 free(curproxy->check_req);
3503 curproxy->check_req = packet;
3504 curproxy->check_len = packet_len;
3505
3506 packet_len = htonl(packet_len);
3507 memcpy(packet, &packet_len, 4);
3508 cur_arg += 2;
3509 } else {
3510 /* unknown suboption - catchall */
3511 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3512 file, linenum, args[0], args[1]);
3513 err_code |= ERR_ALERT | ERR_FATAL;
3514 goto out;
3515 }
3516 } /* end while loop */
3517 }
3518 }
3519
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003520 else if (!strcmp(args[1], "redis-check")) {
3521 /* use REDIS PING request to check servers' health */
3522 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3523 err_code |= ERR_WARN;
3524
3525 free(curproxy->check_req);
3526 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003527 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003528 curproxy->options2 |= PR_O2_REDIS_CHK;
3529
3530 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3531 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3532 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3533 }
3534
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003535 else if (!strcmp(args[1], "mysql-check")) {
3536 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003537 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3538 err_code |= ERR_WARN;
3539
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003540 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003541 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003542 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003543 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003544
3545 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3546 * const char mysql40_client_auth_pkt[] = {
3547 * "\x0e\x00\x00" // packet length
3548 * "\x01" // packet number
3549 * "\x00\x00" // client capabilities
3550 * "\x00\x00\x01" // max packet
3551 * "haproxy\x00" // username (null terminated string)
3552 * "\x00" // filler (always 0x00)
3553 * "\x01\x00\x00" // packet length
3554 * "\x00" // packet number
3555 * "\x01" // COM_QUIT command
3556 * };
3557 */
3558
3559 if (*(args[2])) {
3560 int cur_arg = 2;
3561
3562 while (*(args[cur_arg])) {
3563 if (strcmp(args[cur_arg], "user") == 0) {
3564 char *mysqluser;
3565 int packetlen, reqlen, userlen;
3566
3567 /* suboption header - needs additional argument for it */
3568 if (*(args[cur_arg+1]) == 0) {
3569 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3570 file, linenum, args[0], args[1], args[cur_arg]);
3571 err_code |= ERR_ALERT | ERR_FATAL;
3572 goto out;
3573 }
3574 mysqluser = args[cur_arg + 1];
3575 userlen = strlen(mysqluser);
3576 packetlen = userlen + 7;
3577 reqlen = packetlen + 9;
3578
3579 free(curproxy->check_req);
3580 curproxy->check_req = (char *)calloc(1, reqlen);
3581 curproxy->check_len = reqlen;
3582
3583 snprintf(curproxy->check_req, 4, "%c%c%c",
3584 ((unsigned char) packetlen & 0xff),
3585 ((unsigned char) (packetlen >> 8) & 0xff),
3586 ((unsigned char) (packetlen >> 16) & 0xff));
3587
3588 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003589 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003590 curproxy->check_req[8] = 1;
3591 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3592 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3593 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3594 cur_arg += 2;
3595 } else {
3596 /* unknown suboption - catchall */
3597 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3598 file, linenum, args[0], args[1]);
3599 err_code |= ERR_ALERT | ERR_FATAL;
3600 goto out;
3601 }
3602 } /* end while loop */
3603 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003604 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003605 else if (!strcmp(args[1], "ldap-check")) {
3606 /* use LDAP request to check servers' health */
3607 free(curproxy->check_req);
3608 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003609 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003610 curproxy->options2 |= PR_O2_LDAP_CHK;
3611
3612 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3613 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3614 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3615 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003616 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003617 int cur_arg;
3618
3619 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3620 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003621 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003622
Willy Tarreau87cf5142011-08-19 22:57:24 +02003623 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003624
3625 free(curproxy->fwdfor_hdr_name);
3626 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3627 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3628
3629 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3630 cur_arg = 2;
3631 while (*(args[cur_arg])) {
3632 if (!strcmp(args[cur_arg], "except")) {
3633 /* suboption except - needs additional argument for it */
3634 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3635 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3636 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_ALERT | ERR_FATAL;
3638 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003639 }
3640 /* flush useless bits */
3641 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003642 cur_arg += 2;
3643 } else if (!strcmp(args[cur_arg], "header")) {
3644 /* suboption header - needs additional argument for it */
3645 if (*(args[cur_arg+1]) == 0) {
3646 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3647 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003650 }
3651 free(curproxy->fwdfor_hdr_name);
3652 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3653 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3654 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003655 } else if (!strcmp(args[cur_arg], "if-none")) {
3656 curproxy->options &= ~PR_O_FF_ALWAYS;
3657 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003658 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003659 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003660 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003661 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003662 err_code |= ERR_ALERT | ERR_FATAL;
3663 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003664 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003665 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003666 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003667 else if (!strcmp(args[1], "originalto")) {
3668 int cur_arg;
3669
3670 /* insert x-original-to field, but not for the IP address listed as an except.
3671 * set default options (ie: bitfield, header name, etc)
3672 */
3673
3674 curproxy->options |= PR_O_ORGTO;
3675
3676 free(curproxy->orgto_hdr_name);
3677 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3678 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3679
Willy Tarreau87cf5142011-08-19 22:57:24 +02003680 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003681 cur_arg = 2;
3682 while (*(args[cur_arg])) {
3683 if (!strcmp(args[cur_arg], "except")) {
3684 /* suboption except - needs additional argument for it */
3685 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3686 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3687 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003688 err_code |= ERR_ALERT | ERR_FATAL;
3689 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003690 }
3691 /* flush useless bits */
3692 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3693 cur_arg += 2;
3694 } else if (!strcmp(args[cur_arg], "header")) {
3695 /* suboption header - needs additional argument for it */
3696 if (*(args[cur_arg+1]) == 0) {
3697 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3698 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_ALERT | ERR_FATAL;
3700 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003701 }
3702 free(curproxy->orgto_hdr_name);
3703 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3704 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3705 cur_arg += 2;
3706 } else {
3707 /* unknown suboption - catchall */
3708 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3709 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003710 err_code |= ERR_ALERT | ERR_FATAL;
3711 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003712 }
3713 } /* end while loop */
3714 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 else {
3716 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003717 err_code |= ERR_ALERT | ERR_FATAL;
3718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003719 }
Willy Tarreau93893792009-07-23 13:19:11 +02003720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003722 else if (!strcmp(args[0], "default_backend")) {
3723 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003724 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003725
3726 if (*(args[1]) == 0) {
3727 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003728 err_code |= ERR_ALERT | ERR_FATAL;
3729 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003730 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003731 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003732 curproxy->defbe.name = strdup(args[1]);
3733 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003734 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003735 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003737
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003738 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3739 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003741 /* enable reconnections to dispatch */
3742 curproxy->options |= PR_O_REDISP;
3743 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003744 else if (!strcmp(args[0], "http-check")) {
3745 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003746 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003747
3748 if (strcmp(args[1], "disable-on-404") == 0) {
3749 /* enable a graceful server shutdown on an HTTP 404 response */
3750 curproxy->options |= PR_O_DISABLE404;
3751 }
Willy Tarreauef781042010-01-27 11:53:01 +01003752 else if (strcmp(args[1], "send-state") == 0) {
3753 /* enable emission of the apparent state of a server in HTTP checks */
3754 curproxy->options2 |= PR_O2_CHK_SNDST;
3755 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003756 else if (strcmp(args[1], "expect") == 0) {
3757 const char *ptr_arg;
3758 int cur_arg;
3759
3760 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3761 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
3764 }
3765
3766 cur_arg = 2;
3767 /* consider exclamation marks, sole or at the beginning of a word */
3768 while (*(ptr_arg = args[cur_arg])) {
3769 while (*ptr_arg == '!') {
3770 curproxy->options2 ^= PR_O2_EXP_INV;
3771 ptr_arg++;
3772 }
3773 if (*ptr_arg)
3774 break;
3775 cur_arg++;
3776 }
3777 /* now ptr_arg points to the beginning of a word past any possible
3778 * exclamation mark, and cur_arg is the argument which holds this word.
3779 */
3780 if (strcmp(ptr_arg, "status") == 0) {
3781 if (!*(args[cur_arg + 1])) {
3782 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3783 file, linenum, args[0], args[1], ptr_arg);
3784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
3786 }
3787 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003788 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003789 curproxy->expect_str = strdup(args[cur_arg + 1]);
3790 }
3791 else if (strcmp(ptr_arg, "string") == 0) {
3792 if (!*(args[cur_arg + 1])) {
3793 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3794 file, linenum, args[0], args[1], ptr_arg);
3795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
3797 }
3798 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003799 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003800 curproxy->expect_str = strdup(args[cur_arg + 1]);
3801 }
3802 else if (strcmp(ptr_arg, "rstatus") == 0) {
3803 if (!*(args[cur_arg + 1])) {
3804 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3805 file, linenum, args[0], args[1], ptr_arg);
3806 err_code |= ERR_ALERT | ERR_FATAL;
3807 goto out;
3808 }
3809 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003810 free(curproxy->expect_str);
3811 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3812 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003813 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3814 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3815 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3816 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3817 err_code |= ERR_ALERT | ERR_FATAL;
3818 goto out;
3819 }
3820 }
3821 else if (strcmp(ptr_arg, "rstring") == 0) {
3822 if (!*(args[cur_arg + 1])) {
3823 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3824 file, linenum, args[0], args[1], ptr_arg);
3825 err_code |= ERR_ALERT | ERR_FATAL;
3826 goto out;
3827 }
3828 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003829 free(curproxy->expect_str);
3830 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3831 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003832 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3833 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3834 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3835 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
3838 }
3839 }
3840 else {
3841 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3842 file, linenum, args[0], args[1], ptr_arg);
3843 err_code |= ERR_ALERT | ERR_FATAL;
3844 goto out;
3845 }
3846 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003847 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003848 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'send-state', 'expect'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003851 }
3852 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003853 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003854 if (curproxy == &defproxy) {
3855 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003858 }
3859
Willy Tarreaub80c2302007-11-30 20:51:32 +01003860 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003862
3863 if (strcmp(args[1], "fail") == 0) {
3864 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003865 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003866 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3867 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003868 err_code |= ERR_ALERT | ERR_FATAL;
3869 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003870 }
3871
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003872 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3873 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3874 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003877 }
3878 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3879 }
3880 else {
3881 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003884 }
3885 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886#ifdef TPROXY
3887 else if (!strcmp(args[0], "transparent")) {
3888 /* enable transparent proxy connections */
3889 curproxy->options |= PR_O_TRANSP;
3890 }
3891#endif
3892 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003893 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003894 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003895
Willy Tarreaubaaee002006-06-26 02:48:02 +02003896 if (*(args[1]) == 0) {
3897 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003898 err_code |= ERR_ALERT | ERR_FATAL;
3899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003900 }
3901 curproxy->maxconn = atol(args[1]);
3902 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003903 else if (!strcmp(args[0], "backlog")) { /* backlog */
3904 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003905 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003906
3907 if (*(args[1]) == 0) {
3908 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003909 err_code |= ERR_ALERT | ERR_FATAL;
3910 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003911 }
3912 curproxy->backlog = atol(args[1]);
3913 }
Willy Tarreau86034312006-12-29 00:10:33 +01003914 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003915 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003916 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003917
Willy Tarreau86034312006-12-29 00:10:33 +01003918 if (*(args[1]) == 0) {
3919 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003920 err_code |= ERR_ALERT | ERR_FATAL;
3921 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003922 }
3923 curproxy->fullconn = atol(args[1]);
3924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003925 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3926 if (*(args[1]) == 0) {
3927 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003930 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003931 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3932 if (err) {
3933 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3934 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003937 }
3938 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003939 }
3940 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003941 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003942 if (curproxy == &defproxy) {
3943 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_ALERT | ERR_FATAL;
3945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003946 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003947 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003948 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003949
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 if (strchr(args[1], ':') == NULL) {
3951 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003952 err_code |= ERR_ALERT | ERR_FATAL;
3953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003954 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003955 sk = str2sa(args[1]);
3956 if (!sk) {
3957 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
3960 }
3961 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003962 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003963 }
3964 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003965 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003967
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003968 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3969 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003970 err_code |= ERR_ALERT | ERR_FATAL;
3971 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003972 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003973 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003974 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3975 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3976 err_code |= ERR_WARN;
3977
3978 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3979 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3980 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3981 }
3982 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3983 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3984 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3985 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003986 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3987 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3988 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3989 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003990 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003991 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
3994 }
3995 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003996 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003997 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003998 char *rport, *raddr;
3999 short realport = 0;
4000 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004001
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004002 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004003 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004004 err_code |= ERR_ALERT | ERR_FATAL;
4005 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004006 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004007 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004008 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004009
4010 if (!*args[2]) {
4011 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4012 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004013 err_code |= ERR_ALERT | ERR_FATAL;
4014 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004016
4017 err = invalid_char(args[1]);
4018 if (err) {
4019 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4020 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004023 }
4024
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004025 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004026 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004027
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004028 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4029 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4030 err_code |= ERR_ALERT | ERR_ABORT;
4031 goto out;
4032 }
4033
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004034 /* the servers are linked backwards first */
4035 newsrv->next = curproxy->srv;
4036 curproxy->srv = newsrv;
4037 newsrv->proxy = curproxy;
4038 newsrv->conf.file = file;
4039 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004040
Simon Hormanaf514952011-06-21 14:34:57 +09004041 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004042 LIST_INIT(&newsrv->pendconns);
4043 do_check = 0;
4044 newsrv->state = SRV_RUNNING; /* early server setup */
4045 newsrv->last_change = now.tv_sec;
4046 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004047
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004048 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004049 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004050 * - IP: => port=+0, relative
4051 * - IP:N => port=N, absolute
4052 * - IP:+N => port=+N, relative
4053 * - IP:-N => port=-N, relative
4054 */
4055 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004056 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004057 if (rport) {
4058 *rport++ = 0;
4059 realport = atol(rport);
4060 if (!isdigit((unsigned char)*rport))
4061 newsrv->state |= SRV_MAPPORTS;
4062 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004063 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004064
Willy Tarreaufab5a432011-03-04 15:31:53 +01004065 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004066 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004067 if (!sk) {
4068 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4069 err_code |= ERR_ALERT | ERR_FATAL;
4070 goto out;
4071 }
4072 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004073 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
4074
4075 if (!sk) {
4076 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4077 file, linenum, newsrv->addr.ss_family, args[2]);
4078 err_code |= ERR_ALERT | ERR_FATAL;
4079 goto out;
4080 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004081 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004082
4083 newsrv->check_port = curproxy->defsrv.check_port;
4084 newsrv->inter = curproxy->defsrv.inter;
4085 newsrv->fastinter = curproxy->defsrv.fastinter;
4086 newsrv->downinter = curproxy->defsrv.downinter;
4087 newsrv->rise = curproxy->defsrv.rise;
4088 newsrv->fall = curproxy->defsrv.fall;
4089 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4090 newsrv->minconn = curproxy->defsrv.minconn;
4091 newsrv->maxconn = curproxy->defsrv.maxconn;
4092 newsrv->slowstart = curproxy->defsrv.slowstart;
4093 newsrv->onerror = curproxy->defsrv.onerror;
4094 newsrv->consecutive_errors_limit
4095 = curproxy->defsrv.consecutive_errors_limit;
4096 newsrv->uweight = newsrv->iweight
4097 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004098
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004099 newsrv->curfd = -1; /* no health-check in progress */
4100 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004101
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004102 cur_arg = 3;
4103 } else {
4104 newsrv = &curproxy->defsrv;
4105 cur_arg = 1;
4106 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004107
Willy Tarreaubaaee002006-06-26 02:48:02 +02004108 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004109 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004110 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004111
4112 if (!*args[cur_arg + 1]) {
4113 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4114 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004117 }
4118
4119 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004120 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004121
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004122 if (newsrv->puid <= 0) {
4123 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004124 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004127 }
4128
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004129 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4130 if (node) {
4131 struct server *target = container_of(node, struct server, conf.id);
4132 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4133 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
4136 }
4137 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004138 cur_arg += 2;
4139 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004140 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004141 newsrv->cookie = strdup(args[cur_arg + 1]);
4142 newsrv->cklen = strlen(args[cur_arg + 1]);
4143 cur_arg += 2;
4144 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004145 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004146 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4147 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4148 cur_arg += 2;
4149 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004151 if (!*args[cur_arg + 1]) {
4152 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4153 file, linenum, args[cur_arg]);
4154 err_code |= ERR_ALERT | ERR_FATAL;
4155 goto out;
4156 }
4157
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004159 if (newsrv->rise <= 0) {
4160 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4161 file, linenum, args[cur_arg]);
4162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
4164 }
4165
Willy Tarreau96839092010-03-29 10:02:24 +02004166 if (newsrv->health)
4167 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004168 cur_arg += 2;
4169 }
4170 else if (!strcmp(args[cur_arg], "fall")) {
4171 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004172
4173 if (!*args[cur_arg + 1]) {
4174 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4175 file, linenum, args[cur_arg]);
4176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
4178 }
4179
4180 if (newsrv->fall <= 0) {
4181 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4182 file, linenum, args[cur_arg]);
4183 err_code |= ERR_ALERT | ERR_FATAL;
4184 goto out;
4185 }
4186
Willy Tarreaubaaee002006-06-26 02:48:02 +02004187 cur_arg += 2;
4188 }
4189 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004190 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4191 if (err) {
4192 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4193 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004194 err_code |= ERR_ALERT | ERR_FATAL;
4195 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004196 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004197 if (val <= 0) {
4198 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4199 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004202 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004203 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004204 cur_arg += 2;
4205 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004206 else if (!strcmp(args[cur_arg], "fastinter")) {
4207 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4208 if (err) {
4209 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4210 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004211 err_code |= ERR_ALERT | ERR_FATAL;
4212 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004213 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004214 if (val <= 0) {
4215 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4216 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004219 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004220 newsrv->fastinter = val;
4221 cur_arg += 2;
4222 }
4223 else if (!strcmp(args[cur_arg], "downinter")) {
4224 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4225 if (err) {
4226 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4227 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004228 err_code |= ERR_ALERT | ERR_FATAL;
4229 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004230 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004231 if (val <= 0) {
4232 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4233 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004234 err_code |= ERR_ALERT | ERR_FATAL;
4235 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004236 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004237 newsrv->downinter = val;
4238 cur_arg += 2;
4239 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004240 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004241 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004242 if (!sk) {
4243 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4244 err_code |= ERR_ALERT | ERR_FATAL;
4245 goto out;
4246 }
4247 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004248 cur_arg += 2;
4249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250 else if (!strcmp(args[cur_arg], "port")) {
4251 newsrv->check_port = atol(args[cur_arg + 1]);
4252 cur_arg += 2;
4253 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004254 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 newsrv->state |= SRV_BACKUP;
4256 cur_arg ++;
4257 }
Simon Hormanfa461682011-06-25 09:39:49 +09004258 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4259 newsrv->state |= SRV_NON_STICK;
4260 cur_arg ++;
4261 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004262 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4263 newsrv->state |= SRV_SEND_PROXY;
4264 cur_arg ++;
4265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004266 else if (!strcmp(args[cur_arg], "weight")) {
4267 int w;
4268 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004269 if (w < 0 || w > 256) {
4270 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004271 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004272 err_code |= ERR_ALERT | ERR_FATAL;
4273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004274 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004275 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004276 cur_arg += 2;
4277 }
4278 else if (!strcmp(args[cur_arg], "minconn")) {
4279 newsrv->minconn = atol(args[cur_arg + 1]);
4280 cur_arg += 2;
4281 }
4282 else if (!strcmp(args[cur_arg], "maxconn")) {
4283 newsrv->maxconn = atol(args[cur_arg + 1]);
4284 cur_arg += 2;
4285 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004286 else if (!strcmp(args[cur_arg], "maxqueue")) {
4287 newsrv->maxqueue = atol(args[cur_arg + 1]);
4288 cur_arg += 2;
4289 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004290 else if (!strcmp(args[cur_arg], "slowstart")) {
4291 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004292 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004293 if (err) {
4294 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4295 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004296 err_code |= ERR_ALERT | ERR_FATAL;
4297 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004298 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004299 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004300 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4301 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004302 err_code |= ERR_ALERT | ERR_FATAL;
4303 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004304 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004305 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004306 cur_arg += 2;
4307 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004308 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004309
4310 if (!*args[cur_arg + 1]) {
4311 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4312 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004313 err_code |= ERR_ALERT | ERR_FATAL;
4314 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004315 }
4316
4317 newsrv->trackit = strdup(args[cur_arg + 1]);
4318
4319 cur_arg += 2;
4320 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004321 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004322 global.maxsock++;
4323 do_check = 1;
4324 cur_arg += 1;
4325 }
Willy Tarreau96839092010-03-29 10:02:24 +02004326 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4327 newsrv->state |= SRV_MAINTAIN;
4328 newsrv->state &= ~SRV_RUNNING;
4329 newsrv->health = 0;
4330 cur_arg += 1;
4331 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004332 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004333 if (!strcmp(args[cur_arg + 1], "none"))
4334 newsrv->observe = HANA_OBS_NONE;
4335 else if (!strcmp(args[cur_arg + 1], "layer4"))
4336 newsrv->observe = HANA_OBS_LAYER4;
4337 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4338 if (curproxy->mode != PR_MODE_HTTP) {
4339 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4340 file, linenum, args[cur_arg + 1]);
4341 err_code |= ERR_ALERT;
4342 }
4343 newsrv->observe = HANA_OBS_LAYER7;
4344 }
4345 else {
4346 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004347 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004348 file, linenum, args[cur_arg], args[cur_arg + 1]);
4349 err_code |= ERR_ALERT | ERR_FATAL;
4350 goto out;
4351 }
4352
4353 cur_arg += 2;
4354 }
4355 else if (!strcmp(args[cur_arg], "on-error")) {
4356 if (!strcmp(args[cur_arg + 1], "fastinter"))
4357 newsrv->onerror = HANA_ONERR_FASTINTER;
4358 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4359 newsrv->onerror = HANA_ONERR_FAILCHK;
4360 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4361 newsrv->onerror = HANA_ONERR_SUDDTH;
4362 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4363 newsrv->onerror = HANA_ONERR_MARKDWN;
4364 else {
4365 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004366 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004367 file, linenum, args[cur_arg], args[cur_arg + 1]);
4368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
4371
4372 cur_arg += 2;
4373 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004374 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4375 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4376 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4377 else {
4378 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4379 file, linenum, args[cur_arg], args[cur_arg + 1]);
4380 err_code |= ERR_ALERT | ERR_FATAL;
4381 goto out;
4382 }
4383
4384 cur_arg += 2;
4385 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004386 else if (!strcmp(args[cur_arg], "error-limit")) {
4387 if (!*args[cur_arg + 1]) {
4388 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4389 file, linenum, args[cur_arg]);
4390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
4392 }
4393
4394 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4395
4396 if (newsrv->consecutive_errors_limit <= 0) {
4397 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4398 file, linenum, args[cur_arg]);
4399 err_code |= ERR_ALERT | ERR_FATAL;
4400 goto out;
4401 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004402 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004403 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004404 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004405 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004406 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004407
Willy Tarreaubaaee002006-06-26 02:48:02 +02004408 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004409#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004410 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004411 file, linenum, "source", "usesrc");
4412#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004413 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004414 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004415#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004416 err_code |= ERR_ALERT | ERR_FATAL;
4417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004418 }
4419 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004420 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4421 if (!sk) {
4422 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4423 err_code |= ERR_ALERT | ERR_FATAL;
4424 goto out;
4425 }
4426 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004427
4428 if (port_low != port_high) {
4429 int i;
4430 if (port_low <= 0 || port_low > 65535 ||
4431 port_high <= 0 || port_high > 65535 ||
4432 port_low > port_high) {
4433 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4434 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004435 err_code |= ERR_ALERT | ERR_FATAL;
4436 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004437 }
4438 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4439 for (i = 0; i < newsrv->sport_range->size; i++)
4440 newsrv->sport_range->ports[i] = port_low + i;
4441 }
4442
Willy Tarreaubaaee002006-06-26 02:48:02 +02004443 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004444 while (*(args[cur_arg])) {
4445 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004446#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4447#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004448 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4449 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4450 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004453 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004454#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004455 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004456 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004457 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004458 err_code |= ERR_ALERT | ERR_FATAL;
4459 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004460 }
4461 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004462 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004463 newsrv->state |= SRV_TPROXY_CLI;
4464 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004465 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004466 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004467 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4468 char *name, *end;
4469
4470 name = args[cur_arg+1] + 7;
4471 while (isspace(*name))
4472 name++;
4473
4474 end = name;
4475 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4476 end++;
4477
4478 newsrv->state &= ~SRV_TPROXY_MASK;
4479 newsrv->state |= SRV_TPROXY_DYN;
4480 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4481 newsrv->bind_hdr_len = end - name;
4482 memcpy(newsrv->bind_hdr_name, name, end - name);
4483 newsrv->bind_hdr_name[end-name] = '\0';
4484 newsrv->bind_hdr_occ = -1;
4485
4486 /* now look for an occurrence number */
4487 while (isspace(*end))
4488 end++;
4489 if (*end == ',') {
4490 end++;
4491 name = end;
4492 if (*end == '-')
4493 end++;
4494 while (isdigit(*end))
4495 end++;
4496 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4497 }
4498
4499 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4500 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4501 " occurrences values smaller than %d.\n",
4502 file, linenum, MAX_HDR_HISTORY);
4503 err_code |= ERR_ALERT | ERR_FATAL;
4504 goto out;
4505 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004506 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004507 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004508 if (!sk) {
4509 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4510 err_code |= ERR_ALERT | ERR_FATAL;
4511 goto out;
4512 }
4513 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004514 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004515 }
4516 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004517#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004518 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004519#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004520 cur_arg += 2;
4521 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004522#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004523 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004524 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004525 err_code |= ERR_ALERT | ERR_FATAL;
4526 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004527#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4528 } /* "usesrc" */
4529
4530 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4531#ifdef SO_BINDTODEVICE
4532 if (!*args[cur_arg + 1]) {
4533 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4534 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004537 }
4538 if (newsrv->iface_name)
4539 free(newsrv->iface_name);
4540
4541 newsrv->iface_name = strdup(args[cur_arg + 1]);
4542 newsrv->iface_len = strlen(newsrv->iface_name);
4543 global.last_checks |= LSTCHK_NETADM;
4544#else
4545 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4546 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004549#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004550 cur_arg += 2;
4551 continue;
4552 }
4553 /* this keyword in not an option of "source" */
4554 break;
4555 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004556 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004557 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004558 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4559 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004560 err_code |= ERR_ALERT | ERR_FATAL;
4561 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004562 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004563 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004564 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004565 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'on-marked-down', 'error-limit', 'check', 'disabled', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'send-proxy', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004566 file, linenum, newsrv->id);
4567 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004568 Alert("parsing [%s:%d]: default-server only supports options 'on-error', 'error-limit', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'port', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004569 file, linenum);
4570
Willy Tarreau93893792009-07-23 13:19:11 +02004571 err_code |= ERR_ALERT | ERR_FATAL;
4572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573 }
4574 }
4575
4576 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004577 if (newsrv->trackit) {
4578 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4579 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004580 err_code |= ERR_ALERT | ERR_FATAL;
4581 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004582 }
4583
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004584 /* try to get the port from check_addr if check_port not set */
4585 if (!newsrv->check_port)
4586 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004587
Willy Tarreaubaaee002006-06-26 02:48:02 +02004588 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4589 newsrv->check_port = realport; /* by default */
4590 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004591 /* not yet valid, because no port was set on
4592 * the server either. We'll check if we have
4593 * a known port on the first listener.
4594 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004595 struct listener *l = curproxy->listen;
4596 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4597 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004598 }
4599 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004600 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4601 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004604 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004605
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004606 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004607 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004608 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4609 err_code |= ERR_ALERT | ERR_ABORT;
4610 goto out;
4611 }
4612
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004613 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004614 newsrv->state |= SRV_CHECKED;
4615 }
4616
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004617 if (!defsrv) {
4618 if (newsrv->state & SRV_BACKUP)
4619 curproxy->srv_bck++;
4620 else
4621 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004622
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004623 newsrv->prev_state = newsrv->state;
4624 }
William Lallemanda73203e2012-03-12 12:48:57 +01004625 }
4626
4627 else if (strcmp(args[0], "unique-id-format") == 0) {
4628 if (!*(args[1])) {
4629 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4630 err_code |= ERR_ALERT | ERR_FATAL;
4631 goto out;
4632 }
4633 parse_logformat_string(args[1], curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
William Lallemand723b73a2012-02-08 16:37:49 +01004634 }
William Lallemanda73203e2012-03-12 12:48:57 +01004635
4636 else if (strcmp(args[0], "unique-id-header") == 0) {
4637 if (!*(args[1])) {
4638 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
4641 }
4642 free(curproxy->header_unique_id);
4643 curproxy->header_unique_id = strdup(args[1]);
4644 }
4645
William Lallemand723b73a2012-02-08 16:37:49 +01004646 else if (strcmp(args[0], "log-format") == 0) {
4647 if (!*(args[1])) {
4648 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4649 err_code |= ERR_ALERT | ERR_FATAL;
4650 goto out;
4651 }
William Lallemand1d705562012-03-12 12:46:41 +01004652 parse_logformat_string(args[1], curproxy, &curproxy->logformat, curproxy->mode);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004653 }
William Lallemand723b73a2012-02-08 16:37:49 +01004654
William Lallemand0f99e342011-10-12 17:50:54 +02004655 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4656 /* delete previous herited or defined syslog servers */
4657 struct logsrv *back;
4658
4659 if (*(args[1]) != 0) {
4660 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4661 err_code |= ERR_ALERT | ERR_FATAL;
4662 goto out;
4663 }
4664
William Lallemand723b73a2012-02-08 16:37:49 +01004665 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4666 LIST_DEL(&tmplogsrv->list);
4667 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004668 }
4669 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004670 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004671 struct logsrv *logsrv;
4672
Willy Tarreaubaaee002006-06-26 02:48:02 +02004673 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004674 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004675 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004676 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004677 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004678 LIST_INIT(&node->list);
4679 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4680 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004681 }
4682 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004683
4684 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004685
William Lallemand0f99e342011-10-12 17:50:54 +02004686 logsrv->facility = get_log_facility(args[2]);
4687 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004688 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004689 err_code |= ERR_ALERT | ERR_FATAL;
4690 goto out;
4691
Willy Tarreaubaaee002006-06-26 02:48:02 +02004692 }
4693
William Lallemand0f99e342011-10-12 17:50:54 +02004694 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004695 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004696 logsrv->level = get_log_level(args[3]);
4697 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004698 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004699 err_code |= ERR_ALERT | ERR_FATAL;
4700 goto out;
4701
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702 }
4703 }
4704
William Lallemand0f99e342011-10-12 17:50:54 +02004705 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004706 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004707 logsrv->minlvl = get_log_level(args[4]);
4708 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004709 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004710 err_code |= ERR_ALERT | ERR_FATAL;
4711 goto out;
4712
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004713 }
4714 }
4715
Robert Tsai81ae1952007-12-05 10:47:29 +01004716 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004717 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004718 if (!sk) {
4719 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004720 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004721 err_code |= ERR_ALERT | ERR_FATAL;
4722 goto out;
4723 }
William Lallemand0f99e342011-10-12 17:50:54 +02004724 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004725 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004726 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004727 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004728 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4729 err_code |= ERR_ALERT | ERR_FATAL;
4730 goto out;
4731 }
William Lallemand0f99e342011-10-12 17:50:54 +02004732 logsrv->addr = *sk;
4733 if (!get_host_port(&logsrv->addr))
4734 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004735 }
William Lallemand0f99e342011-10-12 17:50:54 +02004736
4737 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004738 }
4739 else {
4740 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4741 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004742 err_code |= ERR_ALERT | ERR_FATAL;
4743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 }
4745 }
4746 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004747 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004748 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004749
Willy Tarreau977b8e42006-12-29 14:19:17 +01004750 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004751 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004752
Willy Tarreaubaaee002006-06-26 02:48:02 +02004753 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004754 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4755 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004756 err_code |= ERR_ALERT | ERR_FATAL;
4757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004759
4760 /* we must first clear any optional default setting */
4761 curproxy->options &= ~PR_O_TPXY_MASK;
4762 free(curproxy->iface_name);
4763 curproxy->iface_name = NULL;
4764 curproxy->iface_len = 0;
4765
Willy Tarreaud5191e72010-02-09 20:50:45 +01004766 sk = str2sa(args[1]);
4767 if (!sk) {
4768 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4769 err_code |= ERR_ALERT | ERR_FATAL;
4770 goto out;
4771 }
4772 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004774
4775 cur_arg = 2;
4776 while (*(args[cur_arg])) {
4777 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004778#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4779#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004780 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4781 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4782 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004785 }
4786#endif
4787 if (!*args[cur_arg + 1]) {
4788 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4789 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004790 err_code |= ERR_ALERT | ERR_FATAL;
4791 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004792 }
4793
4794 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004795 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004796 curproxy->options |= PR_O_TPXY_CLI;
4797 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004798 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004799 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004800 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4801 char *name, *end;
4802
4803 name = args[cur_arg+1] + 7;
4804 while (isspace(*name))
4805 name++;
4806
4807 end = name;
4808 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4809 end++;
4810
4811 curproxy->options &= ~PR_O_TPXY_MASK;
4812 curproxy->options |= PR_O_TPXY_DYN;
4813 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4814 curproxy->bind_hdr_len = end - name;
4815 memcpy(curproxy->bind_hdr_name, name, end - name);
4816 curproxy->bind_hdr_name[end-name] = '\0';
4817 curproxy->bind_hdr_occ = -1;
4818
4819 /* now look for an occurrence number */
4820 while (isspace(*end))
4821 end++;
4822 if (*end == ',') {
4823 end++;
4824 name = end;
4825 if (*end == '-')
4826 end++;
4827 while (isdigit(*end))
4828 end++;
4829 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4830 }
4831
4832 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4833 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4834 " occurrences values smaller than %d.\n",
4835 file, linenum, MAX_HDR_HISTORY);
4836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
4838 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004839 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004840 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004841 if (!sk) {
4842 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4843 err_code |= ERR_ALERT | ERR_FATAL;
4844 goto out;
4845 }
4846 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004847 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004848 }
4849 global.last_checks |= LSTCHK_NETADM;
4850#if !defined(CONFIG_HAP_LINUX_TPROXY)
4851 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004852#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004853#else /* no TPROXY support */
4854 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004855 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004856 err_code |= ERR_ALERT | ERR_FATAL;
4857 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004858#endif
4859 cur_arg += 2;
4860 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004861 }
4862
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004863 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4864#ifdef SO_BINDTODEVICE
4865 if (!*args[cur_arg + 1]) {
4866 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4867 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004870 }
4871 if (curproxy->iface_name)
4872 free(curproxy->iface_name);
4873
4874 curproxy->iface_name = strdup(args[cur_arg + 1]);
4875 curproxy->iface_len = strlen(curproxy->iface_name);
4876 global.last_checks |= LSTCHK_NETADM;
4877#else
4878 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4879 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004880 err_code |= ERR_ALERT | ERR_FATAL;
4881 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004882#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004883 cur_arg += 2;
4884 continue;
4885 }
4886 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4887 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004888 err_code |= ERR_ALERT | ERR_FATAL;
4889 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004890 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004891 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004892 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4893 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4894 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004895 err_code |= ERR_ALERT | ERR_FATAL;
4896 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004897 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004899 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4901 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004902 err_code |= ERR_ALERT | ERR_FATAL;
4903 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004904 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004905
4906 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004907 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004908 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004909 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004911 }
4912 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004913 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004914 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004915 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004916 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004918 }
4919 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004920 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004921 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004922 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004923 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004925 }
4926 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004927 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004928 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004929 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004930 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004932 }
4933 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004934 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004935 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004936 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004937 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004939 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004940 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004941 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004942 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004943 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004944 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004945 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004946 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004947 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004948 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004949 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004950 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004951 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004952 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004953 }
4954 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004955 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004956 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004957 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004958 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004959 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004960 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004962 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004963 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4964 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004968
4969 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004970 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004971 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004972 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 }
4975 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004976 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004977 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004978 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004979 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 }
4982 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004983 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004984 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004985 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004986 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 }
4989 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004990 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004991 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004992 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004993 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004995 }
4996 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004997 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004998 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004999 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005000 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005002 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005003 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005004 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005005 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005006 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005007 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005008 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005009 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005011 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005012
Willy Tarreaubaaee002006-06-26 02:48:02 +02005013 if (curproxy == &defproxy) {
5014 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005017 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005018 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005019 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020
Willy Tarreaubaaee002006-06-26 02:48:02 +02005021 if (*(args[1]) == 0) {
5022 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005023 err_code |= ERR_ALERT | ERR_FATAL;
5024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005026
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005027 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005028 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5029 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5030 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
5033 }
5034 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5035 }
5036 else if (*args[2]) {
5037 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5038 file, linenum, args[0], args[2]);
5039 err_code |= ERR_ALERT | ERR_FATAL;
5040 goto out;
5041 }
5042
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005043 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005044 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005045 wl->s = strdup(args[1]);
5046 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005047 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005048 }
5049 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005050 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005051 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5052 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005053 err_code |= ERR_ALERT | ERR_FATAL;
5054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005056
Willy Tarreauade5ec42010-01-28 19:33:49 +01005057 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005058 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005059 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005060 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005062 }
5063 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005064 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005065 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005066 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005067 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005069 }
5070 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005071 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005072 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005073 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005074 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005076 }
5077 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005078 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005079 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5080 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005081 err_code |= ERR_ALERT | ERR_FATAL;
5082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005083 }
5084
Willy Tarreauade5ec42010-01-28 19:33:49 +01005085 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005086 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005087 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005088 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005090 }
5091 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005092 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005093 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005094 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005095 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005097 }
5098 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005099 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005100 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005101 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005102 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005104 }
5105 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005106 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005107
Willy Tarreaubaaee002006-06-26 02:48:02 +02005108 if (curproxy == &defproxy) {
5109 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005112 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005113 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005114 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005115
Willy Tarreaubaaee002006-06-26 02:48:02 +02005116 if (*(args[1]) == 0) {
5117 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005118 err_code |= ERR_ALERT | ERR_FATAL;
5119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005120 }
5121
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005122 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005123 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5124 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5125 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
5128 }
5129 err_code |= warnif_cond_requires_req(cond, file, linenum);
5130 }
5131 else if (*args[2]) {
5132 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5133 file, linenum, args[0], args[2]);
5134 err_code |= ERR_ALERT | ERR_FATAL;
5135 goto out;
5136 }
5137
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005138 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005139 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005140 wl->s = strdup(args[1]);
5141 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 }
5143 else if (!strcmp(args[0], "errorloc") ||
5144 !strcmp(args[0], "errorloc302") ||
5145 !strcmp(args[0], "errorloc303")) { /* error location */
5146 int errnum, errlen;
5147 char *err;
5148
Willy Tarreau977b8e42006-12-29 14:19:17 +01005149 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005150 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005151
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005153 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005156 }
5157
5158 errnum = atol(args[1]);
5159 if (!strcmp(args[0], "errorloc303")) {
5160 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5161 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5162 } else {
5163 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5164 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5165 }
5166
Willy Tarreau0f772532006-12-23 20:51:41 +01005167 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5168 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005169 chunk_destroy(&curproxy->errmsg[rc]);
5170 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005171 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005174
5175 if (rc >= HTTP_ERR_SIZE) {
5176 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5177 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005178 free(err);
5179 }
5180 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005181 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5182 int errnum, errlen, fd;
5183 char *err;
5184 struct stat stat;
5185
5186 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005187 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005188
5189 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005190 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005191 err_code |= ERR_ALERT | ERR_FATAL;
5192 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005193 }
5194
5195 fd = open(args[2], O_RDONLY);
5196 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5197 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5198 file, linenum, args[2], args[1]);
5199 if (fd >= 0)
5200 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005201 err_code |= ERR_ALERT | ERR_FATAL;
5202 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005203 }
5204
Willy Tarreau27a674e2009-08-17 07:23:33 +02005205 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005206 errlen = stat.st_size;
5207 } else {
5208 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005209 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005210 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005211 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005212 }
5213
5214 err = malloc(errlen); /* malloc() must succeed during parsing */
5215 errnum = read(fd, err, errlen);
5216 if (errnum != errlen) {
5217 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5218 file, linenum, args[2], args[1]);
5219 close(fd);
5220 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005223 }
5224 close(fd);
5225
5226 errnum = atol(args[1]);
5227 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5228 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005229 chunk_destroy(&curproxy->errmsg[rc]);
5230 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005231 break;
5232 }
5233 }
5234
5235 if (rc >= HTTP_ERR_SIZE) {
5236 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5237 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005238 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005239 free(err);
5240 }
5241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005242 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005243 struct cfg_kw_list *kwl;
5244 int index;
5245
5246 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5247 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5248 if (kwl->kw[index].section != CFG_LISTEN)
5249 continue;
5250 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5251 /* prepare error message just in case */
5252 snprintf(trash, sizeof(trash),
5253 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005254 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005255 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005256 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005257 err_code |= ERR_ALERT | ERR_FATAL;
5258 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005259 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005260 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005261 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005262 err_code |= ERR_WARN;
5263 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005264 }
Willy Tarreau93893792009-07-23 13:19:11 +02005265 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005266 }
5267 }
5268 }
5269
Willy Tarreau6daf3432008-01-22 16:44:08 +01005270 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 }
Willy Tarreau93893792009-07-23 13:19:11 +02005274 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005275 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005276 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005277}
5278
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005279int
5280cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5281{
5282
5283 int err_code = 0;
5284 const char *err;
5285
5286 if (!strcmp(args[0], "userlist")) { /* new userlist */
5287 struct userlist *newul;
5288
5289 if (!*args[1]) {
5290 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5291 file, linenum, args[0]);
5292 err_code |= ERR_ALERT | ERR_FATAL;
5293 goto out;
5294 }
5295
5296 err = invalid_char(args[1]);
5297 if (err) {
5298 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5299 file, linenum, *err, args[0], args[1]);
5300 err_code |= ERR_ALERT | ERR_FATAL;
5301 goto out;
5302 }
5303
5304 for (newul = userlist; newul; newul = newul->next)
5305 if (!strcmp(newul->name, args[1])) {
5306 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5307 file, linenum, args[1]);
5308 err_code |= ERR_WARN;
5309 goto out;
5310 }
5311
5312 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5313 if (!newul) {
5314 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5315 err_code |= ERR_ALERT | ERR_ABORT;
5316 goto out;
5317 }
5318
5319 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5320 newul->name = strdup(args[1]);
5321
5322 if (!newul->groupusers | !newul->name) {
5323 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5324 err_code |= ERR_ALERT | ERR_ABORT;
5325 goto out;
5326 }
5327
5328 newul->next = userlist;
5329 userlist = newul;
5330
5331 } else if (!strcmp(args[0], "group")) { /* new group */
5332 int cur_arg, i;
5333 const char *err;
5334
5335 if (!*args[1]) {
5336 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5337 file, linenum, args[0]);
5338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
5340 }
5341
5342 err = invalid_char(args[1]);
5343 if (err) {
5344 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5345 file, linenum, *err, args[0], args[1]);
5346 err_code |= ERR_ALERT | ERR_FATAL;
5347 goto out;
5348 }
5349
5350 for(i = 0; i < userlist->grpcnt; i++)
5351 if (!strcmp(userlist->groups[i], args[1])) {
5352 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5353 file, linenum, args[1], userlist->name);
5354 err_code |= ERR_ALERT;
5355 goto out;
5356 }
5357
5358 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5359 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5360 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5361 err_code |= ERR_ALERT | ERR_FATAL;
5362 goto out;
5363 }
5364
5365 cur_arg = 2;
5366
5367 while (*args[cur_arg]) {
5368 if (!strcmp(args[cur_arg], "users")) {
5369 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5370 cur_arg += 2;
5371 continue;
5372 } else {
5373 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5374 file, linenum, args[0]);
5375 err_code |= ERR_ALERT | ERR_FATAL;
5376 goto out;
5377 }
5378 }
5379
5380 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5381 } else if (!strcmp(args[0], "user")) { /* new user */
5382 struct auth_users *newuser;
5383 int cur_arg;
5384
5385 if (!*args[1]) {
5386 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5387 file, linenum, args[0]);
5388 err_code |= ERR_ALERT | ERR_FATAL;
5389 goto out;
5390 }
5391
5392 for (newuser = userlist->users; newuser; newuser = newuser->next)
5393 if (!strcmp(newuser->user, args[1])) {
5394 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5395 file, linenum, args[1], userlist->name);
5396 err_code |= ERR_ALERT;
5397 goto out;
5398 }
5399
5400 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5401 if (!newuser) {
5402 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5403 err_code |= ERR_ALERT | ERR_ABORT;
5404 goto out;
5405 }
5406
5407 newuser->user = strdup(args[1]);
5408
5409 newuser->next = userlist->users;
5410 userlist->users = newuser;
5411
5412 cur_arg = 2;
5413
5414 while (*args[cur_arg]) {
5415 if (!strcmp(args[cur_arg], "password")) {
5416#ifndef CONFIG_HAP_CRYPT
5417 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5418 file, linenum);
5419 err_code |= ERR_ALERT;
5420#endif
5421 newuser->pass = strdup(args[cur_arg + 1]);
5422 cur_arg += 2;
5423 continue;
5424 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5425 newuser->pass = strdup(args[cur_arg + 1]);
5426 newuser->flags |= AU_O_INSECURE;
5427 cur_arg += 2;
5428 continue;
5429 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005430 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005431 cur_arg += 2;
5432 continue;
5433 } else {
5434 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5435 file, linenum, args[0]);
5436 err_code |= ERR_ALERT | ERR_FATAL;
5437 goto out;
5438 }
5439 }
5440 } else {
5441 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5442 err_code |= ERR_ALERT | ERR_FATAL;
5443 }
5444
5445out:
5446 return err_code;
5447}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005448
5449/*
5450 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005451 * Returns the error code, 0 if OK, or any combination of :
5452 * - ERR_ABORT: must abort ASAP
5453 * - ERR_FATAL: we can continue parsing but not start the service
5454 * - ERR_WARN: a warning has been emitted
5455 * - ERR_ALERT: an alert has been emitted
5456 * Only the two first ones can stop processing, the two others are just
5457 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005458 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005459int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005460{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005461 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005462 FILE *f;
5463 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005464 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005465 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005466
Willy Tarreaubaaee002006-06-26 02:48:02 +02005467 if ((f=fopen(file,"r")) == NULL)
5468 return -1;
5469
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005470 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005471 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005472 char *end;
5473 char *args[MAX_LINE_ARGS + 1];
5474 char *line = thisline;
5475
Willy Tarreaubaaee002006-06-26 02:48:02 +02005476 linenum++;
5477
5478 end = line + strlen(line);
5479
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005480 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5481 /* Check if we reached the limit and the last char is not \n.
5482 * Watch out for the last line without the terminating '\n'!
5483 */
5484 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005485 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005486 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005487 }
5488
Willy Tarreaubaaee002006-06-26 02:48:02 +02005489 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005490 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005491 line++;
5492
5493 arg = 0;
5494 args[arg] = line;
5495
5496 while (*line && arg < MAX_LINE_ARGS) {
5497 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5498 * C equivalent value. Other combinations left unchanged (eg: \1).
5499 */
5500 if (*line == '\\') {
5501 int skip = 0;
5502 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5503 *line = line[1];
5504 skip = 1;
5505 }
5506 else if (line[1] == 'r') {
5507 *line = '\r';
5508 skip = 1;
5509 }
5510 else if (line[1] == 'n') {
5511 *line = '\n';
5512 skip = 1;
5513 }
5514 else if (line[1] == 't') {
5515 *line = '\t';
5516 skip = 1;
5517 }
5518 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005519 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005520 unsigned char hex1, hex2;
5521 hex1 = toupper(line[2]) - '0';
5522 hex2 = toupper(line[3]) - '0';
5523 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5524 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5525 *line = (hex1<<4) + hex2;
5526 skip = 3;
5527 }
5528 else {
5529 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005530 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005531 }
5532 }
5533 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005534 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005535 end -= skip;
5536 }
5537 line++;
5538 }
5539 else if (*line == '#' || *line == '\n' || *line == '\r') {
5540 /* end of string, end of loop */
5541 *line = 0;
5542 break;
5543 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005544 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005546 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005547 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005548 line++;
5549 args[++arg] = line;
5550 }
5551 else {
5552 line++;
5553 }
5554 }
5555
5556 /* empty line */
5557 if (!**args)
5558 continue;
5559
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005560 if (*line) {
5561 /* we had to stop due to too many args.
5562 * Let's terminate the string, print the offending part then cut the
5563 * last arg.
5564 */
5565 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5566 line++;
5567 *line = '\0';
5568
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005569 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005570 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005571 err_code |= ERR_ALERT | ERR_FATAL;
5572 args[arg] = line;
5573 }
5574
Willy Tarreau540abe42007-05-02 20:50:16 +02005575 /* zero out remaining args and ensure that at least one entry
5576 * is zeroed out.
5577 */
5578 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005579 args[arg] = line;
5580 }
5581
Willy Tarreau3842f002009-06-14 11:39:52 +02005582 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005583 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005584 char *tmp;
5585
Willy Tarreau3842f002009-06-14 11:39:52 +02005586 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005587 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005588 for (arg=0; *args[arg+1]; arg++)
5589 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005590 *tmp = '\0'; // fix the next arg to \0
5591 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005592 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005593 else if (!strcmp(args[0], "default")) {
5594 kwm = KWM_DEF;
5595 for (arg=0; *args[arg+1]; arg++)
5596 args[arg] = args[arg+1]; // shift args after inversion
5597 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005598
William Lallemand0f99e342011-10-12 17:50:54 +02005599 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5600 strcmp(args[0], "log") != 0) {
5601 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005602 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005603 }
5604
Willy Tarreau977b8e42006-12-29 14:19:17 +01005605 if (!strcmp(args[0], "listen") ||
5606 !strcmp(args[0], "frontend") ||
5607 !strcmp(args[0], "backend") ||
5608 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005609 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005611 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005612 cursection = strdup(args[0]);
5613 }
5614 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005616 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005617 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005618 }
5619 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005620 confsect = CFG_USERLIST;
5621 free(cursection);
5622 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005623 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005624 else if (!strcmp(args[0], "peers")) {
5625 confsect = CFG_PEERS;
5626 free(cursection);
5627 cursection = strdup(args[0]);
5628 }
5629
Willy Tarreaubaaee002006-06-26 02:48:02 +02005630 /* else it's a section keyword */
5631
5632 switch (confsect) {
5633 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005634 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005635 break;
5636 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005637 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005638 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005639 case CFG_USERLIST:
5640 err_code |= cfg_parse_users(file, linenum, args, kwm);
5641 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005642 case CFG_PEERS:
5643 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5644 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005645 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005646 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005647 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005648 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005649
5650 if (err_code & ERR_ABORT)
5651 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005652 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005653 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005654 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005655 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005656 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005657}
5658
Willy Tarreaubb925012009-07-23 13:36:36 +02005659/*
5660 * Returns the error code, 0 if OK, or any combination of :
5661 * - ERR_ABORT: must abort ASAP
5662 * - ERR_FATAL: we can continue parsing but not start the service
5663 * - ERR_WARN: a warning has been emitted
5664 * - ERR_ALERT: an alert has been emitted
5665 * Only the two first ones can stop processing, the two others are just
5666 * indicators.
5667 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005668int check_config_validity()
5669{
5670 int cfgerr = 0;
5671 struct proxy *curproxy = NULL;
5672 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005673 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005674 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005675 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005676
5677 /*
5678 * Now, check for the integrity of all that we have collected.
5679 */
5680
5681 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005682 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005683
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005684 /* first, we will invert the proxy list order */
5685 curproxy = NULL;
5686 while (proxy) {
5687 struct proxy *next;
5688
5689 next = proxy->next;
5690 proxy->next = curproxy;
5691 curproxy = proxy;
5692 if (!next)
5693 break;
5694 proxy = next;
5695 }
5696
Willy Tarreaubaaee002006-06-26 02:48:02 +02005697 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005698 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005699 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005700 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005701 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005702 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005703 unsigned int next_id;
5704
5705 if (!curproxy->uuid) {
5706 /* proxy ID not set, use automatic numbering with first
5707 * spare entry starting with next_pxid.
5708 */
5709 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5710 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5711 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005712 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005713 next_pxid++;
5714
Willy Tarreau55ea7572007-06-17 19:56:27 +02005715
Willy Tarreaubaaee002006-06-26 02:48:02 +02005716 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005717 /* ensure we don't keep listeners uselessly bound */
5718 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005719 curproxy = curproxy->next;
5720 continue;
5721 }
5722
Willy Tarreauff01a212009-03-15 13:46:16 +01005723 switch (curproxy->mode) {
5724 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005725 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005726 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005727 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5728 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005729 cfgerr++;
5730 }
5731
5732 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005733 Warning("config : servers will be ignored for %s '%s'.\n",
5734 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005735 break;
5736
5737 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005738 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005739 break;
5740
5741 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005742 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005743 break;
5744 }
5745
5746 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005747 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5748 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005749 cfgerr++;
5750 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005751
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005752 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005753 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005754 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005755 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5756 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005757 cfgerr++;
5758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005759#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005760 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005761 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5762 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005763 cfgerr++;
5764 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005766 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005767 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5768 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005769 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005770 }
5771 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005772 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005773 /* If no LB algo is set in a backend, and we're not in
5774 * transparent mode, dispatch mode nor proxy mode, we
5775 * want to use balance roundrobin by default.
5776 */
5777 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5778 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005779 }
5780 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005781
Willy Tarreau1620ec32011-08-06 17:05:02 +02005782 if (curproxy->options & PR_O_DISPATCH)
5783 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5784 else if (curproxy->options & PR_O_HTTP_PROXY)
5785 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5786 else if (curproxy->options & PR_O_TRANSP)
5787 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005788
Willy Tarreau1620ec32011-08-06 17:05:02 +02005789 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5790 if (curproxy->options & PR_O_DISABLE404) {
5791 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5792 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5793 err_code |= ERR_WARN;
5794 curproxy->options &= ~PR_O_DISABLE404;
5795 }
5796 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5797 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5798 "send-state", proxy_type_str(curproxy), curproxy->id);
5799 err_code |= ERR_WARN;
5800 curproxy->options &= ~PR_O2_CHK_SNDST;
5801 }
Willy Tarreauef781042010-01-27 11:53:01 +01005802 }
5803
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005804 /* if a default backend was specified, let's find it */
5805 if (curproxy->defbe.name) {
5806 struct proxy *target;
5807
Alex Williams96532db2009-11-01 21:27:13 -05005808 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005809 if (!target) {
5810 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5811 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005812 cfgerr++;
5813 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005814 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5815 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005816 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005817 } else {
5818 free(curproxy->defbe.name);
5819 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005820 /* we force the backend to be present on at least all of
5821 * the frontend's processes.
5822 */
5823 target->bind_proc = curproxy->bind_proc ?
5824 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005825
5826 /* Emit a warning if this proxy also has some servers */
5827 if (curproxy->srv) {
5828 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5829 curproxy->id);
5830 err_code |= ERR_WARN;
5831 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832 }
5833 }
5834
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005835 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005836 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5837 /* map jump target for ACT_SETBE in req_rep chain */
5838 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005839 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005840 struct proxy *target;
5841
Willy Tarreaua496b602006-12-17 23:15:24 +01005842 if (exp->action != ACT_SETBE)
5843 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005844
Alex Williams96532db2009-11-01 21:27:13 -05005845 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005846 if (!target) {
5847 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5848 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005849 cfgerr++;
5850 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005851 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5852 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005853 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005854 } else {
5855 free((void *)exp->replace);
5856 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005857 /* we force the backend to be present on at least all of
5858 * the frontend's processes.
5859 */
5860 target->bind_proc = curproxy->bind_proc ?
5861 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005862 }
5863 }
5864 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005865
5866 /* find the target proxy for 'use_backend' rules */
5867 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005868 struct proxy *target;
5869
Alex Williams96532db2009-11-01 21:27:13 -05005870 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005871
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005872 if (!target) {
5873 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5874 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005875 cfgerr++;
5876 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005877 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5878 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005879 cfgerr++;
5880 } else {
5881 free((void *)rule->be.name);
5882 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005883 /* we force the backend to be present on at least all of
5884 * the frontend's processes.
5885 */
5886 target->bind_proc = curproxy->bind_proc ?
5887 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005888 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005889 }
5890
5891 /* find the target proxy for 'use_backend' rules */
5892 list_for_each_entry(srule, &curproxy->server_rules, list) {
5893 struct server *target = findserver(curproxy, srule->srv.name);
5894
5895 if (!target) {
5896 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5897 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5898 cfgerr++;
5899 continue;
5900 }
5901 free((void *)srule->srv.name);
5902 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005903 }
5904
Emeric Brunb982a3d2010-01-04 15:45:53 +01005905 /* find the target table for 'stick' rules */
5906 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5907 struct proxy *target;
5908
Emeric Brun1d33b292010-01-04 15:47:17 +01005909 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5910 if (mrule->flags & STK_IS_STORE)
5911 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5912
Emeric Brunb982a3d2010-01-04 15:45:53 +01005913 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005914 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005915 else
5916 target = curproxy;
5917
5918 if (!target) {
5919 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5920 curproxy->id, mrule->table.name);
5921 cfgerr++;
5922 }
5923 else if (target->table.size == 0) {
5924 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5925 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5926 cfgerr++;
5927 }
Willy Tarreau12785782012-04-27 21:37:17 +02005928 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5929 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005930 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5931 cfgerr++;
5932 }
5933 else {
5934 free((void *)mrule->table.name);
5935 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005936 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005937 }
5938 }
5939
5940 /* find the target table for 'store response' rules */
5941 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5942 struct proxy *target;
5943
Emeric Brun1d33b292010-01-04 15:47:17 +01005944 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5945
Emeric Brunb982a3d2010-01-04 15:45:53 +01005946 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005947 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005948 else
5949 target = curproxy;
5950
5951 if (!target) {
5952 Alert("Proxy '%s': unable to find store table '%s'.\n",
5953 curproxy->id, mrule->table.name);
5954 cfgerr++;
5955 }
5956 else if (target->table.size == 0) {
5957 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5958 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5959 cfgerr++;
5960 }
Willy Tarreau12785782012-04-27 21:37:17 +02005961 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5962 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005963 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5964 cfgerr++;
5965 }
5966 else {
5967 free((void *)mrule->table.name);
5968 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005969 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005970 }
5971 }
5972
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005973 /* find the target table for 'tcp-request' layer 4 rules */
5974 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5975 struct proxy *target;
5976
Willy Tarreau56123282010-08-06 19:06:56 +02005977 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005978 continue;
5979
5980 if (trule->act_prm.trk_ctr.table.n)
5981 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5982 else
5983 target = curproxy;
5984
5985 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005986 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5987 curproxy->id, trule->act_prm.trk_ctr.table.n,
5988 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005989 cfgerr++;
5990 }
5991 else if (target->table.size == 0) {
5992 Alert("Proxy '%s': table '%s' used but not configured.\n",
5993 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5994 cfgerr++;
5995 }
5996 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005997 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005998 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5999 cfgerr++;
6000 }
6001 else {
6002 free(trule->act_prm.trk_ctr.table.n);
6003 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006004 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006005 * to pass a list of counters to track and allocate them right here using
6006 * stktable_alloc_data_type().
6007 */
6008 }
6009 }
6010
Willy Tarreaud1f96522010-08-03 19:34:32 +02006011 /* find the target table for 'tcp-request' layer 6 rules */
6012 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6013 struct proxy *target;
6014
Willy Tarreau56123282010-08-06 19:06:56 +02006015 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006016 continue;
6017
6018 if (trule->act_prm.trk_ctr.table.n)
6019 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6020 else
6021 target = curproxy;
6022
6023 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006024 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6025 curproxy->id, trule->act_prm.trk_ctr.table.n,
6026 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006027 cfgerr++;
6028 }
6029 else if (target->table.size == 0) {
6030 Alert("Proxy '%s': table '%s' used but not configured.\n",
6031 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6032 cfgerr++;
6033 }
6034 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006035 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreaud1f96522010-08-03 19:34:32 +02006036 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6037 cfgerr++;
6038 }
6039 else {
6040 free(trule->act_prm.trk_ctr.table.n);
6041 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006042 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006043 * to pass a list of counters to track and allocate them right here using
6044 * stktable_alloc_data_type().
6045 */
6046 }
6047 }
6048
Emeric Brun32da3c42010-09-23 18:39:19 +02006049 if (curproxy->table.peers.name) {
6050 struct peers *curpeers = peers;
6051
6052 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6053 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6054 free((void *)curproxy->table.peers.name);
6055 curproxy->table.peers.p = peers;
6056 break;
6057 }
6058 }
6059
6060 if (!curpeers) {
6061 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6062 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006063 free((void *)curproxy->table.peers.name);
6064 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006065 cfgerr++;
6066 }
6067 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006068 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6069 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006070 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006071 cfgerr++;
6072 }
6073 }
6074
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006075 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006076 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006077 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6078 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6079 "proxy", curproxy->id);
6080 cfgerr++;
6081 goto out_uri_auth_compat;
6082 }
6083
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006084 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006085 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006086 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006087 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006088
Willy Tarreau95fa4692010-02-01 13:05:50 +01006089 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6090 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006091
6092 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006093 uri_auth_compat_req[i++] = "realm";
6094 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6095 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006096
Willy Tarreau95fa4692010-02-01 13:05:50 +01006097 uri_auth_compat_req[i++] = "unless";
6098 uri_auth_compat_req[i++] = "{";
6099 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6100 uri_auth_compat_req[i++] = "}";
6101 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006102
Willy Tarreauff011f22011-01-06 17:51:27 +01006103 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6104 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006105 cfgerr++;
6106 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006107 }
6108
Willy Tarreauff011f22011-01-06 17:51:27 +01006109 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006110
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006111 if (curproxy->uri_auth->auth_realm) {
6112 free(curproxy->uri_auth->auth_realm);
6113 curproxy->uri_auth->auth_realm = NULL;
6114 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006115
6116 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006117 }
6118out_uri_auth_compat:
6119
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006120 cfgerr += acl_find_targets(curproxy);
6121
Willy Tarreau2738a142006-07-08 17:28:09 +02006122 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006123 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006124 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006125 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006126 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006127 " | While not properly invalid, you will certainly encounter various problems\n"
6128 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006129 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006130 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006131 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006132 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006133
Willy Tarreau1fa31262007-12-03 00:36:16 +01006134 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6135 * We must still support older configurations, so let's find out whether those
6136 * parameters have been set or must be copied from contimeouts.
6137 */
6138 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006139 if (!curproxy->timeout.tarpit ||
6140 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006141 /* tarpit timeout not set. We search in the following order:
6142 * default.tarpit, curr.connect, default.connect.
6143 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006144 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006145 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006146 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006147 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006148 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006149 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006150 }
6151 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006152 (!curproxy->timeout.queue ||
6153 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006154 /* queue timeout not set. We search in the following order:
6155 * default.queue, curr.connect, default.connect.
6156 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006157 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006158 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006159 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006160 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006161 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006162 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006163 }
6164 }
6165
Willy Tarreau1620ec32011-08-06 17:05:02 +02006166 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006167 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6168 curproxy->check_req = (char *)malloc(curproxy->check_len);
6169 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006170 }
6171
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006172 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006173 if (curproxy->nb_req_cap) {
6174 if (curproxy->mode == PR_MODE_HTTP) {
6175 curproxy->req_cap_pool = create_pool("ptrcap",
6176 curproxy->nb_req_cap * sizeof(char *),
6177 MEM_F_SHARED);
6178 } else {
6179 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6180 proxy_type_str(curproxy), curproxy->id);
6181 err_code |= ERR_WARN;
6182 curproxy->to_log &= ~LW_REQHDR;
6183 curproxy->nb_req_cap = 0;
6184 }
6185 }
6186
6187 if (curproxy->nb_rsp_cap) {
6188 if (curproxy->mode == PR_MODE_HTTP) {
6189 curproxy->rsp_cap_pool = create_pool("ptrcap",
6190 curproxy->nb_rsp_cap * sizeof(char *),
6191 MEM_F_SHARED);
6192 } else {
6193 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6194 proxy_type_str(curproxy), curproxy->id);
6195 err_code |= ERR_WARN;
6196 curproxy->to_log &= ~LW_REQHDR;
6197 curproxy->nb_rsp_cap = 0;
6198 }
6199 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006200
Willy Tarreaubaaee002006-06-26 02:48:02 +02006201 /* first, we will invert the servers list order */
6202 newsrv = NULL;
6203 while (curproxy->srv) {
6204 struct server *next;
6205
6206 next = curproxy->srv->next;
6207 curproxy->srv->next = newsrv;
6208 newsrv = curproxy->srv;
6209 if (!next)
6210 break;
6211 curproxy->srv = next;
6212 }
6213
Willy Tarreaudd701652010-05-25 23:03:02 +02006214 /* assign automatic UIDs to servers which don't have one yet */
6215 next_id = 1;
6216 newsrv = curproxy->srv;
6217 while (newsrv != NULL) {
6218 if (!newsrv->puid) {
6219 /* server ID not set, use automatic numbering with first
6220 * spare entry starting with next_svid.
6221 */
6222 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6223 newsrv->conf.id.key = newsrv->puid = next_id;
6224 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6225 }
6226 next_id++;
6227 newsrv = newsrv->next;
6228 }
6229
Willy Tarreau20697042007-11-15 23:26:18 +01006230 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006231 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006232
Willy Tarreau62c3be22012-01-20 13:12:32 +01006233 /*
6234 * If this server supports a maxconn parameter, it needs a dedicated
6235 * tasks to fill the emptied slots when a connection leaves.
6236 * Also, resolve deferred tracking dependency if needed.
6237 */
6238 newsrv = curproxy->srv;
6239 while (newsrv != NULL) {
6240 if (newsrv->minconn > newsrv->maxconn) {
6241 /* Only 'minconn' was specified, or it was higher than or equal
6242 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6243 * this will avoid further useless expensive computations.
6244 */
6245 newsrv->maxconn = newsrv->minconn;
6246 } else if (newsrv->maxconn && !newsrv->minconn) {
6247 /* minconn was not specified, so we set it to maxconn */
6248 newsrv->minconn = newsrv->maxconn;
6249 }
6250
6251 if (newsrv->trackit) {
6252 struct proxy *px;
6253 struct server *srv;
6254 char *pname, *sname;
6255
6256 pname = newsrv->trackit;
6257 sname = strrchr(pname, '/');
6258
6259 if (sname)
6260 *sname++ = '\0';
6261 else {
6262 sname = pname;
6263 pname = NULL;
6264 }
6265
6266 if (pname) {
6267 px = findproxy(pname, PR_CAP_BE);
6268 if (!px) {
6269 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6270 proxy_type_str(curproxy), curproxy->id,
6271 newsrv->id, pname);
6272 cfgerr++;
6273 goto next_srv;
6274 }
6275 } else
6276 px = curproxy;
6277
6278 srv = findserver(px, sname);
6279 if (!srv) {
6280 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6281 proxy_type_str(curproxy), curproxy->id,
6282 newsrv->id, sname);
6283 cfgerr++;
6284 goto next_srv;
6285 }
6286
6287 if (!(srv->state & SRV_CHECKED)) {
6288 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6289 "tracking as it does not have checks enabled.\n",
6290 proxy_type_str(curproxy), curproxy->id,
6291 newsrv->id, px->id, srv->id);
6292 cfgerr++;
6293 goto next_srv;
6294 }
6295
6296 if (curproxy != px &&
6297 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6298 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6299 "tracking: disable-on-404 option inconsistency.\n",
6300 proxy_type_str(curproxy), curproxy->id,
6301 newsrv->id, px->id, srv->id);
6302 cfgerr++;
6303 goto next_srv;
6304 }
6305
6306 /* if the other server is forced disabled, we have to do the same here */
6307 if (srv->state & SRV_MAINTAIN) {
6308 newsrv->state |= SRV_MAINTAIN;
6309 newsrv->state &= ~SRV_RUNNING;
6310 newsrv->health = 0;
6311 }
6312
6313 newsrv->track = srv;
6314 newsrv->tracknext = srv->tracknext;
6315 srv->tracknext = newsrv;
6316
6317 free(newsrv->trackit);
6318 newsrv->trackit = NULL;
6319 }
6320 next_srv:
6321 newsrv = newsrv->next;
6322 }
6323
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006324 /* We have to initialize the server lookup mechanism depending
6325 * on what LB algorithm was choosen.
6326 */
6327
6328 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6329 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6330 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006331 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6332 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6333 init_server_map(curproxy);
6334 } else {
6335 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6336 fwrr_init_server_groups(curproxy);
6337 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006338 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006339
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006340 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006341 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6342 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6343 fwlc_init_server_tree(curproxy);
6344 } else {
6345 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6346 fas_init_server_tree(curproxy);
6347 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006348 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006349
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006350 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006351 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6352 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6353 chash_init_server_tree(curproxy);
6354 } else {
6355 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6356 init_server_map(curproxy);
6357 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006358 break;
6359 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006360
6361 if (curproxy->options & PR_O_LOGASAP)
6362 curproxy->to_log &= ~LW_BYTES;
6363
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006364 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006365 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006366 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6367 proxy_type_str(curproxy), curproxy->id);
6368 err_code |= ERR_WARN;
6369 }
6370
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006371 if (curproxy->mode != PR_MODE_HTTP) {
6372 int optnum;
6373
6374 if (curproxy->options & PR_O_COOK_ANY) {
6375 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6376 proxy_type_str(curproxy), curproxy->id);
6377 err_code |= ERR_WARN;
6378 }
6379
6380 if (curproxy->uri_auth) {
6381 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6382 proxy_type_str(curproxy), curproxy->id);
6383 err_code |= ERR_WARN;
6384 curproxy->uri_auth = NULL;
6385 }
6386
Willy Tarreau87cf5142011-08-19 22:57:24 +02006387 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006388 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6389 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6390 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006391 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006392 }
6393
6394 if (curproxy->options & PR_O_ORGTO) {
6395 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6396 "originalto", proxy_type_str(curproxy), curproxy->id);
6397 err_code |= ERR_WARN;
6398 curproxy->options &= ~PR_O_ORGTO;
6399 }
6400
6401 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6402 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6403 (curproxy->cap & cfg_opts[optnum].cap) &&
6404 (curproxy->options & cfg_opts[optnum].val)) {
6405 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6406 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6407 err_code |= ERR_WARN;
6408 curproxy->options &= ~cfg_opts[optnum].val;
6409 }
6410 }
6411
6412 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6413 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6414 (curproxy->cap & cfg_opts2[optnum].cap) &&
6415 (curproxy->options2 & cfg_opts2[optnum].val)) {
6416 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6417 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6418 err_code |= ERR_WARN;
6419 curproxy->options2 &= ~cfg_opts2[optnum].val;
6420 }
6421 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006422
Willy Tarreauefa5f512010-03-30 20:13:29 +02006423#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006424 if (curproxy->bind_hdr_occ) {
6425 curproxy->bind_hdr_occ = 0;
6426 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6427 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6428 err_code |= ERR_WARN;
6429 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006430#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006431 }
6432
Willy Tarreaubaaee002006-06-26 02:48:02 +02006433 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006434 * ensure that we're not cross-dressing a TCP server into HTTP.
6435 */
6436 newsrv = curproxy->srv;
6437 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006438 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006439 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6440 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006441 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006442 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006443
Willy Tarreau0cec3312011-10-31 13:49:26 +01006444 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6445 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6446 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6447 err_code |= ERR_WARN;
6448 }
6449
Willy Tarreauefa5f512010-03-30 20:13:29 +02006450#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006451 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6452 newsrv->bind_hdr_occ = 0;
6453 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6454 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6455 err_code |= ERR_WARN;
6456 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006457#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006458 newsrv = newsrv->next;
6459 }
6460
Willy Tarreauc1a21672009-08-16 22:37:44 +02006461 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006462 curproxy->accept = frontend_accept;
6463
Willy Tarreauc1a21672009-08-16 22:37:44 +02006464 if (curproxy->tcp_req.inspect_delay ||
6465 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006466 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006467
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006468 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006469 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006470 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006471 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006472
6473 /* both TCP and HTTP must check switching rules */
6474 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6475 }
6476
6477 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006478 if (curproxy->tcp_req.inspect_delay ||
6479 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6480 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6481
Emeric Brun97679e72010-09-23 17:56:44 +02006482 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6483 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6484
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006485 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006486 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006487 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006488 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006489
6490 /* If the backend does requires RDP cookie persistence, we have to
6491 * enable the corresponding analyser.
6492 */
6493 if (curproxy->options2 & PR_O2_RDPC_PRST)
6494 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6495 }
6496
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006497 listener = NULL;
6498 while (curproxy->listen) {
6499 struct listener *next;
6500
6501 next = curproxy->listen->next;
6502 curproxy->listen->next = listener;
6503 listener = curproxy->listen;
6504
6505 if (!next)
6506 break;
6507
6508 curproxy->listen = next;
6509 }
6510
Willy Tarreaue6b98942007-10-29 01:09:36 +01006511 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006512 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006513 listener = curproxy->listen;
6514 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006515 if (!listener->luid) {
6516 /* listener ID not set, use automatic numbering with first
6517 * spare entry starting with next_luid.
6518 */
6519 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6520 listener->conf.id.key = listener->luid = next_id;
6521 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006522 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006523 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006524
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006525 /* enable separate counters */
6526 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6527 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6528 if (!listener->name) {
6529 sprintf(trash, "sock-%d", listener->luid);
6530 listener->name = strdup(trash);
6531 }
6532 }
6533
Willy Tarreaue6b98942007-10-29 01:09:36 +01006534 if (curproxy->options & PR_O_TCP_NOLING)
6535 listener->options |= LI_O_NOLINGER;
6536 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006537 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006538 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006539 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006540 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006541 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006542 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006543
Willy Tarreau8a956912010-10-15 14:27:08 +02006544 if (listener->options & LI_O_ACC_PROXY)
6545 listener->analysers |= AN_REQ_DECODE_PROXY;
6546
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006547 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6548 listener->options |= LI_O_TCP_RULES;
6549
Willy Tarreaude3041d2010-05-31 10:56:17 +02006550 if (curproxy->mon_mask.s_addr)
6551 listener->options |= LI_O_CHK_MONNET;
6552
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006553 /* smart accept mode is automatic in HTTP mode */
6554 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6555 (curproxy->mode == PR_MODE_HTTP &&
6556 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6557 listener->options |= LI_O_NOQUICKACK;
6558
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006559 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006560 listener = listener->next;
6561 }
6562
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006563 /* Check multi-process mode compatibility for the current proxy */
6564 if (global.nbproc > 1) {
6565 int nbproc = 0;
6566 if (curproxy->bind_proc) {
6567 int proc;
6568 for (proc = 0; proc < global.nbproc; proc++) {
6569 if (curproxy->bind_proc & (1 << proc)) {
6570 nbproc++;
6571 }
6572 }
6573 } else {
6574 nbproc = global.nbproc;
6575 }
6576 if (curproxy->table.peers.name) {
6577 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6578 curproxy->id);
6579 cfgerr++;
6580 }
6581 if (nbproc > 1) {
6582 if (curproxy->uri_auth) {
6583 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6584 curproxy->id);
6585 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6586 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6587 curproxy->id);
6588 }
6589 }
6590 if (curproxy->appsession_name) {
6591 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6592 curproxy->id);
6593 }
6594 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6595 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6596 curproxy->id);
6597 }
6598 }
6599 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006600
6601 /* create the task associated with the proxy */
6602 curproxy->task = task_new();
6603 if (curproxy->task) {
6604 curproxy->task->context = curproxy;
6605 curproxy->task->process = manage_proxy;
6606 /* no need to queue, it will be done automatically if some
6607 * listener gets limited.
6608 */
6609 curproxy->task->expire = TICK_ETERNITY;
6610 } else {
6611 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6612 curproxy->id);
6613 cfgerr++;
6614 }
6615
Willy Tarreaubaaee002006-06-26 02:48:02 +02006616 curproxy = curproxy->next;
6617 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006618
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006619 /* Check multi-process mode compatibility */
6620 if (global.nbproc > 1) {
6621 if (global.stats_fe) {
6622 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6623 }
6624 }
6625
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006626 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6627 struct auth_users *curuser;
6628 int g;
6629
6630 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6631 unsigned int group_mask = 0;
6632 char *group = NULL;
6633
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006634 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006635 continue;
6636
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006637 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006638
6639 for (g = 0; g < curuserlist->grpcnt; g++)
6640 if (!strcmp(curuserlist->groups[g], group))
6641 break;
6642
6643 if (g == curuserlist->grpcnt) {
6644 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6645 curuserlist->name, group, curuser->user);
6646 err_code |= ERR_ALERT | ERR_FATAL;
6647 goto out;
6648 }
6649
6650 group_mask |= (1 << g);
6651 }
6652
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006653 free(curuser->u.groups);
6654 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006655 }
6656
6657 for (g = 0; g < curuserlist->grpcnt; g++) {
6658 char *user = NULL;
6659
6660 if (!curuserlist->groupusers[g])
6661 continue;
6662
6663 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6664 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6665 if (!strcmp(curuser->user, user))
6666 break;
6667
6668 if (!curuser) {
6669 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6670 curuserlist->name, user, curuserlist->groups[g]);
6671 err_code |= ERR_ALERT | ERR_FATAL;
6672 goto out;
6673 }
6674
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006675 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006676 }
6677
6678 free(curuserlist->groupusers[g]);
6679 }
6680
6681 free(curuserlist->groupusers);
6682
6683#ifdef DEBUG_AUTH
6684 for (g = 0; g < curuserlist->grpcnt; g++) {
6685 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6686
6687 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006688 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006689 fprintf(stderr, " %s", curuser->user);
6690 }
6691
6692 fprintf(stderr, "\n");
6693 }
6694#endif
6695
Willy Tarreaufbb78422011-06-05 15:38:35 +02006696 }
6697
6698 /* automatically compute fullconn if not set. We must not do it in the
6699 * loop above because cross-references are not yet fully resolved.
6700 */
6701 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6702 /* If <fullconn> is not set, let's set it to 10% of the sum of
6703 * the possible incoming frontend's maxconns.
6704 */
6705 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6706 struct proxy *fe;
6707 int total = 0;
6708
6709 /* sum up the number of maxconns of frontends which
6710 * reference this backend at least once or which are
6711 * the same one ('listen').
6712 */
6713 for (fe = proxy; fe; fe = fe->next) {
6714 struct switching_rule *rule;
6715 struct hdr_exp *exp;
6716 int found = 0;
6717
6718 if (!(fe->cap & PR_CAP_FE))
6719 continue;
6720
6721 if (fe == curproxy) /* we're on a "listen" instance */
6722 found = 1;
6723
6724 if (fe->defbe.be == curproxy) /* "default_backend" */
6725 found = 1;
6726
6727 /* check if a "use_backend" rule matches */
6728 if (!found) {
6729 list_for_each_entry(rule, &fe->switching_rules, list) {
6730 if (rule->be.backend == curproxy) {
6731 found = 1;
6732 break;
6733 }
6734 }
6735 }
6736
6737 /* check if a "reqsetbe" rule matches */
6738 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6739 if (exp->action == ACT_SETBE &&
6740 (struct proxy *)exp->replace == curproxy) {
6741 found = 1;
6742 break;
6743 }
6744 }
6745
6746 /* now we've checked all possible ways to reference a backend
6747 * from a frontend.
6748 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006749 if (!found)
6750 continue;
6751 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006752 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006753 /* we have the sum of the maxconns in <total>. We only
6754 * keep 10% of that sum to set the default fullconn, with
6755 * a hard minimum of 1 (to avoid a divide by zero).
6756 */
6757 curproxy->fullconn = (total + 9) / 10;
6758 if (!curproxy->fullconn)
6759 curproxy->fullconn = 1;
6760 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006761 }
6762
Willy Tarreau056f5682010-06-06 15:51:11 +02006763 /* initialize stick-tables on backend capable proxies. This must not
6764 * be done earlier because the data size may be discovered while parsing
6765 * other proxies.
6766 */
6767 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006768 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006769
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006770 /*
6771 * Recount currently required checks.
6772 */
6773
6774 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6775 int optnum;
6776
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006777 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6778 if (curproxy->options & cfg_opts[optnum].val)
6779 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006780
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006781 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6782 if (curproxy->options2 & cfg_opts2[optnum].val)
6783 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006784 }
6785
Willy Tarreau122541c2011-09-07 21:24:49 +02006786 if (peers) {
6787 struct peers *curpeers = peers, **last;
6788 struct peer *p, *pb;
6789
6790 /* Remove all peers sections which don't have a valid listener.
6791 * This can happen when a peers section is never referenced and
6792 * does not contain a local peer.
6793 */
6794 last = &peers;
6795 while (*last) {
6796 curpeers = *last;
6797 if (curpeers->peers_fe) {
6798 last = &curpeers->next;
6799 continue;
6800 }
6801
6802 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6803 curpeers->id, localpeer);
6804
6805 p = curpeers->remote;
6806 while (p) {
6807 pb = p->next;
6808 free(p->id);
6809 free(p);
6810 p = pb;
6811 }
6812
6813 /* Destroy and unlink this curpeers section.
6814 * Note: curpeers is backed up into *last.
6815 */
6816 free(curpeers->id);
6817 curpeers = curpeers->next;
6818 free(*last);
6819 *last = curpeers;
6820 }
6821 }
6822
Willy Tarreauac1932d2011-10-24 19:14:41 +02006823 if (!global.tune.max_http_hdr)
6824 global.tune.max_http_hdr = MAX_HTTP_HDR;
6825
Willy Tarreau34eb6712011-10-24 18:15:04 +02006826 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006827 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006828 MEM_F_SHARED);
6829
Willy Tarreaubb925012009-07-23 13:36:36 +02006830 if (cfgerr > 0)
6831 err_code |= ERR_ALERT | ERR_FATAL;
6832 out:
6833 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006834}
6835
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006836/*
6837 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6838 * parsing sessions.
6839 */
6840void cfg_register_keywords(struct cfg_kw_list *kwl)
6841{
6842 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6843}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006844
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006845/*
6846 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6847 */
6848void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6849{
6850 LIST_DEL(&kwl->list);
6851 LIST_INIT(&kwl->list);
6852}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006853
6854/*
6855 * Local variables:
6856 * c-indent-level: 8
6857 * c-basic-offset: 8
6858 * End:
6859 */