blob: 1fd5fe1ebbde1c9133be3237773c3d95cc76cb48 [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>
Emeric Brunb982a3d2010-01-04 15:45:53 +010054#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020055#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010056#include <proto/protocols.h>
57#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020058#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010060#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020061#include <proto/peers.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 Tarreaubaaee002006-06-26 02:48:02 +0200457
458 if (!strcmp(args[0], "global")) { /* new section */
459 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 }
462 else if (!strcmp(args[0], "daemon")) {
463 global.mode |= MODE_DAEMON;
464 }
465 else if (!strcmp(args[0], "debug")) {
466 global.mode |= MODE_DEBUG;
467 }
468 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100469 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200471 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100472 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200473 }
474 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100475 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200476 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200477 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100478 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100480 else if (!strcmp(args[0], "nosplice")) {
481 global.tune.options &= ~GTUNE_USE_SPLICE;
482 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483 else if (!strcmp(args[0], "quiet")) {
484 global.mode |= MODE_QUIET;
485 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200486 else if (!strcmp(args[0], "tune.maxpollevents")) {
487 if (global.tune.maxpollevents != 0) {
488 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200489 err_code |= ERR_ALERT;
490 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200491 }
492 if (*(args[1]) == 0) {
493 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200494 err_code |= ERR_ALERT | ERR_FATAL;
495 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200496 }
497 global.tune.maxpollevents = atol(args[1]);
498 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100499 else if (!strcmp(args[0], "tune.maxaccept")) {
500 if (global.tune.maxaccept != 0) {
501 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200502 err_code |= ERR_ALERT;
503 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100504 }
505 if (*(args[1]) == 0) {
506 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200507 err_code |= ERR_ALERT | ERR_FATAL;
508 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100509 }
510 global.tune.maxaccept = atol(args[1]);
511 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200512 else if (!strcmp(args[0], "tune.chksize")) {
513 if (*(args[1]) == 0) {
514 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
515 err_code |= ERR_ALERT | ERR_FATAL;
516 goto out;
517 }
518 global.tune.chksize = atol(args[1]);
519 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200520 else if (!strcmp(args[0], "tune.bufsize")) {
521 if (*(args[1]) == 0) {
522 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT | ERR_FATAL;
524 goto out;
525 }
526 global.tune.bufsize = atol(args[1]);
527 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
528 global.tune.maxrewrite = global.tune.bufsize / 2;
529 }
530 else if (!strcmp(args[0], "tune.maxrewrite")) {
531 if (*(args[1]) == 0) {
532 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
533 err_code |= ERR_ALERT | ERR_FATAL;
534 goto out;
535 }
536 global.tune.maxrewrite = atol(args[1]);
537 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
538 global.tune.maxrewrite = global.tune.bufsize / 2;
539 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100540 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
541 if (global.tune.client_rcvbuf != 0) {
542 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
543 err_code |= ERR_ALERT;
544 goto out;
545 }
546 if (*(args[1]) == 0) {
547 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
548 err_code |= ERR_ALERT | ERR_FATAL;
549 goto out;
550 }
551 global.tune.client_rcvbuf = atol(args[1]);
552 }
553 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
554 if (global.tune.server_rcvbuf != 0) {
555 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
556 err_code |= ERR_ALERT;
557 goto out;
558 }
559 if (*(args[1]) == 0) {
560 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT | ERR_FATAL;
562 goto out;
563 }
564 global.tune.server_rcvbuf = atol(args[1]);
565 }
566 else if (!strcmp(args[0], "tune.sndbuf.client")) {
567 if (global.tune.client_sndbuf != 0) {
568 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT;
570 goto out;
571 }
572 if (*(args[1]) == 0) {
573 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT | ERR_FATAL;
575 goto out;
576 }
577 global.tune.client_sndbuf = atol(args[1]);
578 }
579 else if (!strcmp(args[0], "tune.sndbuf.server")) {
580 if (global.tune.server_sndbuf != 0) {
581 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT;
583 goto out;
584 }
585 if (*(args[1]) == 0) {
586 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590 global.tune.server_sndbuf = atol(args[1]);
591 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200592 else if (!strcmp(args[0], "tune.pipesize")) {
593 if (*(args[1]) == 0) {
594 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
595 err_code |= ERR_ALERT | ERR_FATAL;
596 goto out;
597 }
598 global.tune.pipesize = atol(args[1]);
599 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200600 else if (!strcmp(args[0], "tune.http.maxhdr")) {
601 if (*(args[1]) == 0) {
602 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT | ERR_FATAL;
604 goto out;
605 }
606 global.tune.max_http_hdr = atol(args[1]);
607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 else if (!strcmp(args[0], "uid")) {
609 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200610 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200611 err_code |= ERR_ALERT;
612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 }
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 }
619 global.uid = atol(args[1]);
620 }
621 else if (!strcmp(args[0], "gid")) {
622 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200623 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200624 err_code |= ERR_ALERT;
625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 }
627 if (*(args[1]) == 0) {
628 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200629 err_code |= ERR_ALERT | ERR_FATAL;
630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 }
632 global.gid = atol(args[1]);
633 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200634 /* user/group name handling */
635 else if (!strcmp(args[0], "user")) {
636 struct passwd *ha_user;
637 if (global.uid != 0) {
638 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200639 err_code |= ERR_ALERT;
640 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200641 }
642 errno = 0;
643 ha_user = getpwnam(args[1]);
644 if (ha_user != NULL) {
645 global.uid = (int)ha_user->pw_uid;
646 }
647 else {
648 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 +0200649 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200650 }
651 }
652 else if (!strcmp(args[0], "group")) {
653 struct group *ha_group;
654 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200655 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200656 err_code |= ERR_ALERT;
657 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200658 }
659 errno = 0;
660 ha_group = getgrnam(args[1]);
661 if (ha_group != NULL) {
662 global.gid = (int)ha_group->gr_gid;
663 }
664 else {
665 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 +0200666 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200667 }
668 }
669 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 else if (!strcmp(args[0], "nbproc")) {
671 if (global.nbproc != 0) {
672 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT;
674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 }
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 }
681 global.nbproc = atol(args[1]);
682 }
683 else if (!strcmp(args[0], "maxconn")) {
684 if (global.maxconn != 0) {
685 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200686 err_code |= ERR_ALERT;
687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 }
689 if (*(args[1]) == 0) {
690 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT | ERR_FATAL;
692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 global.maxconn = atol(args[1]);
695#ifdef SYSTEM_MAXCONN
696 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
697 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);
698 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700 }
701#endif /* SYSTEM_MAXCONN */
702 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200703 else if (!strcmp(args[0], "maxconnrate")) {
704 if (global.cps_lim != 0) {
705 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
706 err_code |= ERR_ALERT;
707 goto out;
708 }
709 if (*(args[1]) == 0) {
710 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
711 err_code |= ERR_ALERT | ERR_FATAL;
712 goto out;
713 }
714 global.cps_lim = atol(args[1]);
715 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100716 else if (!strcmp(args[0], "maxpipes")) {
717 if (global.maxpipes != 0) {
718 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200719 err_code |= ERR_ALERT;
720 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100721 }
722 if (*(args[1]) == 0) {
723 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200724 err_code |= ERR_ALERT | ERR_FATAL;
725 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100726 }
727 global.maxpipes = atol(args[1]);
728 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729 else if (!strcmp(args[0], "ulimit-n")) {
730 if (global.rlimit_nofile != 0) {
731 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200732 err_code |= ERR_ALERT;
733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200734 }
735 if (*(args[1]) == 0) {
736 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200739 }
740 global.rlimit_nofile = atol(args[1]);
741 }
742 else if (!strcmp(args[0], "chroot")) {
743 if (global.chroot != NULL) {
744 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200745 err_code |= ERR_ALERT;
746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 }
748 if (*(args[1]) == 0) {
749 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200750 err_code |= ERR_ALERT | ERR_FATAL;
751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 }
753 global.chroot = strdup(args[1]);
754 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200755 else if (!strcmp(args[0], "description")) {
756 int i, len=0;
757 char *d;
758
759 if (!*args[1]) {
760 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
761 file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765
766 for(i=1; *args[i]; i++)
767 len += strlen(args[i])+1;
768
769 if (global.desc)
770 free(global.desc);
771
772 global.desc = d = (char *)calloc(1, len);
773
774 d += sprintf(d, "%s", args[1]);
775 for(i=2; *args[i]; i++)
776 d += sprintf(d, " %s", args[i]);
777 }
778 else if (!strcmp(args[0], "node")) {
779 int i;
780 char c;
781
782 for (i=0; args[1][i]; i++) {
783 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100784 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
785 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200786 break;
787 }
788
789 if (!i || args[1][i]) {
790 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
791 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
792 file, linenum, args[0]);
793 err_code |= ERR_ALERT | ERR_FATAL;
794 goto out;
795 }
796
797 if (global.node)
798 free(global.node);
799
800 global.node = strdup(args[1]);
801 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200802 else if (!strcmp(args[0], "pidfile")) {
803 if (global.pidfile != NULL) {
804 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200805 err_code |= ERR_ALERT;
806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200807 }
808 if (*(args[1]) == 0) {
809 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200810 err_code |= ERR_ALERT | ERR_FATAL;
811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812 }
813 global.pidfile = strdup(args[1]);
814 }
Emeric Bruned760922010-10-22 17:59:25 +0200815 else if (!strcmp(args[0], "unix-bind")) {
816 int cur_arg = 1;
817 while (*(args[cur_arg])) {
818 if (!strcmp(args[cur_arg], "prefix")) {
819 if (global.unix_bind.prefix != NULL) {
820 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
821 err_code |= ERR_ALERT;
822 cur_arg += 2;
823 continue;
824 }
825
826 if (*(args[cur_arg+1]) == 0) {
827 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
828 err_code |= ERR_ALERT | ERR_FATAL;
829 goto out;
830 }
831 global.unix_bind.prefix = strdup(args[cur_arg+1]);
832 cur_arg += 2;
833 continue;
834 }
835
836 if (!strcmp(args[cur_arg], "mode")) {
837
838 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
839 cur_arg += 2;
840 continue;
841 }
842
843 if (!strcmp(args[cur_arg], "uid")) {
844
845 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
846 cur_arg += 2;
847 continue;
848 }
849
850 if (!strcmp(args[cur_arg], "gid")) {
851
852 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
853 cur_arg += 2;
854 continue;
855 }
856
857 if (!strcmp(args[cur_arg], "user")) {
858 struct passwd *user;
859
860 user = getpwnam(args[cur_arg + 1]);
861 if (!user) {
862 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
863 file, linenum, args[0], args[cur_arg + 1 ]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867
868 global.unix_bind.ux.uid = user->pw_uid;
869 cur_arg += 2;
870 continue;
871 }
872
873 if (!strcmp(args[cur_arg], "group")) {
874 struct group *group;
875
876 group = getgrnam(args[cur_arg + 1]);
877 if (!group) {
878 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
879 file, linenum, args[0], args[cur_arg + 1 ]);
880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
882 }
883
884 global.unix_bind.ux.gid = group->gr_gid;
885 cur_arg += 2;
886 continue;
887 }
888
Willy Tarreaub48f9582011-09-05 01:17:06 +0200889 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200890 file, linenum, args[0]);
891 err_code |= ERR_ALERT | ERR_FATAL;
892 goto out;
893 }
894 }
William Lallemand0f99e342011-10-12 17:50:54 +0200895 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
896 /* delete previous herited or defined syslog servers */
897 struct logsrv *back;
898 struct logsrv *tmp;
899
900 if (*(args[1]) != 0) {
901 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
902 err_code |= ERR_ALERT | ERR_FATAL;
903 goto out;
904 }
905
906 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
907 LIST_DEL(&tmp->list);
908 free(tmp);
909 }
910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200911 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200912 struct logsrv *logsrv;
913
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914 if (*(args[1]) == 0 || *(args[2]) == 0) {
915 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 }
William Lallemand0f99e342011-10-12 17:50:54 +0200919
920 logsrv = calloc(1, sizeof(struct logsrv));
921
922 logsrv->facility = get_log_facility(args[2]);
923 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200925 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200926 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928
William Lallemand0f99e342011-10-12 17:50:54 +0200929 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200931 logsrv->level = get_log_level(args[3]);
932 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200934 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200935 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936 }
937 }
938
William Lallemand0f99e342011-10-12 17:50:54 +0200939 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200940 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200941 logsrv->minlvl = get_log_level(args[4]);
942 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200943 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200944 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200945 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200946 }
947 }
948
Robert Tsai81ae1952007-12-05 10:47:29 +0100949 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100950 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100951 if (!sk) {
952 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100953 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100954 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200955 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100956 goto out;
957 }
William Lallemand0f99e342011-10-12 17:50:54 +0200958 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100959 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100960 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100961 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100962 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
963 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200964 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100965 goto out;
966 }
William Lallemand0f99e342011-10-12 17:50:54 +0200967 logsrv->addr = *sk;
968 if (!get_host_port(&logsrv->addr))
969 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100970 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200971
William Lallemand0f99e342011-10-12 17:50:54 +0200972 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200973 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100974 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
975 char *name;
976 int len;
977
978 if (global.log_send_hostname != NULL) {
979 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
980 err_code |= ERR_ALERT;
981 goto out;
982 }
983
984 if (*(args[1]))
985 name = args[1];
986 else
987 name = hostname;
988
989 len = strlen(name);
990
991 /* We'll add a space after the name to respect the log format */
992 free(global.log_send_hostname);
993 global.log_send_hostname = malloc(len + 2);
994 snprintf(global.log_send_hostname, len + 2, "%s ", name);
995 }
Kevinm48936af2010-12-22 16:08:21 +0000996 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
997 if (*(args[1]) == 0) {
998 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
1001 }
1002 free(global.log_tag);
1003 global.log_tag = strdup(args[1]);
1004 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001005 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1006 if (global.spread_checks != 0) {
1007 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001008 err_code |= ERR_ALERT;
1009 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001010 }
1011 if (*(args[1]) == 0) {
1012 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001013 err_code |= ERR_ALERT | ERR_FATAL;
1014 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001015 }
1016 global.spread_checks = atol(args[1]);
1017 if (global.spread_checks < 0 || global.spread_checks > 50) {
1018 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001019 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001020 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021 }
1022 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001023 struct cfg_kw_list *kwl;
1024 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001025 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001026
1027 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1028 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1029 if (kwl->kw[index].section != CFG_GLOBAL)
1030 continue;
1031 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1032 /* prepare error message just in case */
1033 snprintf(trash, sizeof(trash),
1034 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001035 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1036 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001037 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001038 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001039 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001040 else if (rc > 0) {
1041 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001042 err_code |= ERR_WARN;
1043 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001044 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001045 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001046 }
1047 }
1048 }
1049
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001051 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001053
Willy Tarreau058e9072009-07-20 09:30:05 +02001054 out:
1055 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056}
1057
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001058void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001060 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001061 defproxy.mode = PR_MODE_TCP;
1062 defproxy.state = PR_STNEW;
1063 defproxy.maxconn = cfg_maxpconn;
1064 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001065
1066 defproxy.defsrv.inter = DEF_CHKINTR;
1067 defproxy.defsrv.fastinter = 0;
1068 defproxy.defsrv.downinter = 0;
1069 defproxy.defsrv.rise = DEF_RISETIME;
1070 defproxy.defsrv.fall = DEF_FALLTIME;
1071 defproxy.defsrv.check_port = 0;
1072 defproxy.defsrv.maxqueue = 0;
1073 defproxy.defsrv.minconn = 0;
1074 defproxy.defsrv.maxconn = 0;
1075 defproxy.defsrv.slowstart = 0;
1076 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1077 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1078 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079}
1080
Willy Tarreauade5ec42010-01-28 19:33:49 +01001081
1082static int create_cond_regex_rule(const char *file, int line,
1083 struct proxy *px, int dir, int action, int flags,
1084 const char *cmd, const char *reg, const char *repl,
1085 const char **cond_start)
1086{
1087 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001088 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001089 const char *err;
1090 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001091 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001092
1093 if (px == &defproxy) {
1094 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto err;
1097 }
1098
1099 if (*reg == 0) {
1100 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1101 err_code |= ERR_ALERT | ERR_FATAL;
1102 goto err;
1103 }
1104
1105 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1106 err_code |= ERR_WARN;
1107
Willy Tarreau5321c422010-01-28 20:35:13 +01001108 if (cond_start &&
1109 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001110 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1111 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1112 file, line, cmd, errmsg);
1113 free(errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001114 err_code |= ERR_ALERT | ERR_FATAL;
1115 goto err;
1116 }
1117 }
1118 else if (cond_start && **cond_start) {
1119 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1120 file, line, cmd, *cond_start);
1121 err_code |= ERR_ALERT | ERR_FATAL;
1122 goto err;
1123 }
1124
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001125 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001126 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001127 else
1128 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001129
Willy Tarreauade5ec42010-01-28 19:33:49 +01001130 preg = calloc(1, sizeof(regex_t));
1131 if (!preg) {
1132 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1133 err_code = ERR_ALERT | ERR_FATAL;
1134 goto err;
1135 }
1136
1137 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1138 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1139 err_code = ERR_ALERT | ERR_FATAL;
1140 goto err;
1141 }
1142
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001143 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001144 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001145 if (repl && err) {
1146 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1147 file, line, cmd, *err);
1148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto err;
1150 }
1151
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001152 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001153 err_code |= ERR_WARN;
1154
1155 return err_code;
1156 err:
1157 free(preg);
1158 return err_code;
1159}
1160
Willy Tarreaubaaee002006-06-26 02:48:02 +02001161/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001162 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001163 * Returns the error code, 0 if OK, or any combination of :
1164 * - ERR_ABORT: must abort ASAP
1165 * - ERR_FATAL: we can continue parsing but not start the service
1166 * - ERR_WARN: a warning has been emitted
1167 * - ERR_ALERT: an alert has been emitted
1168 * Only the two first ones can stop processing, the two others are just
1169 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001170 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001171int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1172{
1173 static struct peers *curpeers = NULL;
1174 struct peer *newpeer = NULL;
1175 const char *err;
1176 int err_code = 0;
1177
1178 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1179
1180 err = invalid_char(args[1]);
1181 if (err) {
1182 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1183 file, linenum, *err, args[0], args[1]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 }
1186
1187 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1188 /*
1189 * If there are two proxies with the same name only following
1190 * combinations are allowed:
1191 */
1192 if (strcmp(curpeers->id, args[1]) == 0) {
1193 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1194 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1195 err_code |= ERR_WARN;
1196 }
1197 }
1198
1199 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1200 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1201 err_code |= ERR_ALERT | ERR_ABORT;
1202 goto out;
1203 }
1204
1205 curpeers->next = peers;
1206 peers = curpeers;
1207 curpeers->conf.file = file;
1208 curpeers->conf.line = linenum;
1209 curpeers->last_change = now.tv_sec;
1210 curpeers->id = strdup(args[1]);
1211 }
1212 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1213 char *rport, *raddr;
1214 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001215 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001216
1217 if (!*args[2]) {
1218 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1219 file, linenum, args[0]);
1220 err_code |= ERR_ALERT | ERR_FATAL;
1221 goto out;
1222 }
1223
1224 err = invalid_char(args[1]);
1225 if (err) {
1226 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1227 file, linenum, *err, args[1]);
1228 err_code |= ERR_ALERT | ERR_FATAL;
1229 goto out;
1230 }
1231
1232 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1233 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1234 err_code |= ERR_ALERT | ERR_ABORT;
1235 goto out;
1236 }
1237
1238 /* the peers are linked backwards first */
1239 curpeers->count++;
1240 newpeer->next = curpeers->remote;
1241 curpeers->remote = newpeer;
1242 newpeer->peers = curpeers;
1243 newpeer->conf.file = file;
1244 newpeer->conf.line = linenum;
1245
1246 newpeer->last_change = now.tv_sec;
1247 newpeer->id = strdup(args[1]);
1248
1249 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001250 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001251 if (rport) {
1252 *rport++ = 0;
1253 realport = atol(rport);
1254 }
1255 if (!realport) {
1256 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1257 err_code |= ERR_ALERT | ERR_FATAL;
1258 goto out;
1259 }
1260
Willy Tarreaufab5a432011-03-04 15:31:53 +01001261 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001262 free(raddr);
1263 if (!sk) {
1264 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1265 err_code |= ERR_ALERT | ERR_FATAL;
1266 goto out;
1267 }
1268 newpeer->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001269 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001270
1271 if (strcmp(newpeer->id, localpeer) == 0) {
1272 /* Current is local peer, it define a frontend */
1273 newpeer->local = 1;
1274
1275 if (!curpeers->peers_fe) {
1276 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1277 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1278 err_code |= ERR_ALERT | ERR_ABORT;
1279 goto out;
1280 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001281
Willy Tarreau237250c2011-07-29 01:49:03 +02001282 init_new_proxy(curpeers->peers_fe);
1283 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001284
1285 curpeers->peers_fe->last_change = now.tv_sec;
1286 curpeers->peers_fe->id = strdup(args[1]);
1287 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001288 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001289 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1290 curpeers->peers_fe->timeout.connect = 5000;
1291 curpeers->peers_fe->accept = peer_accept;
1292 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001293 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001294 err_code |= ERR_FATAL;
1295 goto out;
1296 }
1297 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1298 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1299 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1300 curpeers->peers_fe->listen->accept = session_accept;
1301 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1302 curpeers->peers_fe->listen->handler = process_session;
1303 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001304 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1305 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001306 }
1307 }
1308 } /* neither "peer" nor "peers" */
1309 else if (*args[0] != 0) {
1310 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
1313 }
1314
1315out:
1316 return err_code;
1317}
1318
1319
Willy Tarreau3842f002009-06-14 11:39:52 +02001320int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001321{
1322 static struct proxy *curproxy = NULL;
1323 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001324 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001325 int rc;
1326 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001327 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001328 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001329 struct logsrv *tmplogsrv;
1330 struct logformat_node *tmplf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001331
Willy Tarreau977b8e42006-12-29 14:19:17 +01001332 if (!strcmp(args[0], "listen"))
1333 rc = PR_CAP_LISTEN;
1334 else if (!strcmp(args[0], "frontend"))
1335 rc = PR_CAP_FE | PR_CAP_RS;
1336 else if (!strcmp(args[0], "backend"))
1337 rc = PR_CAP_BE | PR_CAP_RS;
1338 else if (!strcmp(args[0], "ruleset"))
1339 rc = PR_CAP_RS;
1340 else
1341 rc = PR_CAP_NONE;
1342
1343 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001344 if (!*args[1]) {
1345 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1346 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1347 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001348 err_code |= ERR_ALERT | ERR_ABORT;
1349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001350 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001351
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001352 err = invalid_char(args[1]);
1353 if (err) {
1354 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1355 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001356 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001357 }
1358
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001359 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1360 /*
1361 * If there are two proxies with the same name only following
1362 * combinations are allowed:
1363 *
1364 * listen backend frontend ruleset
1365 * listen - - - -
1366 * backend - - OK -
1367 * frontend - OK - -
1368 * ruleset - - - -
1369 */
1370
1371 if (!strcmp(curproxy->id, args[1]) &&
1372 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1373 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001374 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1375 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1376 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001377 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001378 }
1379 }
1380
Willy Tarreaubaaee002006-06-26 02:48:02 +02001381 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1382 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001383 err_code |= ERR_ALERT | ERR_ABORT;
1384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001386
Willy Tarreau97cb7802010-01-03 20:23:58 +01001387 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388 curproxy->next = proxy;
1389 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001390 curproxy->conf.file = file;
1391 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001392 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001393 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001394 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395
1396 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001397 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001398 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001399 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001400 err_code |= ERR_FATAL;
1401 goto out;
1402 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001403 new = curproxy->listen;
1404 while (new != last) {
1405 new->conf.file = file;
1406 new->conf.line = linenum;
1407 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001408 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001409 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410 }
1411
1412 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001413 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001414 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001415
Willy Tarreaubaaee002006-06-26 02:48:02 +02001416 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001417 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001418 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001419 curproxy->no_options = defproxy.no_options;
1420 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001421 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001422 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001423 curproxy->except_net = defproxy.except_net;
1424 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001425 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001426 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001428 if (defproxy.fwdfor_hdr_len) {
1429 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1430 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1431 }
1432
Willy Tarreaub86db342009-11-30 11:50:16 +01001433 if (defproxy.orgto_hdr_len) {
1434 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1435 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1436 }
1437
Mark Lamourinec2247f02012-01-04 13:02:01 -05001438 if (defproxy.server_id_hdr_len) {
1439 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1440 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1441 }
1442
Willy Tarreau977b8e42006-12-29 14:19:17 +01001443 if (curproxy->cap & PR_CAP_FE) {
1444 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001445 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001446 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001447
1448 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001449 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1450 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001451
1452 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454
Willy Tarreau977b8e42006-12-29 14:19:17 +01001455 if (curproxy->cap & PR_CAP_BE) {
1456 curproxy->fullconn = defproxy.fullconn;
1457 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001458
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001459 if (defproxy.check_req) {
1460 curproxy->check_req = calloc(1, defproxy.check_len);
1461 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1462 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001463 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001464
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001465 if (defproxy.expect_str) {
1466 curproxy->expect_str = strdup(defproxy.expect_str);
1467 if (defproxy.expect_regex) {
1468 /* note: this regex is known to be valid */
1469 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1470 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1471 }
1472 }
1473
Willy Tarreau977b8e42006-12-29 14:19:17 +01001474 if (defproxy.cookie_name)
1475 curproxy->cookie_name = strdup(defproxy.cookie_name);
1476 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001477 if (defproxy.cookie_domain)
1478 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001479
Willy Tarreau31936852010-10-06 16:59:56 +02001480 if (defproxy.cookie_maxidle)
1481 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1482
1483 if (defproxy.cookie_maxlife)
1484 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1485
Emeric Brun647caf12009-06-30 17:57:00 +02001486 if (defproxy.rdp_cookie_name)
1487 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1488 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1489
Willy Tarreau01732802007-11-01 22:48:15 +01001490 if (defproxy.url_param_name)
1491 curproxy->url_param_name = strdup(defproxy.url_param_name);
1492 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001493
Benoitaffb4812009-03-25 13:02:10 +01001494 if (defproxy.hh_name)
1495 curproxy->hh_name = strdup(defproxy.hh_name);
1496 curproxy->hh_len = defproxy.hh_len;
1497 curproxy->hh_match_domain = defproxy.hh_match_domain;
1498
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001499 if (defproxy.iface_name)
1500 curproxy->iface_name = strdup(defproxy.iface_name);
1501 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001503
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001504 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001505 if (defproxy.capture_name)
1506 curproxy->capture_name = strdup(defproxy.capture_name);
1507 curproxy->capture_namelen = defproxy.capture_namelen;
1508 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001510
Willy Tarreau977b8e42006-12-29 14:19:17 +01001511 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001512 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001513 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001514 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001515 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001516 curproxy->uri_auth = defproxy.uri_auth;
1517 curproxy->mon_net = defproxy.mon_net;
1518 curproxy->mon_mask = defproxy.mon_mask;
1519 if (defproxy.monitor_uri)
1520 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1521 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001522 if (defproxy.defbe.name)
1523 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001524 }
1525
1526 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001527 curproxy->timeout.connect = defproxy.timeout.connect;
1528 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001529 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001530 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001531 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001532 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001533 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001534 curproxy->source_addr = defproxy.source_addr;
1535 }
1536
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001538
1539 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001540 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001541 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001542 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001543 LIST_INIT(&node->list);
1544 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1545 }
1546
William Lallemand723b73a2012-02-08 16:37:49 +01001547 /* copy default log_format to curproxy */
1548 list_for_each_entry(tmplf, &defproxy.logformat, list) {
1549 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1550 memcpy(node, tmplf, sizeof(struct logformat_node));
1551 LIST_INIT(&node->list);
1552 LIST_ADDQ(&curproxy->logformat, &node->list);
1553 }
1554
William Lallemanda73203e2012-03-12 12:48:57 +01001555 /* copy default unique_id to curproxy */
1556 list_for_each_entry(tmplf, &defproxy.format_unique_id, list) {
1557 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1558 memcpy(node, tmplf, sizeof(struct logformat_node));
1559 LIST_INIT(&node->list);
1560 LIST_ADDQ(&curproxy->format_unique_id, &node->list);
1561 }
1562
1563 /* copy default header unique id */
1564 if (defproxy.header_unique_id)
1565 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1566
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001568 curproxy->conf.used_listener_id = EB_ROOT;
1569 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001570
Willy Tarreau93893792009-07-23 13:19:11 +02001571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572 }
1573 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1574 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001575 /* FIXME-20070101: we should do this too at the end of the
1576 * config parsing to free all default values.
1577 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001578 free(defproxy.check_req);
1579 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001580 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001581 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001582 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001583 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001584 free(defproxy.capture_name);
1585 free(defproxy.monitor_uri);
1586 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001587 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001588 free(defproxy.fwdfor_hdr_name);
1589 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001590 free(defproxy.orgto_hdr_name);
1591 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001592 free(defproxy.server_id_hdr_name);
1593 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001594 free(defproxy.expect_str);
1595 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001596
Willy Tarreaua534fea2008-08-03 12:19:50 +02001597 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001598 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001599
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600 /* we cannot free uri_auth because it might already be used */
1601 init_default_instance();
1602 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001603 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 }
1606 else if (curproxy == NULL) {
1607 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001608 err_code |= ERR_ALERT | ERR_FATAL;
1609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001610 }
1611
Willy Tarreau977b8e42006-12-29 14:19:17 +01001612
1613 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001615 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001616 int cur_arg;
1617
Willy Tarreaubaaee002006-06-26 02:48:02 +02001618 if (curproxy == &defproxy) {
1619 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001620 err_code |= ERR_ALERT | ERR_FATAL;
1621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001623 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001624 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625
Emeric Bruned760922010-10-22 17:59:25 +02001626 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001627 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001629 err_code |= ERR_ALERT | ERR_FATAL;
1630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001632
1633 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001634
1635 /* NOTE: the following line might create several listeners if there
1636 * are comma-separated IPs or port ranges. So all further processing
1637 * will have to be applied to all listeners created after last_listen.
1638 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001639 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001640 err_code |= ERR_ALERT | ERR_FATAL;
1641 goto out;
1642 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001643
Willy Tarreau90a570f2009-10-04 20:54:54 +02001644 new_listen = curproxy->listen;
1645 while (new_listen != last_listen) {
1646 new_listen->conf.file = file;
1647 new_listen->conf.line = linenum;
1648 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001649 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001650 }
1651
Emeric Bruned760922010-10-22 17:59:25 +02001652 /* Set default global rights and owner for unix bind */
1653 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1654 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1655 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001656 cur_arg = 2;
1657 while (*(args[cur_arg])) {
1658 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1659#ifdef SO_BINDTODEVICE
1660 struct listener *l;
1661
Emeric Bruned760922010-10-22 17:59:25 +02001662 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1663 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1664 file, linenum, args[0], args[cur_arg]);
1665 err_code |= ERR_ALERT | ERR_FATAL;
1666 goto out;
1667 }
1668
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001669 if (!*args[cur_arg + 1]) {
1670 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1671 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001672 err_code |= ERR_ALERT | ERR_FATAL;
1673 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001674 }
1675
1676 for (l = curproxy->listen; l != last_listen; l = l->next)
1677 l->interface = strdup(args[cur_arg + 1]);
1678
1679 global.last_checks |= LSTCHK_NETADM;
1680
1681 cur_arg += 2;
1682 continue;
1683#else
1684 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1685 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001686 err_code |= ERR_ALERT | ERR_FATAL;
1687 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001688#endif
1689 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001690 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1691#ifdef TCP_MAXSEG
1692 struct listener *l;
1693 int mss;
1694
Emeric Bruned760922010-10-22 17:59:25 +02001695 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1696 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1697 file, linenum, args[0], args[cur_arg]);
1698 err_code |= ERR_ALERT | ERR_FATAL;
1699 goto out;
1700 }
1701
Willy Tarreaube1b9182009-06-14 18:48:19 +02001702 if (!*args[cur_arg + 1]) {
1703 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1704 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001705 err_code |= ERR_ALERT | ERR_FATAL;
1706 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001707 }
1708
Willy Tarreau48a7e722010-12-24 15:26:39 +01001709 mss = atoi(args[cur_arg + 1]);
1710 if (!mss || abs(mss) > 65535) {
1711 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001712 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001713 err_code |= ERR_ALERT | ERR_FATAL;
1714 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001715 }
1716
1717 for (l = curproxy->listen; l != last_listen; l = l->next)
1718 l->maxseg = mss;
1719
1720 cur_arg += 2;
1721 continue;
1722#else
1723 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1724 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001725 err_code |= ERR_ALERT | ERR_FATAL;
1726 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001727#endif
1728 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001729
1730 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1731#ifdef TCP_DEFER_ACCEPT
1732 struct listener *l;
1733
1734 for (l = curproxy->listen; l != last_listen; l = l->next)
1735 l->options |= LI_O_DEF_ACCEPT;
1736
1737 cur_arg ++;
1738 continue;
1739#else
1740 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1741 file, linenum, args[0], args[cur_arg]);
1742 err_code |= ERR_ALERT | ERR_FATAL;
1743 goto out;
1744#endif
1745 }
1746
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001747 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001748#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001749 struct listener *l;
1750
Emeric Bruned760922010-10-22 17:59:25 +02001751 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1752 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1753 file, linenum, args[0], args[cur_arg]);
1754 err_code |= ERR_ALERT | ERR_FATAL;
1755 goto out;
1756 }
1757
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001758 for (l = curproxy->listen; l != last_listen; l = l->next)
1759 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001760
1761 cur_arg ++;
1762 continue;
1763#else
1764 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1765 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001766 err_code |= ERR_ALERT | ERR_FATAL;
1767 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001768#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001769 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001770
Willy Tarreau8a956912010-10-15 14:27:08 +02001771 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1772 struct listener *l;
1773
1774 for (l = curproxy->listen; l != last_listen; l = l->next)
1775 l->options |= LI_O_ACC_PROXY;
1776
1777 cur_arg ++;
1778 continue;
1779 }
1780
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001781 if (!strcmp(args[cur_arg], "name")) {
1782 struct listener *l;
1783
1784 for (l = curproxy->listen; l != last_listen; l = l->next)
1785 l->name = strdup(args[cur_arg + 1]);
1786
1787 cur_arg += 2;
1788 continue;
1789 }
1790
1791 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001792 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001793 struct listener *l;
1794
1795 if (curproxy->listen->next != last_listen) {
1796 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1797 file, linenum, args[cur_arg]);
1798 err_code |= ERR_ALERT | ERR_FATAL;
1799 goto out;
1800 }
1801
1802 if (!*args[cur_arg + 1]) {
1803 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1804 file, linenum, args[cur_arg]);
1805 err_code |= ERR_ALERT | ERR_FATAL;
1806 goto out;
1807 }
1808
1809 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001810 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001811
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001812 if (curproxy->listen->luid <= 0) {
1813 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001814 file, linenum);
1815 err_code |= ERR_ALERT | ERR_FATAL;
1816 goto out;
1817 }
1818
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001819 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1820 if (node) {
1821 l = container_of(node, struct listener, conf.id);
1822 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1823 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
1826 }
1827 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1828
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001829 cur_arg += 2;
1830 continue;
1831 }
1832
Emeric Bruned760922010-10-22 17:59:25 +02001833 if (!strcmp(args[cur_arg], "mode")) {
1834
1835 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1836 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1837 file, linenum, args[0], args[cur_arg]);
1838 err_code |= ERR_ALERT | ERR_FATAL;
1839 goto out;
1840 }
1841
1842 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1843
1844 cur_arg += 2;
1845 continue;
1846 }
1847
1848 if (!strcmp(args[cur_arg], "uid")) {
1849
1850 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1851 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1852 file, linenum, args[0], args[cur_arg]);
1853 err_code |= ERR_ALERT | ERR_FATAL;
1854 goto out;
1855 }
1856
1857 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1858 cur_arg += 2;
1859 continue;
1860 }
1861
1862 if (!strcmp(args[cur_arg], "gid")) {
1863
1864 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1865 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1866 file, linenum, args[0], args[cur_arg]);
1867 err_code |= ERR_ALERT | ERR_FATAL;
1868 goto out;
1869 }
1870
1871 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1872 cur_arg += 2;
1873 continue;
1874 }
1875
1876 if (!strcmp(args[cur_arg], "user")) {
1877 struct passwd *user;
1878
1879 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1880 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1881 file, linenum, args[0], args[cur_arg]);
1882 err_code |= ERR_ALERT | ERR_FATAL;
1883 goto out;
1884 }
1885 user = getpwnam(args[cur_arg + 1]);
1886 if (!user) {
1887 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1888 file, linenum, args[0], args[cur_arg + 1 ]);
1889 err_code |= ERR_ALERT | ERR_FATAL;
1890 goto out;
1891 }
1892
1893 curproxy->listen->perm.ux.uid = user->pw_uid;
1894 cur_arg += 2;
1895 continue;
1896 }
1897
1898 if (!strcmp(args[cur_arg], "group")) {
1899 struct group *group;
1900
1901 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1902 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1903 file, linenum, args[0], args[cur_arg]);
1904 err_code |= ERR_ALERT | ERR_FATAL;
1905 goto out;
1906 }
1907 group = getgrnam(args[cur_arg + 1]);
1908 if (!group) {
1909 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1910 file, linenum, args[0], args[cur_arg + 1 ]);
1911 err_code |= ERR_ALERT | ERR_FATAL;
1912 goto out;
1913 }
1914
1915 curproxy->listen->perm.ux.gid = group->gr_gid;
1916 cur_arg += 2;
1917 continue;
1918 }
1919
Willy Tarreaub48f9582011-09-05 01:17:06 +02001920 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 +01001921 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001922 err_code |= ERR_ALERT | ERR_FATAL;
1923 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001924 }
Willy Tarreau93893792009-07-23 13:19:11 +02001925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 }
1927 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1928 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1929 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1930 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001934 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001936
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 /* flush useless bits */
1938 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001939 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001941 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001942 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001943 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001944
Willy Tarreau1c47f852006-07-09 08:22:27 +02001945 if (!*args[1]) {
1946 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1947 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001948 err_code |= ERR_ALERT | ERR_FATAL;
1949 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001950 }
1951
Willy Tarreaua534fea2008-08-03 12:19:50 +02001952 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001953 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001954 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001955 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001956 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1957
Willy Tarreau93893792009-07-23 13:19:11 +02001958 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001959 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001960 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1961 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1962 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1963 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1964 else {
1965 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001966 err_code |= ERR_ALERT | ERR_FATAL;
1967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001968 }
1969 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001970 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001971 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001972
1973 if (curproxy == &defproxy) {
1974 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1975 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001976 err_code |= ERR_ALERT | ERR_FATAL;
1977 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001978 }
1979
1980 if (!*args[1]) {
1981 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1982 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001983 err_code |= ERR_ALERT | ERR_FATAL;
1984 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001985 }
1986
1987 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001988 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001989
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001990 if (curproxy->uuid <= 0) {
1991 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001992 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001993 err_code |= ERR_ALERT | ERR_FATAL;
1994 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001995 }
1996
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001997 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1998 if (node) {
1999 struct proxy *target = container_of(node, struct proxy, conf.id);
2000 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2001 file, linenum, proxy_type_str(curproxy), curproxy->id,
2002 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2003 err_code |= ERR_ALERT | ERR_FATAL;
2004 goto out;
2005 }
2006 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002007 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002008 else if (!strcmp(args[0], "description")) {
2009 int i, len=0;
2010 char *d;
2011
Cyril Bonté99ed3272010-01-24 23:29:44 +01002012 if (curproxy == &defproxy) {
2013 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2014 file, linenum, args[0]);
2015 err_code |= ERR_ALERT | ERR_FATAL;
2016 goto out;
2017 }
2018
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002019 if (!*args[1]) {
2020 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2021 file, linenum, args[0]);
2022 return -1;
2023 }
2024
2025 for(i=1; *args[i]; i++)
2026 len += strlen(args[i])+1;
2027
2028 d = (char *)calloc(1, len);
2029 curproxy->desc = d;
2030
2031 d += sprintf(d, "%s", args[1]);
2032 for(i=2; *args[i]; i++)
2033 d += sprintf(d, " %s", args[i]);
2034
2035 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002036 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2037 curproxy->state = PR_STSTOPPED;
2038 }
2039 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2040 curproxy->state = PR_STNEW;
2041 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002042 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2043 int cur_arg = 1;
2044 unsigned int set = 0;
2045
2046 while (*args[cur_arg]) {
2047 int u;
2048 if (strcmp(args[cur_arg], "all") == 0) {
2049 set = 0;
2050 break;
2051 }
2052 else if (strcmp(args[cur_arg], "odd") == 0) {
2053 set |= 0x55555555;
2054 }
2055 else if (strcmp(args[cur_arg], "even") == 0) {
2056 set |= 0xAAAAAAAA;
2057 }
2058 else {
2059 u = str2uic(args[cur_arg]);
2060 if (u < 1 || u > 32) {
2061 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2062 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002063 err_code |= ERR_ALERT | ERR_FATAL;
2064 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002065 }
2066 if (u > global.nbproc) {
2067 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2068 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002069 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002070 }
2071 set |= 1 << (u - 1);
2072 }
2073 cur_arg++;
2074 }
2075 curproxy->bind_proc = set;
2076 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002077 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002078 char *errmsg = NULL;
2079
Willy Tarreaub099aca2008-10-12 17:26:37 +02002080 if (curproxy == &defproxy) {
2081 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002082 err_code |= ERR_ALERT | ERR_FATAL;
2083 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002084 }
2085
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002086 err = invalid_char(args[1]);
2087 if (err) {
2088 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2089 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002090 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002091 }
2092
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002093 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2094 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2095 file, linenum, args[1], errmsg);
2096 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002097 err_code |= ERR_ALERT | ERR_FATAL;
2098 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002099 }
2100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002101 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2102 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103
Willy Tarreau977b8e42006-12-29 14:19:17 +01002104 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002105 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002106
Willy Tarreaubaaee002006-06-26 02:48:02 +02002107 if (*(args[1]) == 0) {
2108 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2109 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002110 err_code |= ERR_ALERT | ERR_FATAL;
2111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002112 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002113
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002114 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002115 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002116 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002117 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002118 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002119 curproxy->cookie_name = strdup(args[1]);
2120 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002121
Willy Tarreaubaaee002006-06-26 02:48:02 +02002122 cur_arg = 2;
2123 while (*(args[cur_arg])) {
2124 if (!strcmp(args[cur_arg], "rewrite")) {
2125 curproxy->options |= PR_O_COOK_RW;
2126 }
2127 else if (!strcmp(args[cur_arg], "indirect")) {
2128 curproxy->options |= PR_O_COOK_IND;
2129 }
2130 else if (!strcmp(args[cur_arg], "insert")) {
2131 curproxy->options |= PR_O_COOK_INS;
2132 }
2133 else if (!strcmp(args[cur_arg], "nocache")) {
2134 curproxy->options |= PR_O_COOK_NOC;
2135 }
2136 else if (!strcmp(args[cur_arg], "postonly")) {
2137 curproxy->options |= PR_O_COOK_POST;
2138 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002139 else if (!strcmp(args[cur_arg], "preserve")) {
2140 curproxy->options2 |= PR_O2_COOK_PSV;
2141 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002142 else if (!strcmp(args[cur_arg], "prefix")) {
2143 curproxy->options |= PR_O_COOK_PFX;
2144 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002145 else if (!strcmp(args[cur_arg], "domain")) {
2146 if (!*args[cur_arg + 1]) {
2147 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2148 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002149 err_code |= ERR_ALERT | ERR_FATAL;
2150 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002151 }
2152
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002153 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002154 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002155 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2156 " dots nor does not start with a dot."
2157 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002158 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002159 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002160 }
2161
2162 err = invalid_domainchar(args[cur_arg + 1]);
2163 if (err) {
2164 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2165 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002168 }
2169
Willy Tarreau68a897b2009-12-03 23:28:34 +01002170 if (!curproxy->cookie_domain) {
2171 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2172 } else {
2173 /* one domain was already specified, add another one by
2174 * building the string which will be returned along with
2175 * the cookie.
2176 */
2177 char *new_ptr;
2178 int new_len = strlen(curproxy->cookie_domain) +
2179 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2180 new_ptr = malloc(new_len);
2181 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2182 free(curproxy->cookie_domain);
2183 curproxy->cookie_domain = new_ptr;
2184 }
Willy Tarreau31936852010-10-06 16:59:56 +02002185 cur_arg++;
2186 }
2187 else if (!strcmp(args[cur_arg], "maxidle")) {
2188 unsigned int maxidle;
2189 const char *res;
2190
2191 if (!*args[cur_arg + 1]) {
2192 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2193 file, linenum, args[cur_arg]);
2194 err_code |= ERR_ALERT | ERR_FATAL;
2195 goto out;
2196 }
2197
2198 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2199 if (res) {
2200 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2201 file, linenum, *res, args[cur_arg]);
2202 err_code |= ERR_ALERT | ERR_FATAL;
2203 goto out;
2204 }
2205 curproxy->cookie_maxidle = maxidle;
2206 cur_arg++;
2207 }
2208 else if (!strcmp(args[cur_arg], "maxlife")) {
2209 unsigned int maxlife;
2210 const char *res;
2211
2212 if (!*args[cur_arg + 1]) {
2213 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2214 file, linenum, args[cur_arg]);
2215 err_code |= ERR_ALERT | ERR_FATAL;
2216 goto out;
2217 }
2218
2219 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2220 if (res) {
2221 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2222 file, linenum, *res, args[cur_arg]);
2223 err_code |= ERR_ALERT | ERR_FATAL;
2224 goto out;
2225 }
2226 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002227 cur_arg++;
2228 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002229 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002230 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 +02002231 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002232 err_code |= ERR_ALERT | ERR_FATAL;
2233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002234 }
2235 cur_arg++;
2236 }
2237 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2238 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2239 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002240 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241 }
2242
2243 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2244 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2245 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002246 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002248
2249 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2250 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2251 file, linenum);
2252 err_code |= ERR_ALERT | ERR_FATAL;
2253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002255 else if (!strcmp(args[0], "persist")) { /* persist */
2256 if (*(args[1]) == 0) {
2257 Alert("parsing [%s:%d] : missing persist method.\n",
2258 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002261 }
2262
2263 if (!strncmp(args[1], "rdp-cookie", 10)) {
2264 curproxy->options2 |= PR_O2_RDPC_PRST;
2265
Emeric Brunb982a3d2010-01-04 15:45:53 +01002266 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002267 const char *beg, *end;
2268
2269 beg = args[1] + 11;
2270 end = strchr(beg, ')');
2271
2272 if (!end || end == beg) {
2273 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2274 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002275 err_code |= ERR_ALERT | ERR_FATAL;
2276 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002277 }
2278
2279 free(curproxy->rdp_cookie_name);
2280 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2281 curproxy->rdp_cookie_len = end-beg;
2282 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002283 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002284 free(curproxy->rdp_cookie_name);
2285 curproxy->rdp_cookie_name = strdup("msts");
2286 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2287 }
2288 else { /* syntax */
2289 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2290 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002293 }
2294 }
2295 else {
2296 Alert("parsing [%s:%d] : unknown persist method.\n",
2297 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002300 }
2301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002302 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002303 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002304
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002305 if (curproxy == &defproxy) {
2306 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2307 err_code |= ERR_ALERT | ERR_FATAL;
2308 goto out;
2309 }
2310
Willy Tarreau977b8e42006-12-29 14:19:17 +01002311 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002312 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002313
Willy Tarreaubaaee002006-06-26 02:48:02 +02002314 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002315 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002316 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002317 err_code |= ERR_ALERT | ERR_FATAL;
2318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 }
2320 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002321 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322 curproxy->appsession_name = strdup(args[1]);
2323 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2324 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002325 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2326 if (err) {
2327 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2328 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002329 err_code |= ERR_ALERT | ERR_FATAL;
2330 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002331 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002332 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002333
Willy Tarreau51041c72007-09-09 21:56:53 +02002334 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2335 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002336 err_code |= ERR_ALERT | ERR_ABORT;
2337 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002338 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002339
2340 cur_arg = 6;
2341 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002342 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2343 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002344 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002345 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002346 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002347 } else if (!strcmp(args[cur_arg], "prefix")) {
2348 curproxy->options2 |= PR_O2_AS_PFX;
2349 } else if (!strcmp(args[cur_arg], "mode")) {
2350 if (!*args[cur_arg + 1]) {
2351 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2352 file, linenum, args[0], args[cur_arg]);
2353 err_code |= ERR_ALERT | ERR_FATAL;
2354 goto out;
2355 }
2356
2357 cur_arg++;
2358 if (!strcmp(args[cur_arg], "query-string")) {
2359 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2360 curproxy->options2 |= PR_O2_AS_M_QS;
2361 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2362 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2363 curproxy->options2 |= PR_O2_AS_M_PP;
2364 } else {
2365 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
2368 }
2369 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002370 cur_arg++;
2371 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 } /* Url App Session */
2373 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002374 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002375 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002376
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002378 if (curproxy == &defproxy) {
2379 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2380 err_code |= ERR_ALERT | ERR_FATAL;
2381 goto out;
2382 }
2383
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 if (*(args[4]) == 0) {
2385 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2386 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002390 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 curproxy->capture_name = strdup(args[2]);
2392 curproxy->capture_namelen = strlen(curproxy->capture_name);
2393 curproxy->capture_len = atol(args[4]);
2394 if (curproxy->capture_len >= CAPTURE_LEN) {
2395 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2396 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002397 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 curproxy->capture_len = CAPTURE_LEN - 1;
2399 }
2400 curproxy->to_log |= LW_COOKIE;
2401 }
2402 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2403 struct cap_hdr *hdr;
2404
2405 if (curproxy == &defproxy) {
2406 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 +02002407 err_code |= ERR_ALERT | ERR_FATAL;
2408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002409 }
2410
2411 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2412 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2413 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002414 err_code |= ERR_ALERT | ERR_FATAL;
2415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002416 }
2417
2418 hdr = calloc(sizeof(struct cap_hdr), 1);
2419 hdr->next = curproxy->req_cap;
2420 hdr->name = strdup(args[3]);
2421 hdr->namelen = strlen(args[3]);
2422 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002423 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 hdr->index = curproxy->nb_req_cap++;
2425 curproxy->req_cap = hdr;
2426 curproxy->to_log |= LW_REQHDR;
2427 }
2428 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2429 struct cap_hdr *hdr;
2430
2431 if (curproxy == &defproxy) {
2432 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 +02002433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 }
2436
2437 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2438 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2439 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
2443 hdr = calloc(sizeof(struct cap_hdr), 1);
2444 hdr->next = curproxy->rsp_cap;
2445 hdr->name = strdup(args[3]);
2446 hdr->namelen = strlen(args[3]);
2447 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002448 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002449 hdr->index = curproxy->nb_rsp_cap++;
2450 curproxy->rsp_cap = hdr;
2451 curproxy->to_log |= LW_RSPHDR;
2452 }
2453 else {
2454 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2455 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458 }
2459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002461 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002462 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002463
Willy Tarreaubaaee002006-06-26 02:48:02 +02002464 if (*(args[1]) == 0) {
2465 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2466 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002469 }
2470 curproxy->conn_retries = atol(args[1]);
2471 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002472 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002473 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002474
2475 if (curproxy == &defproxy) {
2476 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
2480
Willy Tarreauff011f22011-01-06 17:51:27 +01002481 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 +01002482 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2483 file, linenum, args[0]);
2484 err_code |= ERR_WARN;
2485 }
2486
Willy Tarreauff011f22011-01-06 17:51:27 +01002487 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002488
Willy Tarreauff011f22011-01-06 17:51:27 +01002489 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002490 err_code |= ERR_ALERT | ERR_ABORT;
2491 goto out;
2492 }
2493
Willy Tarreauff011f22011-01-06 17:51:27 +01002494 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2495 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002496 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002497 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2498 /* set the header name and length into the proxy structure */
2499 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2500 err_code |= ERR_WARN;
2501
2502 if (!*args[1]) {
2503 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2504 file, linenum, args[0]);
2505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
2507 }
2508
2509 /* set the desired header name */
2510 free(curproxy->server_id_hdr_name);
2511 curproxy->server_id_hdr_name = strdup(args[1]);
2512 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2513 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002514 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002515 char *errmsg = NULL;
2516
Willy Tarreaub099aca2008-10-12 17:26:37 +02002517 if (curproxy == &defproxy) {
2518 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002521 }
2522
Willy Tarreauef6494c2010-01-28 17:12:36 +01002523 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002524 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2525 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002526 err_code |= ERR_ALERT | ERR_FATAL;
2527 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002528 }
2529
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002530 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2531 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2532 file, linenum, errmsg);
2533 free(errmsg);
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 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002537
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002538 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002539 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002540 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002541 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002542 struct redirect_rule *rule;
2543 int cur_arg;
2544 int type = REDIRECT_TYPE_NONE;
2545 int code = 302;
2546 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002547 char *cookie = NULL;
2548 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002549 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002550
Cyril Bonté99ed3272010-01-24 23:29:44 +01002551 if (curproxy == &defproxy) {
2552 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
2555 }
2556
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002557 cur_arg = 1;
2558 while (*(args[cur_arg])) {
2559 if (!strcmp(args[cur_arg], "location")) {
2560 if (!*args[cur_arg + 1]) {
2561 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2562 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002563 err_code |= ERR_ALERT | ERR_FATAL;
2564 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002565 }
2566
2567 type = REDIRECT_TYPE_LOCATION;
2568 cur_arg++;
2569 destination = args[cur_arg];
2570 }
2571 else if (!strcmp(args[cur_arg], "prefix")) {
2572 if (!*args[cur_arg + 1]) {
2573 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2574 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002577 }
2578
2579 type = REDIRECT_TYPE_PREFIX;
2580 cur_arg++;
2581 destination = args[cur_arg];
2582 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002583 else if (!strcmp(args[cur_arg], "set-cookie")) {
2584 if (!*args[cur_arg + 1]) {
2585 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2586 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002589 }
2590
2591 cur_arg++;
2592 cookie = args[cur_arg];
2593 cookie_set = 1;
2594 }
2595 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2596 if (!*args[cur_arg + 1]) {
2597 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2598 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002599 err_code |= ERR_ALERT | ERR_FATAL;
2600 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002601 }
2602
2603 cur_arg++;
2604 cookie = args[cur_arg];
2605 cookie_set = 0;
2606 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002607 else if (!strcmp(args[cur_arg],"code")) {
2608 if (!*args[cur_arg + 1]) {
2609 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2610 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002611 err_code |= ERR_ALERT | ERR_FATAL;
2612 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002613 }
2614 cur_arg++;
2615 code = atol(args[cur_arg]);
2616 if (code < 301 || code > 303) {
2617 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2618 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002619 err_code |= ERR_ALERT | ERR_FATAL;
2620 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002621 }
2622 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002623 else if (!strcmp(args[cur_arg],"drop-query")) {
2624 flags |= REDIRECT_FLAG_DROP_QS;
2625 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002626 else if (!strcmp(args[cur_arg],"append-slash")) {
2627 flags |= REDIRECT_FLAG_APPEND_SLASH;
2628 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002629 else if (strcmp(args[cur_arg], "if") == 0 ||
2630 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002631 char *errmsg = NULL;
2632
2633 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002634 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002635 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2636 file, linenum, args[0], errmsg);
2637 free(errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
2640 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002641 break;
2642 }
2643 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002644 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 +02002645 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002646 err_code |= ERR_ALERT | ERR_FATAL;
2647 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002648 }
2649 cur_arg++;
2650 }
2651
2652 if (type == REDIRECT_TYPE_NONE) {
2653 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2654 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002657 }
2658
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002659 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2660 rule->cond = cond;
2661 rule->rdr_str = strdup(destination);
2662 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002663 if (cookie) {
2664 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002665 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002666 */
2667 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002668 if (cookie_set) {
2669 rule->cookie_str = malloc(rule->cookie_len + 10);
2670 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2671 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2672 rule->cookie_len += 9;
2673 } else {
2674 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002675 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002676 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2677 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002678 }
2679 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002680 rule->type = type;
2681 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002682 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002683 LIST_INIT(&rule->list);
2684 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002685 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2686 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002687 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002688 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002689 struct switching_rule *rule;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002690 char *errmsg = NULL;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002691
Willy Tarreaub099aca2008-10-12 17:26:37 +02002692 if (curproxy == &defproxy) {
2693 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002696 }
2697
Willy Tarreau55ea7572007-06-17 19:56:27 +02002698 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002699 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002700
2701 if (*(args[1]) == 0) {
2702 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002705 }
2706
Willy Tarreauef6494c2010-01-28 17:12:36 +01002707 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002708 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2709 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002712 }
2713
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002714 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2715 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2716 file, linenum, errmsg);
2717 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002718 err_code |= ERR_ALERT | ERR_FATAL;
2719 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002720 }
2721
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002722 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002723
Willy Tarreau55ea7572007-06-17 19:56:27 +02002724 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2725 rule->cond = cond;
2726 rule->be.name = strdup(args[1]);
2727 LIST_INIT(&rule->list);
2728 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2729 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002730 else if (strcmp(args[0], "use-server") == 0) {
2731 struct server_rule *rule;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002732 char *errmsg = NULL;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002733
2734 if (curproxy == &defproxy) {
2735 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
2738 }
2739
2740 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2741 err_code |= ERR_WARN;
2742
2743 if (*(args[1]) == 0) {
2744 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
2747 }
2748
2749 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2750 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2751 file, linenum, args[0]);
2752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
2754 }
2755
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002756 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2757 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2758 file, linenum, errmsg);
2759 free(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 Tarreaub7451bb2012-04-27 12:38:15 +02002776 char *errmsg = NULL;
Willy Tarreau4de91492010-01-22 19:10:05 +01002777
2778 if (curproxy == &defproxy) {
2779 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
2782 }
2783
2784 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2785 err_code |= ERR_WARN;
2786
Willy Tarreauef6494c2010-01-28 17:12:36 +01002787 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002788 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2789 file, linenum, args[0]);
2790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
2792 }
2793
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002794 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2795 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2796 file, linenum, args[0], errmsg);
2797 free(errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002798 err_code |= ERR_ALERT | ERR_FATAL;
2799 goto out;
2800 }
2801
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002802 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002803
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002804 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002805 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002806 if (!strcmp(args[0], "force-persist")) {
2807 rule->type = PERSIST_TYPE_FORCE;
2808 } else {
2809 rule->type = PERSIST_TYPE_IGNORE;
2810 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002811 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002812 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002813 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002814 else if (!strcmp(args[0], "stick-table")) {
2815 int myidx = 1;
2816
Emeric Brun32da3c42010-09-23 18:39:19 +02002817 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002818 curproxy->table.type = (unsigned int)-1;
2819 while (*args[myidx]) {
2820 const char *err;
2821
2822 if (strcmp(args[myidx], "size") == 0) {
2823 myidx++;
2824 if (!*(args[myidx])) {
2825 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2826 file, linenum, args[myidx-1]);
2827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
2829 }
2830 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2831 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2832 file, linenum, *err, args[myidx-1]);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
2835 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002836 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002837 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002838 else if (strcmp(args[myidx], "peers") == 0) {
2839 myidx++;
2840 if (!*(args[myidx])) {
2841 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2842 file, linenum, args[myidx-1]);
2843 err_code |= ERR_ALERT | ERR_FATAL;
2844 goto out;
2845 }
2846 curproxy->table.peers.name = strdup(args[myidx++]);
2847 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002848 else if (strcmp(args[myidx], "expire") == 0) {
2849 myidx++;
2850 if (!*(args[myidx])) {
2851 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2852 file, linenum, args[myidx-1]);
2853 err_code |= ERR_ALERT | ERR_FATAL;
2854 goto out;
2855 }
2856 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2857 if (err) {
2858 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2859 file, linenum, *err, args[myidx-1]);
2860 err_code |= ERR_ALERT | ERR_FATAL;
2861 goto out;
2862 }
2863 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002864 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002865 }
2866 else if (strcmp(args[myidx], "nopurge") == 0) {
2867 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002868 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002869 }
2870 else if (strcmp(args[myidx], "type") == 0) {
2871 myidx++;
2872 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2873 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2874 file, linenum, args[myidx]);
2875 err_code |= ERR_ALERT | ERR_FATAL;
2876 goto out;
2877 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002878 /* myidx already points to next arg */
2879 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002880 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002881 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002882 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002883
2884 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002885 nw = args[myidx];
2886 while (*nw) {
2887 /* the "store" keyword supports a comma-separated list */
2888 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002889 sa = NULL; /* store arg */
2890 while (*nw && *nw != ',') {
2891 if (*nw == '(') {
2892 *nw = 0;
2893 sa = ++nw;
2894 while (*nw != ')') {
2895 if (!*nw) {
2896 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2897 file, linenum, args[0], cw);
2898 err_code |= ERR_ALERT | ERR_FATAL;
2899 goto out;
2900 }
2901 nw++;
2902 }
2903 *nw = '\0';
2904 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002905 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002906 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002907 if (*nw)
2908 *nw++ = '\0';
2909 type = stktable_get_data_type(cw);
2910 if (type < 0) {
2911 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2912 file, linenum, args[0], cw);
2913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
2915 }
Willy Tarreauac782882010-06-20 10:41:54 +02002916
2917 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2918 switch (err) {
2919 case PE_NONE: break;
2920 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002921 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2922 file, linenum, args[0], cw);
2923 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002924 break;
2925
2926 case PE_ARG_MISSING:
2927 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2928 file, linenum, args[0], cw);
2929 err_code |= ERR_ALERT | ERR_FATAL;
2930 goto out;
2931
2932 case PE_ARG_NOT_USED:
2933 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2934 file, linenum, args[0], cw);
2935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
2937
2938 default:
2939 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2940 file, linenum, args[0], cw);
2941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002943 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002944 }
2945 myidx++;
2946 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002947 else {
2948 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2949 file, linenum, args[myidx]);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002952 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002953 }
2954
2955 if (!curproxy->table.size) {
2956 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2957 file, linenum);
2958 err_code |= ERR_ALERT | ERR_FATAL;
2959 goto out;
2960 }
2961
2962 if (curproxy->table.type == (unsigned int)-1) {
2963 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2964 file, linenum);
2965 err_code |= ERR_ALERT | ERR_FATAL;
2966 goto out;
2967 }
2968 }
2969 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002970 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002971 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002972 int myidx = 0;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002973 char *errmsg = NULL;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002974 const char *name = NULL;
2975 int flags;
2976
2977 if (curproxy == &defproxy) {
2978 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
2981 }
2982
2983 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2984 err_code |= ERR_WARN;
2985 goto out;
2986 }
2987
2988 myidx++;
2989 if ((strcmp(args[myidx], "store") == 0) ||
2990 (strcmp(args[myidx], "store-request") == 0)) {
2991 myidx++;
2992 flags = STK_IS_STORE;
2993 }
2994 else if (strcmp(args[myidx], "store-response") == 0) {
2995 myidx++;
2996 flags = STK_IS_STORE | STK_ON_RSP;
2997 }
2998 else if (strcmp(args[myidx], "match") == 0) {
2999 myidx++;
3000 flags = STK_IS_MATCH;
3001 }
3002 else if (strcmp(args[myidx], "on") == 0) {
3003 myidx++;
3004 flags = STK_IS_MATCH | STK_IS_STORE;
3005 }
3006 else {
3007 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
3010 }
3011
3012 if (*(args[myidx]) == 0) {
3013 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
3016 }
3017
Willy Tarreau12785782012-04-27 21:37:17 +02003018 expr = sample_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003019 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003020 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
3023 }
3024
3025 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003026 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003027 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3028 file, linenum, args[0], expr->fetch->kw);
3029 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003030 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003031 goto out;
3032 }
3033 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003034 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003035 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3036 file, linenum, args[0], expr->fetch->kw);
3037 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003038 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003039 goto out;
3040 }
3041 }
3042
3043 if (strcmp(args[myidx], "table") == 0) {
3044 myidx++;
3045 name = args[myidx++];
3046 }
3047
Willy Tarreauef6494c2010-01-28 17:12:36 +01003048 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003049 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3050 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3051 file, linenum, args[0], errmsg);
3052 free(errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003053 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003054 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003055 goto out;
3056 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003057 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003058 else if (*(args[myidx])) {
3059 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3060 file, linenum, args[0], args[myidx]);
3061 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003062 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003063 goto out;
3064 }
Emeric Brun97679e72010-09-23 17:56:44 +02003065 if (flags & STK_ON_RSP)
3066 err_code |= warnif_cond_requires_req(cond, file, linenum);
3067 else
3068 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003069
Emeric Brunb982a3d2010-01-04 15:45:53 +01003070 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3071 rule->cond = cond;
3072 rule->expr = expr;
3073 rule->flags = flags;
3074 rule->table.name = name ? strdup(name) : NULL;
3075 LIST_INIT(&rule->list);
3076 if (flags & STK_ON_RSP)
3077 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3078 else
3079 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3080 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003082 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003084
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3086 curproxy->uri_auth = NULL; /* we must detach from the default config */
3087
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003088 if (!*args[1]) {
3089 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003090 } else if (!strcmp(args[1], "admin")) {
3091 struct stats_admin_rule *rule;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003092 char *errmsg = NULL;
Cyril Bonté474be412010-10-12 00:14:36 +02003093
3094 if (curproxy == &defproxy) {
3095 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
3098 }
3099
3100 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3101 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3102 err_code |= ERR_ALERT | ERR_ABORT;
3103 goto out;
3104 }
3105
3106 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3107 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3108 file, linenum, args[0], args[1]);
3109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
3111 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003112 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3113 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3114 file, linenum, args[0], args[1], errmsg);
3115 free(errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
3118 }
3119
3120 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3121
3122 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3123 rule->cond = cond;
3124 LIST_INIT(&rule->list);
3125 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 } else if (!strcmp(args[1], "uri")) {
3127 if (*(args[2]) == 0) {
3128 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3132 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003133 err_code |= ERR_ALERT | ERR_ABORT;
3134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 }
3136 } else if (!strcmp(args[1], "realm")) {
3137 if (*(args[2]) == 0) {
3138 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3142 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003143 err_code |= ERR_ALERT | ERR_ABORT;
3144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003146 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003147 unsigned interval;
3148
3149 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3150 if (err) {
3151 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3152 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003155 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3156 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003157 err_code |= ERR_ALERT | ERR_ABORT;
3158 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003159 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003160 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003161 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003162
3163 if (curproxy == &defproxy) {
3164 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
3167 }
3168
3169 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3170 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3171 err_code |= ERR_ALERT | ERR_ABORT;
3172 goto out;
3173 }
3174
Willy Tarreauff011f22011-01-06 17:51:27 +01003175 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3176 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003177 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3178 file, linenum, args[0]);
3179 err_code |= ERR_WARN;
3180 }
3181
Willy Tarreauff011f22011-01-06 17:51:27 +01003182 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003183
Willy Tarreauff011f22011-01-06 17:51:27 +01003184 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003185 err_code |= ERR_ALERT | ERR_ABORT;
3186 goto out;
3187 }
3188
Willy Tarreauff011f22011-01-06 17:51:27 +01003189 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3190 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003191
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 } else if (!strcmp(args[1], "auth")) {
3193 if (*(args[2]) == 0) {
3194 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003195 err_code |= ERR_ALERT | ERR_FATAL;
3196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3198 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_ABORT;
3200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 }
3202 } else if (!strcmp(args[1], "scope")) {
3203 if (*(args[2]) == 0) {
3204 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
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 }
3212 } else if (!strcmp(args[1], "enable")) {
3213 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
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;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003218 } else if (!strcmp(args[1], "hide-version")) {
3219 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3220 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003221 err_code |= ERR_ALERT | ERR_ABORT;
3222 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003223 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003224 } else if (!strcmp(args[1], "show-legends")) {
3225 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3226 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3227 err_code |= ERR_ALERT | ERR_ABORT;
3228 goto out;
3229 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003230 } else if (!strcmp(args[1], "show-node")) {
3231
3232 if (*args[2]) {
3233 int i;
3234 char c;
3235
3236 for (i=0; args[2][i]; i++) {
3237 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003238 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3239 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003240 break;
3241 }
3242
3243 if (!i || args[2][i]) {
3244 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3245 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3246 file, linenum, args[0], args[1]);
3247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
3249 }
3250 }
3251
3252 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3253 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3254 err_code |= ERR_ALERT | ERR_ABORT;
3255 goto out;
3256 }
3257 } else if (!strcmp(args[1], "show-desc")) {
3258 char *desc = NULL;
3259
3260 if (*args[2]) {
3261 int i, len=0;
3262 char *d;
3263
3264 for(i=2; *args[i]; i++)
3265 len += strlen(args[i])+1;
3266
3267 desc = d = (char *)calloc(1, len);
3268
3269 d += sprintf(d, "%s", args[2]);
3270 for(i=3; *args[i]; i++)
3271 d += sprintf(d, " %s", args[i]);
3272 }
3273
3274 if (!*args[2] && !global.desc)
3275 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3276 file, linenum, args[1]);
3277 else {
3278 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3279 free(desc);
3280 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3281 err_code |= ERR_ALERT | ERR_ABORT;
3282 goto out;
3283 }
3284 free(desc);
3285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003287stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003288 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 +01003289 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 }
3293 }
3294 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003295 int optnum;
3296
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003297 if (*(args[1]) == '\0') {
3298 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3299 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003300 err_code |= ERR_ALERT | ERR_FATAL;
3301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003303
3304 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3305 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003306 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3307 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3308 file, linenum, cfg_opts[optnum].name);
3309 err_code |= ERR_ALERT | ERR_FATAL;
3310 goto out;
3311 }
Willy Tarreau93893792009-07-23 13:19:11 +02003312 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3313 err_code |= ERR_WARN;
3314 goto out;
3315 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003316
Willy Tarreau3842f002009-06-14 11:39:52 +02003317 curproxy->no_options &= ~cfg_opts[optnum].val;
3318 curproxy->options &= ~cfg_opts[optnum].val;
3319
3320 switch (kwm) {
3321 case KWM_STD:
3322 curproxy->options |= cfg_opts[optnum].val;
3323 break;
3324 case KWM_NO:
3325 curproxy->no_options |= cfg_opts[optnum].val;
3326 break;
3327 case KWM_DEF: /* already cleared */
3328 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003329 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003330
Willy Tarreau93893792009-07-23 13:19:11 +02003331 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003332 }
3333 }
3334
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003335 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3336 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003337 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3338 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3339 file, linenum, cfg_opts2[optnum].name);
3340 err_code |= ERR_ALERT | ERR_FATAL;
3341 goto out;
3342 }
Willy Tarreau93893792009-07-23 13:19:11 +02003343 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3344 err_code |= ERR_WARN;
3345 goto out;
3346 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003347
Willy Tarreau3842f002009-06-14 11:39:52 +02003348 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3349 curproxy->options2 &= ~cfg_opts2[optnum].val;
3350
3351 switch (kwm) {
3352 case KWM_STD:
3353 curproxy->options2 |= cfg_opts2[optnum].val;
3354 break;
3355 case KWM_NO:
3356 curproxy->no_options2 |= cfg_opts2[optnum].val;
3357 break;
3358 case KWM_DEF: /* already cleared */
3359 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003360 }
Willy Tarreau93893792009-07-23 13:19:11 +02003361 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003362 }
3363 }
3364
Willy Tarreau3842f002009-06-14 11:39:52 +02003365 if (kwm != KWM_STD) {
3366 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003367 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003370 }
3371
Emeric Brun3a058f32009-06-30 18:26:00 +02003372 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003373 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003375 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003376 if (*(args[2]) != '\0') {
3377 if (!strcmp(args[2], "clf")) {
3378 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003379 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003380 } else {
3381 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003382 err_code |= ERR_ALERT | ERR_FATAL;
3383 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003384 }
3385 }
William Lallemand1d705562012-03-12 12:46:41 +01003386 parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode);
Emeric Brun3a058f32009-06-30 18:26:00 +02003387 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003388 else if (!strcmp(args[1], "tcplog")) {
3389 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 /* generate a detailed TCP log */
William Lallemandbddd4fd2012-02-27 11:23:10 +01003391 logformat = default_tcp_log_format;
William Lallemand1d705562012-03-12 12:46:41 +01003392 parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode);
William Lallemandbddd4fd2012-02-27 11:23:10 +01003393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 else if (!strcmp(args[1], "tcpka")) {
3395 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003396 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003397 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003398
3399 if (curproxy->cap & PR_CAP_FE)
3400 curproxy->options |= PR_O_TCP_CLI_KA;
3401 if (curproxy->cap & PR_CAP_BE)
3402 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 }
3404 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003405 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_WARN;
3407
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003409 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003410 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003411 curproxy->options2 &= ~PR_O2_CHK_ANY;
3412 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 if (!*args[2]) { /* no argument */
3414 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3415 curproxy->check_len = strlen(DEF_CHECK_REQ);
3416 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003417 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 curproxy->check_req = (char *)malloc(reqlen);
3419 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003420 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003422 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 if (*args[4])
3424 reqlen += strlen(args[4]);
3425 else
3426 reqlen += strlen("HTTP/1.0");
3427
3428 curproxy->check_req = (char *)malloc(reqlen);
3429 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003430 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003432 }
3433 else if (!strcmp(args[1], "ssl-hello-chk")) {
3434 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003435 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003436 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003437
Willy Tarreaua534fea2008-08-03 12:19:50 +02003438 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003439 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003440 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003441 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442 }
Willy Tarreau23677902007-05-08 23:50:35 +02003443 else if (!strcmp(args[1], "smtpchk")) {
3444 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003445 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003446 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003447 curproxy->options2 &= ~PR_O2_CHK_ANY;
3448 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003449
3450 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3451 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3452 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3453 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3454 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3455 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3456 curproxy->check_req = (char *)malloc(reqlen);
3457 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3458 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3459 } else {
3460 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3461 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3462 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3463 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3464 }
3465 }
3466 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003467 else if (!strcmp(args[1], "pgsql-check")) {
3468 /* use PostgreSQL request to check servers' health */
3469 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3470 err_code |= ERR_WARN;
3471
3472 free(curproxy->check_req);
3473 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003474 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003475 curproxy->options2 |= PR_O2_PGSQL_CHK;
3476
3477 if (*(args[2])) {
3478 int cur_arg = 2;
3479
3480 while (*(args[cur_arg])) {
3481 if (strcmp(args[cur_arg], "user") == 0) {
3482 char * packet;
3483 uint32_t packet_len;
3484 uint32_t pv;
3485
3486 /* suboption header - needs additional argument for it */
3487 if (*(args[cur_arg+1]) == 0) {
3488 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3489 file, linenum, args[0], args[1], args[cur_arg]);
3490 err_code |= ERR_ALERT | ERR_FATAL;
3491 goto out;
3492 }
3493
3494 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3495 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3496 pv = htonl(0x30000); /* protocol version 3.0 */
3497
3498 packet = (char*) calloc(1, packet_len);
3499
3500 memcpy(packet + 4, &pv, 4);
3501
3502 /* copy "user" */
3503 memcpy(packet + 8, "user", 4);
3504
3505 /* copy username */
3506 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3507
3508 free(curproxy->check_req);
3509 curproxy->check_req = packet;
3510 curproxy->check_len = packet_len;
3511
3512 packet_len = htonl(packet_len);
3513 memcpy(packet, &packet_len, 4);
3514 cur_arg += 2;
3515 } else {
3516 /* unknown suboption - catchall */
3517 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3518 file, linenum, args[0], args[1]);
3519 err_code |= ERR_ALERT | ERR_FATAL;
3520 goto out;
3521 }
3522 } /* end while loop */
3523 }
3524 }
3525
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003526 else if (!strcmp(args[1], "redis-check")) {
3527 /* use REDIS PING request to check servers' health */
3528 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3529 err_code |= ERR_WARN;
3530
3531 free(curproxy->check_req);
3532 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003533 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003534 curproxy->options2 |= PR_O2_REDIS_CHK;
3535
3536 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3537 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3538 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3539 }
3540
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003541 else if (!strcmp(args[1], "mysql-check")) {
3542 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003543 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3544 err_code |= ERR_WARN;
3545
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003546 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003547 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003548 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003549 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003550
3551 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3552 * const char mysql40_client_auth_pkt[] = {
3553 * "\x0e\x00\x00" // packet length
3554 * "\x01" // packet number
3555 * "\x00\x00" // client capabilities
3556 * "\x00\x00\x01" // max packet
3557 * "haproxy\x00" // username (null terminated string)
3558 * "\x00" // filler (always 0x00)
3559 * "\x01\x00\x00" // packet length
3560 * "\x00" // packet number
3561 * "\x01" // COM_QUIT command
3562 * };
3563 */
3564
3565 if (*(args[2])) {
3566 int cur_arg = 2;
3567
3568 while (*(args[cur_arg])) {
3569 if (strcmp(args[cur_arg], "user") == 0) {
3570 char *mysqluser;
3571 int packetlen, reqlen, userlen;
3572
3573 /* suboption header - needs additional argument for it */
3574 if (*(args[cur_arg+1]) == 0) {
3575 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3576 file, linenum, args[0], args[1], args[cur_arg]);
3577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
3579 }
3580 mysqluser = args[cur_arg + 1];
3581 userlen = strlen(mysqluser);
3582 packetlen = userlen + 7;
3583 reqlen = packetlen + 9;
3584
3585 free(curproxy->check_req);
3586 curproxy->check_req = (char *)calloc(1, reqlen);
3587 curproxy->check_len = reqlen;
3588
3589 snprintf(curproxy->check_req, 4, "%c%c%c",
3590 ((unsigned char) packetlen & 0xff),
3591 ((unsigned char) (packetlen >> 8) & 0xff),
3592 ((unsigned char) (packetlen >> 16) & 0xff));
3593
3594 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003595 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003596 curproxy->check_req[8] = 1;
3597 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3598 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3599 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3600 cur_arg += 2;
3601 } else {
3602 /* unknown suboption - catchall */
3603 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3604 file, linenum, args[0], args[1]);
3605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
3607 }
3608 } /* end while loop */
3609 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003610 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003611 else if (!strcmp(args[1], "ldap-check")) {
3612 /* use LDAP request to check servers' health */
3613 free(curproxy->check_req);
3614 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003615 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003616 curproxy->options2 |= PR_O2_LDAP_CHK;
3617
3618 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3619 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3620 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3621 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003622 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003623 int cur_arg;
3624
3625 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3626 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003627 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003628
Willy Tarreau87cf5142011-08-19 22:57:24 +02003629 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003630
3631 free(curproxy->fwdfor_hdr_name);
3632 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3633 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3634
3635 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3636 cur_arg = 2;
3637 while (*(args[cur_arg])) {
3638 if (!strcmp(args[cur_arg], "except")) {
3639 /* suboption except - needs additional argument for it */
3640 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3641 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3642 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003643 err_code |= ERR_ALERT | ERR_FATAL;
3644 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003645 }
3646 /* flush useless bits */
3647 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003648 cur_arg += 2;
3649 } else if (!strcmp(args[cur_arg], "header")) {
3650 /* suboption header - needs additional argument for it */
3651 if (*(args[cur_arg+1]) == 0) {
3652 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3653 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003656 }
3657 free(curproxy->fwdfor_hdr_name);
3658 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3659 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3660 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003661 } else if (!strcmp(args[cur_arg], "if-none")) {
3662 curproxy->options &= ~PR_O_FF_ALWAYS;
3663 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003664 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003665 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003666 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003667 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003668 err_code |= ERR_ALERT | ERR_FATAL;
3669 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003670 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003671 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003672 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003673 else if (!strcmp(args[1], "originalto")) {
3674 int cur_arg;
3675
3676 /* insert x-original-to field, but not for the IP address listed as an except.
3677 * set default options (ie: bitfield, header name, etc)
3678 */
3679
3680 curproxy->options |= PR_O_ORGTO;
3681
3682 free(curproxy->orgto_hdr_name);
3683 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3684 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3685
Willy Tarreau87cf5142011-08-19 22:57:24 +02003686 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003687 cur_arg = 2;
3688 while (*(args[cur_arg])) {
3689 if (!strcmp(args[cur_arg], "except")) {
3690 /* suboption except - needs additional argument for it */
3691 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3692 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3693 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003694 err_code |= ERR_ALERT | ERR_FATAL;
3695 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003696 }
3697 /* flush useless bits */
3698 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3699 cur_arg += 2;
3700 } else if (!strcmp(args[cur_arg], "header")) {
3701 /* suboption header - needs additional argument for it */
3702 if (*(args[cur_arg+1]) == 0) {
3703 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3704 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003707 }
3708 free(curproxy->orgto_hdr_name);
3709 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3710 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3711 cur_arg += 2;
3712 } else {
3713 /* unknown suboption - catchall */
3714 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3715 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003716 err_code |= ERR_ALERT | ERR_FATAL;
3717 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003718 }
3719 } /* end while loop */
3720 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 else {
3722 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003723 err_code |= ERR_ALERT | ERR_FATAL;
3724 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003725 }
Willy Tarreau93893792009-07-23 13:19:11 +02003726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003727 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003728 else if (!strcmp(args[0], "default_backend")) {
3729 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003730 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003731
3732 if (*(args[1]) == 0) {
3733 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003736 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003737 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003738 curproxy->defbe.name = strdup(args[1]);
3739 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003740 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003741 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003742 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003743
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003744 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3745 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003746 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747 /* enable reconnections to dispatch */
3748 curproxy->options |= PR_O_REDISP;
3749 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003750 else if (!strcmp(args[0], "http-check")) {
3751 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003752 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003753
3754 if (strcmp(args[1], "disable-on-404") == 0) {
3755 /* enable a graceful server shutdown on an HTTP 404 response */
3756 curproxy->options |= PR_O_DISABLE404;
3757 }
Willy Tarreauef781042010-01-27 11:53:01 +01003758 else if (strcmp(args[1], "send-state") == 0) {
3759 /* enable emission of the apparent state of a server in HTTP checks */
3760 curproxy->options2 |= PR_O2_CHK_SNDST;
3761 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003762 else if (strcmp(args[1], "expect") == 0) {
3763 const char *ptr_arg;
3764 int cur_arg;
3765
3766 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3767 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
3770 }
3771
3772 cur_arg = 2;
3773 /* consider exclamation marks, sole or at the beginning of a word */
3774 while (*(ptr_arg = args[cur_arg])) {
3775 while (*ptr_arg == '!') {
3776 curproxy->options2 ^= PR_O2_EXP_INV;
3777 ptr_arg++;
3778 }
3779 if (*ptr_arg)
3780 break;
3781 cur_arg++;
3782 }
3783 /* now ptr_arg points to the beginning of a word past any possible
3784 * exclamation mark, and cur_arg is the argument which holds this word.
3785 */
3786 if (strcmp(ptr_arg, "status") == 0) {
3787 if (!*(args[cur_arg + 1])) {
3788 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3789 file, linenum, args[0], args[1], ptr_arg);
3790 err_code |= ERR_ALERT | ERR_FATAL;
3791 goto out;
3792 }
3793 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003794 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003795 curproxy->expect_str = strdup(args[cur_arg + 1]);
3796 }
3797 else if (strcmp(ptr_arg, "string") == 0) {
3798 if (!*(args[cur_arg + 1])) {
3799 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3800 file, linenum, args[0], args[1], ptr_arg);
3801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
3803 }
3804 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003805 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003806 curproxy->expect_str = strdup(args[cur_arg + 1]);
3807 }
3808 else if (strcmp(ptr_arg, "rstatus") == 0) {
3809 if (!*(args[cur_arg + 1])) {
3810 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3811 file, linenum, args[0], args[1], ptr_arg);
3812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
3814 }
3815 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003816 free(curproxy->expect_str);
3817 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3818 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003819 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3820 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3821 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3822 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3823 err_code |= ERR_ALERT | ERR_FATAL;
3824 goto out;
3825 }
3826 }
3827 else if (strcmp(ptr_arg, "rstring") == 0) {
3828 if (!*(args[cur_arg + 1])) {
3829 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3830 file, linenum, args[0], args[1], ptr_arg);
3831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
3833 }
3834 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003835 free(curproxy->expect_str);
3836 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3837 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003838 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3839 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3840 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3841 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3842 err_code |= ERR_ALERT | ERR_FATAL;
3843 goto out;
3844 }
3845 }
3846 else {
3847 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3848 file, linenum, args[0], args[1], ptr_arg);
3849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
3851 }
3852 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003853 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003854 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 +02003855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003857 }
3858 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003859 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003860 if (curproxy == &defproxy) {
3861 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003864 }
3865
Willy Tarreaub80c2302007-11-30 20:51:32 +01003866 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003867 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003868
3869 if (strcmp(args[1], "fail") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003870 char *errmsg = NULL;
3871
Willy Tarreaub80c2302007-11-30 20:51:32 +01003872 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003873 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003874 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3875 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003876 err_code |= ERR_ALERT | ERR_FATAL;
3877 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003878 }
3879
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003880 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3881 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3882 file, linenum, args[0], args[1], errmsg);
3883 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003884 err_code |= ERR_ALERT | ERR_FATAL;
3885 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003886 }
3887 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3888 }
3889 else {
3890 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003893 }
3894 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003895#ifdef TPROXY
3896 else if (!strcmp(args[0], "transparent")) {
3897 /* enable transparent proxy connections */
3898 curproxy->options |= PR_O_TRANSP;
3899 }
3900#endif
3901 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003902 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003903 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003904
Willy Tarreaubaaee002006-06-26 02:48:02 +02003905 if (*(args[1]) == 0) {
3906 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003909 }
3910 curproxy->maxconn = atol(args[1]);
3911 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003912 else if (!strcmp(args[0], "backlog")) { /* backlog */
3913 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003914 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003915
3916 if (*(args[1]) == 0) {
3917 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003920 }
3921 curproxy->backlog = atol(args[1]);
3922 }
Willy Tarreau86034312006-12-29 00:10:33 +01003923 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003924 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003925 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003926
Willy Tarreau86034312006-12-29 00:10:33 +01003927 if (*(args[1]) == 0) {
3928 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003929 err_code |= ERR_ALERT | ERR_FATAL;
3930 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003931 }
3932 curproxy->fullconn = atol(args[1]);
3933 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003934 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3935 if (*(args[1]) == 0) {
3936 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003937 err_code |= ERR_ALERT | ERR_FATAL;
3938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003939 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003940 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3941 if (err) {
3942 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3943 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_ALERT | ERR_FATAL;
3945 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003946 }
3947 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003948 }
3949 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003950 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003951 if (curproxy == &defproxy) {
3952 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003955 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003956 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003957 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003958
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959 if (strchr(args[1], ':') == NULL) {
3960 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003961 err_code |= ERR_ALERT | ERR_FATAL;
3962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003963 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003964 sk = str2sa(args[1]);
3965 if (!sk) {
3966 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
3969 }
3970 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003971 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003972 }
3973 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003974 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003975 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003976
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003977 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003978 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3979 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003980 err_code |= ERR_ALERT | ERR_FATAL;
3981 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003982 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003983 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003984 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3985 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3986 err_code |= ERR_WARN;
3987
3988 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3989 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3990 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3991 }
3992 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3993 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3994 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3995 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003996 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3997 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3998 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3999 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004000 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004001 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004002 err_code |= ERR_ALERT | ERR_FATAL;
4003 goto out;
4004 }
4005 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004006 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004007 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004008 char *rport, *raddr;
4009 short realport = 0;
4010 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004011
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004012 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004013 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004014 err_code |= ERR_ALERT | ERR_FATAL;
4015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004016 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004017 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004018 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004019
4020 if (!*args[2]) {
4021 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4022 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004023 err_code |= ERR_ALERT | ERR_FATAL;
4024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004025 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004026
4027 err = invalid_char(args[1]);
4028 if (err) {
4029 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4030 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004031 err_code |= ERR_ALERT | ERR_FATAL;
4032 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004033 }
4034
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004035 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004036 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004037
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004038 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4039 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4040 err_code |= ERR_ALERT | ERR_ABORT;
4041 goto out;
4042 }
4043
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004044 /* the servers are linked backwards first */
4045 newsrv->next = curproxy->srv;
4046 curproxy->srv = newsrv;
4047 newsrv->proxy = curproxy;
4048 newsrv->conf.file = file;
4049 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004050
Simon Hormanaf514952011-06-21 14:34:57 +09004051 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004052 LIST_INIT(&newsrv->pendconns);
4053 do_check = 0;
4054 newsrv->state = SRV_RUNNING; /* early server setup */
4055 newsrv->last_change = now.tv_sec;
4056 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004057
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004058 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004059 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004060 * - IP: => port=+0, relative
4061 * - IP:N => port=N, absolute
4062 * - IP:+N => port=+N, relative
4063 * - IP:-N => port=-N, relative
4064 */
4065 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004066 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004067 if (rport) {
4068 *rport++ = 0;
4069 realport = atol(rport);
4070 if (!isdigit((unsigned char)*rport))
4071 newsrv->state |= SRV_MAPPORTS;
4072 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004073 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004074
Willy Tarreaufab5a432011-03-04 15:31:53 +01004075 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004076 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004077 if (!sk) {
4078 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4079 err_code |= ERR_ALERT | ERR_FATAL;
4080 goto out;
4081 }
4082 newsrv->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004083 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004084
4085 newsrv->check_port = curproxy->defsrv.check_port;
4086 newsrv->inter = curproxy->defsrv.inter;
4087 newsrv->fastinter = curproxy->defsrv.fastinter;
4088 newsrv->downinter = curproxy->defsrv.downinter;
4089 newsrv->rise = curproxy->defsrv.rise;
4090 newsrv->fall = curproxy->defsrv.fall;
4091 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4092 newsrv->minconn = curproxy->defsrv.minconn;
4093 newsrv->maxconn = curproxy->defsrv.maxconn;
4094 newsrv->slowstart = curproxy->defsrv.slowstart;
4095 newsrv->onerror = curproxy->defsrv.onerror;
4096 newsrv->consecutive_errors_limit
4097 = curproxy->defsrv.consecutive_errors_limit;
4098 newsrv->uweight = newsrv->iweight
4099 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004100
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004101 newsrv->curfd = -1; /* no health-check in progress */
4102 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004103
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004104 cur_arg = 3;
4105 } else {
4106 newsrv = &curproxy->defsrv;
4107 cur_arg = 1;
4108 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004109
Willy Tarreaubaaee002006-06-26 02:48:02 +02004110 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004111 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004112 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004113
4114 if (!*args[cur_arg + 1]) {
4115 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4116 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004119 }
4120
4121 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004122 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004123
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004124 if (newsrv->puid <= 0) {
4125 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004126 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004129 }
4130
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004131 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4132 if (node) {
4133 struct server *target = container_of(node, struct server, conf.id);
4134 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4135 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4136 err_code |= ERR_ALERT | ERR_FATAL;
4137 goto out;
4138 }
4139 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004140 cur_arg += 2;
4141 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004142 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004143 newsrv->cookie = strdup(args[cur_arg + 1]);
4144 newsrv->cklen = strlen(args[cur_arg + 1]);
4145 cur_arg += 2;
4146 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004147 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004148 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4149 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4150 cur_arg += 2;
4151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004152 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004153 if (!*args[cur_arg + 1]) {
4154 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4155 file, linenum, args[cur_arg]);
4156 err_code |= ERR_ALERT | ERR_FATAL;
4157 goto out;
4158 }
4159
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004161 if (newsrv->rise <= 0) {
4162 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4163 file, linenum, args[cur_arg]);
4164 err_code |= ERR_ALERT | ERR_FATAL;
4165 goto out;
4166 }
4167
Willy Tarreau96839092010-03-29 10:02:24 +02004168 if (newsrv->health)
4169 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004170 cur_arg += 2;
4171 }
4172 else if (!strcmp(args[cur_arg], "fall")) {
4173 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004174
4175 if (!*args[cur_arg + 1]) {
4176 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4177 file, linenum, args[cur_arg]);
4178 err_code |= ERR_ALERT | ERR_FATAL;
4179 goto out;
4180 }
4181
4182 if (newsrv->fall <= 0) {
4183 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4184 file, linenum, args[cur_arg]);
4185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
4187 }
4188
Willy Tarreaubaaee002006-06-26 02:48:02 +02004189 cur_arg += 2;
4190 }
4191 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004192 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4193 if (err) {
4194 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4195 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004198 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004199 if (val <= 0) {
4200 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4201 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004204 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004205 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004206 cur_arg += 2;
4207 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004208 else if (!strcmp(args[cur_arg], "fastinter")) {
4209 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4210 if (err) {
4211 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4212 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004213 err_code |= ERR_ALERT | ERR_FATAL;
4214 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004215 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004216 if (val <= 0) {
4217 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4218 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004219 err_code |= ERR_ALERT | ERR_FATAL;
4220 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004221 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004222 newsrv->fastinter = val;
4223 cur_arg += 2;
4224 }
4225 else if (!strcmp(args[cur_arg], "downinter")) {
4226 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4227 if (err) {
4228 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4229 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004232 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004233 if (val <= 0) {
4234 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4235 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004238 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004239 newsrv->downinter = val;
4240 cur_arg += 2;
4241 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004242 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004243 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004244 if (!sk) {
4245 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4246 err_code |= ERR_ALERT | ERR_FATAL;
4247 goto out;
4248 }
4249 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004250 cur_arg += 2;
4251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004252 else if (!strcmp(args[cur_arg], "port")) {
4253 newsrv->check_port = atol(args[cur_arg + 1]);
4254 cur_arg += 2;
4255 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004256 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004257 newsrv->state |= SRV_BACKUP;
4258 cur_arg ++;
4259 }
Simon Hormanfa461682011-06-25 09:39:49 +09004260 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4261 newsrv->state |= SRV_NON_STICK;
4262 cur_arg ++;
4263 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004264 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4265 newsrv->state |= SRV_SEND_PROXY;
4266 cur_arg ++;
4267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004268 else if (!strcmp(args[cur_arg], "weight")) {
4269 int w;
4270 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004271 if (w < 0 || w > 256) {
4272 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004273 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004274 err_code |= ERR_ALERT | ERR_FATAL;
4275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004276 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004277 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004278 cur_arg += 2;
4279 }
4280 else if (!strcmp(args[cur_arg], "minconn")) {
4281 newsrv->minconn = atol(args[cur_arg + 1]);
4282 cur_arg += 2;
4283 }
4284 else if (!strcmp(args[cur_arg], "maxconn")) {
4285 newsrv->maxconn = atol(args[cur_arg + 1]);
4286 cur_arg += 2;
4287 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004288 else if (!strcmp(args[cur_arg], "maxqueue")) {
4289 newsrv->maxqueue = atol(args[cur_arg + 1]);
4290 cur_arg += 2;
4291 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004292 else if (!strcmp(args[cur_arg], "slowstart")) {
4293 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004294 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004295 if (err) {
4296 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4297 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004298 err_code |= ERR_ALERT | ERR_FATAL;
4299 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004300 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004301 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004302 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4303 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004304 err_code |= ERR_ALERT | ERR_FATAL;
4305 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004306 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004307 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004308 cur_arg += 2;
4309 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004310 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004311
4312 if (!*args[cur_arg + 1]) {
4313 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4314 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004317 }
4318
4319 newsrv->trackit = strdup(args[cur_arg + 1]);
4320
4321 cur_arg += 2;
4322 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004323 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004324 global.maxsock++;
4325 do_check = 1;
4326 cur_arg += 1;
4327 }
Willy Tarreau96839092010-03-29 10:02:24 +02004328 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4329 newsrv->state |= SRV_MAINTAIN;
4330 newsrv->state &= ~SRV_RUNNING;
4331 newsrv->health = 0;
4332 cur_arg += 1;
4333 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004334 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004335 if (!strcmp(args[cur_arg + 1], "none"))
4336 newsrv->observe = HANA_OBS_NONE;
4337 else if (!strcmp(args[cur_arg + 1], "layer4"))
4338 newsrv->observe = HANA_OBS_LAYER4;
4339 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4340 if (curproxy->mode != PR_MODE_HTTP) {
4341 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4342 file, linenum, args[cur_arg + 1]);
4343 err_code |= ERR_ALERT;
4344 }
4345 newsrv->observe = HANA_OBS_LAYER7;
4346 }
4347 else {
4348 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004349 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004350 file, linenum, args[cur_arg], args[cur_arg + 1]);
4351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
4353 }
4354
4355 cur_arg += 2;
4356 }
4357 else if (!strcmp(args[cur_arg], "on-error")) {
4358 if (!strcmp(args[cur_arg + 1], "fastinter"))
4359 newsrv->onerror = HANA_ONERR_FASTINTER;
4360 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4361 newsrv->onerror = HANA_ONERR_FAILCHK;
4362 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4363 newsrv->onerror = HANA_ONERR_SUDDTH;
4364 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4365 newsrv->onerror = HANA_ONERR_MARKDWN;
4366 else {
4367 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004368 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004369 file, linenum, args[cur_arg], args[cur_arg + 1]);
4370 err_code |= ERR_ALERT | ERR_FATAL;
4371 goto out;
4372 }
4373
4374 cur_arg += 2;
4375 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004376 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4377 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4378 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4379 else {
4380 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4381 file, linenum, args[cur_arg], args[cur_arg + 1]);
4382 err_code |= ERR_ALERT | ERR_FATAL;
4383 goto out;
4384 }
4385
4386 cur_arg += 2;
4387 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004388 else if (!strcmp(args[cur_arg], "error-limit")) {
4389 if (!*args[cur_arg + 1]) {
4390 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4391 file, linenum, args[cur_arg]);
4392 err_code |= ERR_ALERT | ERR_FATAL;
4393 goto out;
4394 }
4395
4396 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4397
4398 if (newsrv->consecutive_errors_limit <= 0) {
4399 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4400 file, linenum, args[cur_arg]);
4401 err_code |= ERR_ALERT | ERR_FATAL;
4402 goto out;
4403 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004404 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004405 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004406 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004407 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004408 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004409
Willy Tarreaubaaee002006-06-26 02:48:02 +02004410 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004411#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004412 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004413 file, linenum, "source", "usesrc");
4414#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004415 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004416 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004417#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004418 err_code |= ERR_ALERT | ERR_FATAL;
4419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004420 }
4421 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004422 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4423 if (!sk) {
4424 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
4427 }
4428 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004429
4430 if (port_low != port_high) {
4431 int i;
4432 if (port_low <= 0 || port_low > 65535 ||
4433 port_high <= 0 || port_high > 65535 ||
4434 port_low > port_high) {
4435 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4436 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004437 err_code |= ERR_ALERT | ERR_FATAL;
4438 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004439 }
4440 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4441 for (i = 0; i < newsrv->sport_range->size; i++)
4442 newsrv->sport_range->ports[i] = port_low + i;
4443 }
4444
Willy Tarreaubaaee002006-06-26 02:48:02 +02004445 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004446 while (*(args[cur_arg])) {
4447 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004448#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4449#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004450 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4451 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4452 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004455 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004456#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004457 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004458 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004459 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004460 err_code |= ERR_ALERT | ERR_FATAL;
4461 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004462 }
4463 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004464 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004465 newsrv->state |= SRV_TPROXY_CLI;
4466 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004467 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004468 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004469 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4470 char *name, *end;
4471
4472 name = args[cur_arg+1] + 7;
4473 while (isspace(*name))
4474 name++;
4475
4476 end = name;
4477 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4478 end++;
4479
4480 newsrv->state &= ~SRV_TPROXY_MASK;
4481 newsrv->state |= SRV_TPROXY_DYN;
4482 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4483 newsrv->bind_hdr_len = end - name;
4484 memcpy(newsrv->bind_hdr_name, name, end - name);
4485 newsrv->bind_hdr_name[end-name] = '\0';
4486 newsrv->bind_hdr_occ = -1;
4487
4488 /* now look for an occurrence number */
4489 while (isspace(*end))
4490 end++;
4491 if (*end == ',') {
4492 end++;
4493 name = end;
4494 if (*end == '-')
4495 end++;
4496 while (isdigit(*end))
4497 end++;
4498 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4499 }
4500
4501 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4502 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4503 " occurrences values smaller than %d.\n",
4504 file, linenum, MAX_HDR_HISTORY);
4505 err_code |= ERR_ALERT | ERR_FATAL;
4506 goto out;
4507 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004508 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004509 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004510 if (!sk) {
4511 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4512 err_code |= ERR_ALERT | ERR_FATAL;
4513 goto out;
4514 }
4515 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004516 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004517 }
4518 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004519#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004520 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004521#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004522 cur_arg += 2;
4523 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004524#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004525 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004526 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004527 err_code |= ERR_ALERT | ERR_FATAL;
4528 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004529#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4530 } /* "usesrc" */
4531
4532 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4533#ifdef SO_BINDTODEVICE
4534 if (!*args[cur_arg + 1]) {
4535 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4536 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004537 err_code |= ERR_ALERT | ERR_FATAL;
4538 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004539 }
4540 if (newsrv->iface_name)
4541 free(newsrv->iface_name);
4542
4543 newsrv->iface_name = strdup(args[cur_arg + 1]);
4544 newsrv->iface_len = strlen(newsrv->iface_name);
4545 global.last_checks |= LSTCHK_NETADM;
4546#else
4547 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4548 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004549 err_code |= ERR_ALERT | ERR_FATAL;
4550 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004551#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004552 cur_arg += 2;
4553 continue;
4554 }
4555 /* this keyword in not an option of "source" */
4556 break;
4557 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004558 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004559 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004560 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4561 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004562 err_code |= ERR_ALERT | ERR_FATAL;
4563 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004564 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004565 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004566 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004567 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 +01004568 file, linenum, newsrv->id);
4569 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004570 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 +01004571 file, linenum);
4572
Willy Tarreau93893792009-07-23 13:19:11 +02004573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004575 }
4576 }
4577
4578 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004579 if (newsrv->trackit) {
4580 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4581 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004582 err_code |= ERR_ALERT | ERR_FATAL;
4583 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004584 }
4585
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004586 /* try to get the port from check_addr if check_port not set */
4587 if (!newsrv->check_port)
4588 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004589
Willy Tarreaubaaee002006-06-26 02:48:02 +02004590 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4591 newsrv->check_port = realport; /* by default */
4592 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004593 /* not yet valid, because no port was set on
4594 * the server either. We'll check if we have
4595 * a known port on the first listener.
4596 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004597 struct listener *l = curproxy->listen;
4598 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4599 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004600 }
4601 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004602 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4603 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004607
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004608 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004609 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004610 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4611 err_code |= ERR_ALERT | ERR_ABORT;
4612 goto out;
4613 }
4614
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004615 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004616 newsrv->state |= SRV_CHECKED;
4617 }
4618
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004619 if (!defsrv) {
4620 if (newsrv->state & SRV_BACKUP)
4621 curproxy->srv_bck++;
4622 else
4623 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004624
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004625 newsrv->prev_state = newsrv->state;
4626 }
William Lallemanda73203e2012-03-12 12:48:57 +01004627 }
4628
4629 else if (strcmp(args[0], "unique-id-format") == 0) {
4630 if (!*(args[1])) {
4631 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
4634 }
4635 parse_logformat_string(args[1], curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
William Lallemand723b73a2012-02-08 16:37:49 +01004636 }
William Lallemanda73203e2012-03-12 12:48:57 +01004637
4638 else if (strcmp(args[0], "unique-id-header") == 0) {
4639 if (!*(args[1])) {
4640 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
4643 }
4644 free(curproxy->header_unique_id);
4645 curproxy->header_unique_id = strdup(args[1]);
4646 }
4647
William Lallemand723b73a2012-02-08 16:37:49 +01004648 else if (strcmp(args[0], "log-format") == 0) {
4649 if (!*(args[1])) {
4650 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4651 err_code |= ERR_ALERT | ERR_FATAL;
4652 goto out;
4653 }
William Lallemand1d705562012-03-12 12:46:41 +01004654 parse_logformat_string(args[1], curproxy, &curproxy->logformat, curproxy->mode);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004655 }
William Lallemand723b73a2012-02-08 16:37:49 +01004656
William Lallemand0f99e342011-10-12 17:50:54 +02004657 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4658 /* delete previous herited or defined syslog servers */
4659 struct logsrv *back;
4660
4661 if (*(args[1]) != 0) {
4662 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4663 err_code |= ERR_ALERT | ERR_FATAL;
4664 goto out;
4665 }
4666
William Lallemand723b73a2012-02-08 16:37:49 +01004667 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4668 LIST_DEL(&tmplogsrv->list);
4669 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004670 }
4671 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004672 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004673 struct logsrv *logsrv;
4674
Willy Tarreaubaaee002006-06-26 02:48:02 +02004675 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004676 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004677 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004678 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004679 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004680 LIST_INIT(&node->list);
4681 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4682 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004683 }
4684 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004685
4686 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687
William Lallemand0f99e342011-10-12 17:50:54 +02004688 logsrv->facility = get_log_facility(args[2]);
4689 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004690 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004691 err_code |= ERR_ALERT | ERR_FATAL;
4692 goto out;
4693
Willy Tarreaubaaee002006-06-26 02:48:02 +02004694 }
4695
William Lallemand0f99e342011-10-12 17:50:54 +02004696 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004697 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004698 logsrv->level = get_log_level(args[3]);
4699 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004701 err_code |= ERR_ALERT | ERR_FATAL;
4702 goto out;
4703
Willy Tarreaubaaee002006-06-26 02:48:02 +02004704 }
4705 }
4706
William Lallemand0f99e342011-10-12 17:50:54 +02004707 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004708 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004709 logsrv->minlvl = get_log_level(args[4]);
4710 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004711 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004712 err_code |= ERR_ALERT | ERR_FATAL;
4713 goto out;
4714
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004715 }
4716 }
4717
Robert Tsai81ae1952007-12-05 10:47:29 +01004718 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004719 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004720 if (!sk) {
4721 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004722 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004723 err_code |= ERR_ALERT | ERR_FATAL;
4724 goto out;
4725 }
William Lallemand0f99e342011-10-12 17:50:54 +02004726 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004727 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004728 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004729 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004730 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4731 err_code |= ERR_ALERT | ERR_FATAL;
4732 goto out;
4733 }
William Lallemand0f99e342011-10-12 17:50:54 +02004734 logsrv->addr = *sk;
4735 if (!get_host_port(&logsrv->addr))
4736 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004737 }
William Lallemand0f99e342011-10-12 17:50:54 +02004738
4739 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004740 }
4741 else {
4742 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4743 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004744 err_code |= ERR_ALERT | ERR_FATAL;
4745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004746 }
4747 }
4748 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004749 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004750 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004751
Willy Tarreau977b8e42006-12-29 14:19:17 +01004752 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004753 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004754
Willy Tarreaubaaee002006-06-26 02:48:02 +02004755 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004756 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4757 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004758 err_code |= ERR_ALERT | ERR_FATAL;
4759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004760 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004761
4762 /* we must first clear any optional default setting */
4763 curproxy->options &= ~PR_O_TPXY_MASK;
4764 free(curproxy->iface_name);
4765 curproxy->iface_name = NULL;
4766 curproxy->iface_len = 0;
4767
Willy Tarreaud5191e72010-02-09 20:50:45 +01004768 sk = str2sa(args[1]);
4769 if (!sk) {
4770 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4771 err_code |= ERR_ALERT | ERR_FATAL;
4772 goto out;
4773 }
4774 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004775 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004776
4777 cur_arg = 2;
4778 while (*(args[cur_arg])) {
4779 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004780#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4781#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004782 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4783 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4784 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004785 err_code |= ERR_ALERT | ERR_FATAL;
4786 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004787 }
4788#endif
4789 if (!*args[cur_arg + 1]) {
4790 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4791 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004792 err_code |= ERR_ALERT | ERR_FATAL;
4793 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004794 }
4795
4796 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004797 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004798 curproxy->options |= PR_O_TPXY_CLI;
4799 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004800 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004801 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004802 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4803 char *name, *end;
4804
4805 name = args[cur_arg+1] + 7;
4806 while (isspace(*name))
4807 name++;
4808
4809 end = name;
4810 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4811 end++;
4812
4813 curproxy->options &= ~PR_O_TPXY_MASK;
4814 curproxy->options |= PR_O_TPXY_DYN;
4815 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4816 curproxy->bind_hdr_len = end - name;
4817 memcpy(curproxy->bind_hdr_name, name, end - name);
4818 curproxy->bind_hdr_name[end-name] = '\0';
4819 curproxy->bind_hdr_occ = -1;
4820
4821 /* now look for an occurrence number */
4822 while (isspace(*end))
4823 end++;
4824 if (*end == ',') {
4825 end++;
4826 name = end;
4827 if (*end == '-')
4828 end++;
4829 while (isdigit(*end))
4830 end++;
4831 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4832 }
4833
4834 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4835 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4836 " occurrences values smaller than %d.\n",
4837 file, linenum, MAX_HDR_HISTORY);
4838 err_code |= ERR_ALERT | ERR_FATAL;
4839 goto out;
4840 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004841 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004842 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004843 if (!sk) {
4844 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4845 err_code |= ERR_ALERT | ERR_FATAL;
4846 goto out;
4847 }
4848 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004849 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004850 }
4851 global.last_checks |= LSTCHK_NETADM;
4852#if !defined(CONFIG_HAP_LINUX_TPROXY)
4853 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004854#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004855#else /* no TPROXY support */
4856 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004857 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004858 err_code |= ERR_ALERT | ERR_FATAL;
4859 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004860#endif
4861 cur_arg += 2;
4862 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004863 }
4864
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004865 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4866#ifdef SO_BINDTODEVICE
4867 if (!*args[cur_arg + 1]) {
4868 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4869 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004872 }
4873 if (curproxy->iface_name)
4874 free(curproxy->iface_name);
4875
4876 curproxy->iface_name = strdup(args[cur_arg + 1]);
4877 curproxy->iface_len = strlen(curproxy->iface_name);
4878 global.last_checks |= LSTCHK_NETADM;
4879#else
4880 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4881 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004882 err_code |= ERR_ALERT | ERR_FATAL;
4883 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004884#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004885 cur_arg += 2;
4886 continue;
4887 }
4888 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4889 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004890 err_code |= ERR_ALERT | ERR_FATAL;
4891 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004892 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004893 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004894 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4895 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4896 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004897 err_code |= ERR_ALERT | ERR_FATAL;
4898 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004901 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004902 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4903 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004904 err_code |= ERR_ALERT | ERR_FATAL;
4905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004907
4908 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004909 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004910 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004911 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913 }
4914 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004915 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004916 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004917 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004918 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 }
4921 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004922 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004923 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004924 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004925 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004927 }
4928 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004929 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004930 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004931 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004932 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004934 }
4935 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004936 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004937 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004938 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004939 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004940 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004941 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004942 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004943 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004944 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004945 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004946 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004947 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004948 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004949 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004950 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004951 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004952 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004953 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004954 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004955 }
4956 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004957 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004958 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004959 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004960 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004961 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004962 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004963 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004964 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4966 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004967 err_code |= ERR_ALERT | ERR_FATAL;
4968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004970
4971 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004972 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004973 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004974 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004976 }
4977 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004978 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004979 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004980 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004981 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004982 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004983 }
4984 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004985 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004986 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004987 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004988 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004990 }
4991 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004992 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004993 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004994 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004995 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 }
4998 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004999 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005000 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005001 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005002 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005005 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005006 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005007 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005008 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005009 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005010 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005011 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005012 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005013 struct cond_wordlist *wl;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005014 char *errmsg = NULL;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005015
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 if (curproxy == &defproxy) {
5017 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005018 err_code |= ERR_ALERT | ERR_FATAL;
5019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005021 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005022 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 if (*(args[1]) == 0) {
5025 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005026 err_code |= ERR_ALERT | ERR_FATAL;
5027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005029
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005030 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005031 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5032 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5033 file, linenum, args[0], errmsg);
5034 free(errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005035 err_code |= ERR_ALERT | ERR_FATAL;
5036 goto out;
5037 }
5038 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5039 }
5040 else if (*args[2]) {
5041 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5042 file, linenum, args[0], args[2]);
5043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
5045 }
5046
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005047 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005048 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005049 wl->s = strdup(args[1]);
5050 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005051 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005052 }
5053 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005054 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5056 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005057 err_code |= ERR_ALERT | ERR_FATAL;
5058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005060
Willy Tarreauade5ec42010-01-28 19:33:49 +01005061 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005062 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005063 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005064 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005066 }
5067 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005068 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005069 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005070 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005071 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005073 }
5074 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005075 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005076 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005077 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005078 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005080 }
5081 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005082 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005083 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5084 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005087 }
5088
Willy Tarreauade5ec42010-01-28 19:33:49 +01005089 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005090 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005091 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005092 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005094 }
5095 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005096 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005097 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005098 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005099 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005101 }
5102 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005103 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005104 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005105 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005106 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005108 }
5109 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005110 struct cond_wordlist *wl;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005111 char *errmsg = NULL;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005112
Willy Tarreaubaaee002006-06-26 02:48:02 +02005113 if (curproxy == &defproxy) {
5114 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005117 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005118 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005119 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005120
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121 if (*(args[1]) == 0) {
5122 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005123 err_code |= ERR_ALERT | ERR_FATAL;
5124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005125 }
5126
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005127 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005128 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5129 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5130 file, linenum, args[0], errmsg);
5131 free(errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005132 err_code |= ERR_ALERT | ERR_FATAL;
5133 goto out;
5134 }
5135 err_code |= warnif_cond_requires_req(cond, file, linenum);
5136 }
5137 else if (*args[2]) {
5138 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5139 file, linenum, args[0], args[2]);
5140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
5142 }
5143
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005144 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005145 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005146 wl->s = strdup(args[1]);
5147 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005148 }
5149 else if (!strcmp(args[0], "errorloc") ||
5150 !strcmp(args[0], "errorloc302") ||
5151 !strcmp(args[0], "errorloc303")) { /* error location */
5152 int errnum, errlen;
5153 char *err;
5154
Willy Tarreau977b8e42006-12-29 14:19:17 +01005155 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005156 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005157
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005159 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005160 err_code |= ERR_ALERT | ERR_FATAL;
5161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005162 }
5163
5164 errnum = atol(args[1]);
5165 if (!strcmp(args[0], "errorloc303")) {
5166 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5167 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5168 } else {
5169 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5170 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5171 }
5172
Willy Tarreau0f772532006-12-23 20:51:41 +01005173 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5174 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005175 chunk_destroy(&curproxy->errmsg[rc]);
5176 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005177 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005178 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005179 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005180
5181 if (rc >= HTTP_ERR_SIZE) {
5182 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5183 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 free(err);
5185 }
5186 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005187 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5188 int errnum, errlen, fd;
5189 char *err;
5190 struct stat stat;
5191
5192 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005193 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005194
5195 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005196 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005197 err_code |= ERR_ALERT | ERR_FATAL;
5198 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005199 }
5200
5201 fd = open(args[2], O_RDONLY);
5202 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5203 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5204 file, linenum, args[2], args[1]);
5205 if (fd >= 0)
5206 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005209 }
5210
Willy Tarreau27a674e2009-08-17 07:23:33 +02005211 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005212 errlen = stat.st_size;
5213 } else {
5214 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005215 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005216 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005217 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005218 }
5219
5220 err = malloc(errlen); /* malloc() must succeed during parsing */
5221 errnum = read(fd, err, errlen);
5222 if (errnum != errlen) {
5223 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5224 file, linenum, args[2], args[1]);
5225 close(fd);
5226 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005229 }
5230 close(fd);
5231
5232 errnum = atol(args[1]);
5233 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5234 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005235 chunk_destroy(&curproxy->errmsg[rc]);
5236 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005237 break;
5238 }
5239 }
5240
5241 if (rc >= HTTP_ERR_SIZE) {
5242 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5243 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005244 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005245 free(err);
5246 }
5247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005249 struct cfg_kw_list *kwl;
5250 int index;
5251
5252 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5253 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5254 if (kwl->kw[index].section != CFG_LISTEN)
5255 continue;
5256 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5257 /* prepare error message just in case */
5258 snprintf(trash, sizeof(trash),
5259 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005260 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5261 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005262 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005265 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005266 else if (rc > 0) {
5267 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005268 err_code |= ERR_WARN;
5269 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005270 }
Willy Tarreau93893792009-07-23 13:19:11 +02005271 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005272 }
5273 }
5274 }
5275
Willy Tarreau6daf3432008-01-22 16:44:08 +01005276 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 }
Willy Tarreau93893792009-07-23 13:19:11 +02005280 out:
5281 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282}
5283
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005284int
5285cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5286{
5287
5288 int err_code = 0;
5289 const char *err;
5290
5291 if (!strcmp(args[0], "userlist")) { /* new userlist */
5292 struct userlist *newul;
5293
5294 if (!*args[1]) {
5295 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5296 file, linenum, args[0]);
5297 err_code |= ERR_ALERT | ERR_FATAL;
5298 goto out;
5299 }
5300
5301 err = invalid_char(args[1]);
5302 if (err) {
5303 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5304 file, linenum, *err, args[0], args[1]);
5305 err_code |= ERR_ALERT | ERR_FATAL;
5306 goto out;
5307 }
5308
5309 for (newul = userlist; newul; newul = newul->next)
5310 if (!strcmp(newul->name, args[1])) {
5311 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5312 file, linenum, args[1]);
5313 err_code |= ERR_WARN;
5314 goto out;
5315 }
5316
5317 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5318 if (!newul) {
5319 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5320 err_code |= ERR_ALERT | ERR_ABORT;
5321 goto out;
5322 }
5323
5324 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5325 newul->name = strdup(args[1]);
5326
5327 if (!newul->groupusers | !newul->name) {
5328 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5329 err_code |= ERR_ALERT | ERR_ABORT;
5330 goto out;
5331 }
5332
5333 newul->next = userlist;
5334 userlist = newul;
5335
5336 } else if (!strcmp(args[0], "group")) { /* new group */
5337 int cur_arg, i;
5338 const char *err;
5339
5340 if (!*args[1]) {
5341 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5342 file, linenum, args[0]);
5343 err_code |= ERR_ALERT | ERR_FATAL;
5344 goto out;
5345 }
5346
5347 err = invalid_char(args[1]);
5348 if (err) {
5349 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5350 file, linenum, *err, args[0], args[1]);
5351 err_code |= ERR_ALERT | ERR_FATAL;
5352 goto out;
5353 }
5354
5355 for(i = 0; i < userlist->grpcnt; i++)
5356 if (!strcmp(userlist->groups[i], args[1])) {
5357 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5358 file, linenum, args[1], userlist->name);
5359 err_code |= ERR_ALERT;
5360 goto out;
5361 }
5362
5363 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5364 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5365 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5366 err_code |= ERR_ALERT | ERR_FATAL;
5367 goto out;
5368 }
5369
5370 cur_arg = 2;
5371
5372 while (*args[cur_arg]) {
5373 if (!strcmp(args[cur_arg], "users")) {
5374 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5375 cur_arg += 2;
5376 continue;
5377 } else {
5378 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5379 file, linenum, args[0]);
5380 err_code |= ERR_ALERT | ERR_FATAL;
5381 goto out;
5382 }
5383 }
5384
5385 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5386 } else if (!strcmp(args[0], "user")) { /* new user */
5387 struct auth_users *newuser;
5388 int cur_arg;
5389
5390 if (!*args[1]) {
5391 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5392 file, linenum, args[0]);
5393 err_code |= ERR_ALERT | ERR_FATAL;
5394 goto out;
5395 }
5396
5397 for (newuser = userlist->users; newuser; newuser = newuser->next)
5398 if (!strcmp(newuser->user, args[1])) {
5399 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5400 file, linenum, args[1], userlist->name);
5401 err_code |= ERR_ALERT;
5402 goto out;
5403 }
5404
5405 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5406 if (!newuser) {
5407 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5408 err_code |= ERR_ALERT | ERR_ABORT;
5409 goto out;
5410 }
5411
5412 newuser->user = strdup(args[1]);
5413
5414 newuser->next = userlist->users;
5415 userlist->users = newuser;
5416
5417 cur_arg = 2;
5418
5419 while (*args[cur_arg]) {
5420 if (!strcmp(args[cur_arg], "password")) {
5421#ifndef CONFIG_HAP_CRYPT
5422 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5423 file, linenum);
5424 err_code |= ERR_ALERT;
5425#endif
5426 newuser->pass = strdup(args[cur_arg + 1]);
5427 cur_arg += 2;
5428 continue;
5429 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5430 newuser->pass = strdup(args[cur_arg + 1]);
5431 newuser->flags |= AU_O_INSECURE;
5432 cur_arg += 2;
5433 continue;
5434 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005435 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005436 cur_arg += 2;
5437 continue;
5438 } else {
5439 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5440 file, linenum, args[0]);
5441 err_code |= ERR_ALERT | ERR_FATAL;
5442 goto out;
5443 }
5444 }
5445 } else {
5446 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5447 err_code |= ERR_ALERT | ERR_FATAL;
5448 }
5449
5450out:
5451 return err_code;
5452}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453
5454/*
5455 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005456 * Returns the error code, 0 if OK, or any combination of :
5457 * - ERR_ABORT: must abort ASAP
5458 * - ERR_FATAL: we can continue parsing but not start the service
5459 * - ERR_WARN: a warning has been emitted
5460 * - ERR_ALERT: an alert has been emitted
5461 * Only the two first ones can stop processing, the two others are just
5462 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005463 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005464int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005465{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005466 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005467 FILE *f;
5468 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005469 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005470 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005471
Willy Tarreaubaaee002006-06-26 02:48:02 +02005472 if ((f=fopen(file,"r")) == NULL)
5473 return -1;
5474
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005475 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005476 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005477 char *end;
5478 char *args[MAX_LINE_ARGS + 1];
5479 char *line = thisline;
5480
Willy Tarreaubaaee002006-06-26 02:48:02 +02005481 linenum++;
5482
5483 end = line + strlen(line);
5484
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005485 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5486 /* Check if we reached the limit and the last char is not \n.
5487 * Watch out for the last line without the terminating '\n'!
5488 */
5489 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005490 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005491 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005492 }
5493
Willy Tarreaubaaee002006-06-26 02:48:02 +02005494 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005495 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005496 line++;
5497
5498 arg = 0;
5499 args[arg] = line;
5500
5501 while (*line && arg < MAX_LINE_ARGS) {
5502 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5503 * C equivalent value. Other combinations left unchanged (eg: \1).
5504 */
5505 if (*line == '\\') {
5506 int skip = 0;
5507 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5508 *line = line[1];
5509 skip = 1;
5510 }
5511 else if (line[1] == 'r') {
5512 *line = '\r';
5513 skip = 1;
5514 }
5515 else if (line[1] == 'n') {
5516 *line = '\n';
5517 skip = 1;
5518 }
5519 else if (line[1] == 't') {
5520 *line = '\t';
5521 skip = 1;
5522 }
5523 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005524 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005525 unsigned char hex1, hex2;
5526 hex1 = toupper(line[2]) - '0';
5527 hex2 = toupper(line[3]) - '0';
5528 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5529 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5530 *line = (hex1<<4) + hex2;
5531 skip = 3;
5532 }
5533 else {
5534 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005535 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005536 }
5537 }
5538 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005539 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005540 end -= skip;
5541 }
5542 line++;
5543 }
5544 else if (*line == '#' || *line == '\n' || *line == '\r') {
5545 /* end of string, end of loop */
5546 *line = 0;
5547 break;
5548 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005549 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005550 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005551 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005552 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005553 line++;
5554 args[++arg] = line;
5555 }
5556 else {
5557 line++;
5558 }
5559 }
5560
5561 /* empty line */
5562 if (!**args)
5563 continue;
5564
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005565 if (*line) {
5566 /* we had to stop due to too many args.
5567 * Let's terminate the string, print the offending part then cut the
5568 * last arg.
5569 */
5570 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5571 line++;
5572 *line = '\0';
5573
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005574 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005575 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005576 err_code |= ERR_ALERT | ERR_FATAL;
5577 args[arg] = line;
5578 }
5579
Willy Tarreau540abe42007-05-02 20:50:16 +02005580 /* zero out remaining args and ensure that at least one entry
5581 * is zeroed out.
5582 */
5583 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 args[arg] = line;
5585 }
5586
Willy Tarreau3842f002009-06-14 11:39:52 +02005587 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005588 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005589 char *tmp;
5590
Willy Tarreau3842f002009-06-14 11:39:52 +02005591 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005592 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005593 for (arg=0; *args[arg+1]; arg++)
5594 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005595 *tmp = '\0'; // fix the next arg to \0
5596 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005597 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005598 else if (!strcmp(args[0], "default")) {
5599 kwm = KWM_DEF;
5600 for (arg=0; *args[arg+1]; arg++)
5601 args[arg] = args[arg+1]; // shift args after inversion
5602 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005603
William Lallemand0f99e342011-10-12 17:50:54 +02005604 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5605 strcmp(args[0], "log") != 0) {
5606 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005607 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005608 }
5609
Willy Tarreau977b8e42006-12-29 14:19:17 +01005610 if (!strcmp(args[0], "listen") ||
5611 !strcmp(args[0], "frontend") ||
5612 !strcmp(args[0], "backend") ||
5613 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005614 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005616 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005617 cursection = strdup(args[0]);
5618 }
5619 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005621 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005622 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005623 }
5624 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005625 confsect = CFG_USERLIST;
5626 free(cursection);
5627 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005628 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005629 else if (!strcmp(args[0], "peers")) {
5630 confsect = CFG_PEERS;
5631 free(cursection);
5632 cursection = strdup(args[0]);
5633 }
5634
Willy Tarreaubaaee002006-06-26 02:48:02 +02005635 /* else it's a section keyword */
5636
5637 switch (confsect) {
5638 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005639 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005640 break;
5641 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005642 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005643 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005644 case CFG_USERLIST:
5645 err_code |= cfg_parse_users(file, linenum, args, kwm);
5646 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005647 case CFG_PEERS:
5648 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5649 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005650 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005651 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005652 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005653 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005654
5655 if (err_code & ERR_ABORT)
5656 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005657 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005658 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005659 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005660 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005661 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005662}
5663
Willy Tarreaubb925012009-07-23 13:36:36 +02005664/*
5665 * Returns the error code, 0 if OK, or any combination of :
5666 * - ERR_ABORT: must abort ASAP
5667 * - ERR_FATAL: we can continue parsing but not start the service
5668 * - ERR_WARN: a warning has been emitted
5669 * - ERR_ALERT: an alert has been emitted
5670 * Only the two first ones can stop processing, the two others are just
5671 * indicators.
5672 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005673int check_config_validity()
5674{
5675 int cfgerr = 0;
5676 struct proxy *curproxy = NULL;
5677 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005678 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005679 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005680 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005681
5682 /*
5683 * Now, check for the integrity of all that we have collected.
5684 */
5685
5686 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005687 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005689 /* first, we will invert the proxy list order */
5690 curproxy = NULL;
5691 while (proxy) {
5692 struct proxy *next;
5693
5694 next = proxy->next;
5695 proxy->next = curproxy;
5696 curproxy = proxy;
5697 if (!next)
5698 break;
5699 proxy = next;
5700 }
5701
Willy Tarreaubaaee002006-06-26 02:48:02 +02005702 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005703 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005704 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005705 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005706 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005707 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005708 unsigned int next_id;
5709
5710 if (!curproxy->uuid) {
5711 /* proxy ID not set, use automatic numbering with first
5712 * spare entry starting with next_pxid.
5713 */
5714 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5715 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5716 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005717 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005718 next_pxid++;
5719
Willy Tarreau55ea7572007-06-17 19:56:27 +02005720
Willy Tarreaubaaee002006-06-26 02:48:02 +02005721 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005722 /* ensure we don't keep listeners uselessly bound */
5723 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 curproxy = curproxy->next;
5725 continue;
5726 }
5727
Willy Tarreauff01a212009-03-15 13:46:16 +01005728 switch (curproxy->mode) {
5729 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005730 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005731 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005732 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5733 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005734 cfgerr++;
5735 }
5736
5737 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005738 Warning("config : servers will be ignored for %s '%s'.\n",
5739 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005740 break;
5741
5742 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005743 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005744 break;
5745
5746 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005747 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005748 break;
5749 }
5750
5751 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005752 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5753 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005754 cfgerr++;
5755 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005756
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005757 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005758 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005759 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005760 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5761 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005762 cfgerr++;
5763 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005765 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005766 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5767 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005768 cfgerr++;
5769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005770#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005771 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005772 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5773 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005774 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005775 }
5776 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005777 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005778 /* If no LB algo is set in a backend, and we're not in
5779 * transparent mode, dispatch mode nor proxy mode, we
5780 * want to use balance roundrobin by default.
5781 */
5782 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5783 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005784 }
5785 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005786
Willy Tarreau1620ec32011-08-06 17:05:02 +02005787 if (curproxy->options & PR_O_DISPATCH)
5788 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5789 else if (curproxy->options & PR_O_HTTP_PROXY)
5790 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5791 else if (curproxy->options & PR_O_TRANSP)
5792 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005793
Willy Tarreau1620ec32011-08-06 17:05:02 +02005794 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5795 if (curproxy->options & PR_O_DISABLE404) {
5796 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5797 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5798 err_code |= ERR_WARN;
5799 curproxy->options &= ~PR_O_DISABLE404;
5800 }
5801 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5802 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5803 "send-state", proxy_type_str(curproxy), curproxy->id);
5804 err_code |= ERR_WARN;
5805 curproxy->options &= ~PR_O2_CHK_SNDST;
5806 }
Willy Tarreauef781042010-01-27 11:53:01 +01005807 }
5808
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005809 /* if a default backend was specified, let's find it */
5810 if (curproxy->defbe.name) {
5811 struct proxy *target;
5812
Alex Williams96532db2009-11-01 21:27:13 -05005813 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005814 if (!target) {
5815 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5816 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005817 cfgerr++;
5818 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005819 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5820 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005821 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005822 } else {
5823 free(curproxy->defbe.name);
5824 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005825 /* we force the backend to be present on at least all of
5826 * the frontend's processes.
5827 */
5828 target->bind_proc = curproxy->bind_proc ?
5829 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005830
5831 /* Emit a warning if this proxy also has some servers */
5832 if (curproxy->srv) {
5833 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5834 curproxy->id);
5835 err_code |= ERR_WARN;
5836 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005837 }
5838 }
5839
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005840 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005841 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5842 /* map jump target for ACT_SETBE in req_rep chain */
5843 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005844 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005845 struct proxy *target;
5846
Willy Tarreaua496b602006-12-17 23:15:24 +01005847 if (exp->action != ACT_SETBE)
5848 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005849
Alex Williams96532db2009-11-01 21:27:13 -05005850 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005851 if (!target) {
5852 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5853 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005854 cfgerr++;
5855 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005856 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5857 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005858 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005859 } else {
5860 free((void *)exp->replace);
5861 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005862 /* we force the backend to be present on at least all of
5863 * the frontend's processes.
5864 */
5865 target->bind_proc = curproxy->bind_proc ?
5866 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005867 }
5868 }
5869 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005870
5871 /* find the target proxy for 'use_backend' rules */
5872 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005873 struct proxy *target;
5874
Alex Williams96532db2009-11-01 21:27:13 -05005875 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005876
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005877 if (!target) {
5878 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5879 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005880 cfgerr++;
5881 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005882 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5883 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005884 cfgerr++;
5885 } else {
5886 free((void *)rule->be.name);
5887 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005888 /* we force the backend to be present on at least all of
5889 * the frontend's processes.
5890 */
5891 target->bind_proc = curproxy->bind_proc ?
5892 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005893 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005894 }
5895
5896 /* find the target proxy for 'use_backend' rules */
5897 list_for_each_entry(srule, &curproxy->server_rules, list) {
5898 struct server *target = findserver(curproxy, srule->srv.name);
5899
5900 if (!target) {
5901 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5902 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5903 cfgerr++;
5904 continue;
5905 }
5906 free((void *)srule->srv.name);
5907 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005908 }
5909
Emeric Brunb982a3d2010-01-04 15:45:53 +01005910 /* find the target table for 'stick' rules */
5911 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5912 struct proxy *target;
5913
Emeric Brun1d33b292010-01-04 15:47:17 +01005914 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5915 if (mrule->flags & STK_IS_STORE)
5916 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5917
Emeric Brunb982a3d2010-01-04 15:45:53 +01005918 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005919 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005920 else
5921 target = curproxy;
5922
5923 if (!target) {
5924 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5925 curproxy->id, mrule->table.name);
5926 cfgerr++;
5927 }
5928 else if (target->table.size == 0) {
5929 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5930 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5931 cfgerr++;
5932 }
Willy Tarreau12785782012-04-27 21:37:17 +02005933 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5934 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005935 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5936 cfgerr++;
5937 }
5938 else {
5939 free((void *)mrule->table.name);
5940 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005941 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005942 }
5943 }
5944
5945 /* find the target table for 'store response' rules */
5946 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5947 struct proxy *target;
5948
Emeric Brun1d33b292010-01-04 15:47:17 +01005949 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5950
Emeric Brunb982a3d2010-01-04 15:45:53 +01005951 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005952 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005953 else
5954 target = curproxy;
5955
5956 if (!target) {
5957 Alert("Proxy '%s': unable to find store table '%s'.\n",
5958 curproxy->id, mrule->table.name);
5959 cfgerr++;
5960 }
5961 else if (target->table.size == 0) {
5962 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5963 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5964 cfgerr++;
5965 }
Willy Tarreau12785782012-04-27 21:37:17 +02005966 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5967 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005968 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5969 cfgerr++;
5970 }
5971 else {
5972 free((void *)mrule->table.name);
5973 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005974 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005975 }
5976 }
5977
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005978 /* find the target table for 'tcp-request' layer 4 rules */
5979 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5980 struct proxy *target;
5981
Willy Tarreau56123282010-08-06 19:06:56 +02005982 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005983 continue;
5984
5985 if (trule->act_prm.trk_ctr.table.n)
5986 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5987 else
5988 target = curproxy;
5989
5990 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005991 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5992 curproxy->id, trule->act_prm.trk_ctr.table.n,
5993 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005994 cfgerr++;
5995 }
5996 else if (target->table.size == 0) {
5997 Alert("Proxy '%s': table '%s' used but not configured.\n",
5998 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5999 cfgerr++;
6000 }
6001 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006002 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 +02006003 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6004 cfgerr++;
6005 }
6006 else {
6007 free(trule->act_prm.trk_ctr.table.n);
6008 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006009 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006010 * to pass a list of counters to track and allocate them right here using
6011 * stktable_alloc_data_type().
6012 */
6013 }
6014 }
6015
Willy Tarreaud1f96522010-08-03 19:34:32 +02006016 /* find the target table for 'tcp-request' layer 6 rules */
6017 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6018 struct proxy *target;
6019
Willy Tarreau56123282010-08-06 19:06:56 +02006020 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006021 continue;
6022
6023 if (trule->act_prm.trk_ctr.table.n)
6024 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6025 else
6026 target = curproxy;
6027
6028 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006029 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6030 curproxy->id, trule->act_prm.trk_ctr.table.n,
6031 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006032 cfgerr++;
6033 }
6034 else if (target->table.size == 0) {
6035 Alert("Proxy '%s': table '%s' used but not configured.\n",
6036 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6037 cfgerr++;
6038 }
6039 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006040 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 +02006041 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6042 cfgerr++;
6043 }
6044 else {
6045 free(trule->act_prm.trk_ctr.table.n);
6046 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006047 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006048 * to pass a list of counters to track and allocate them right here using
6049 * stktable_alloc_data_type().
6050 */
6051 }
6052 }
6053
Emeric Brun32da3c42010-09-23 18:39:19 +02006054 if (curproxy->table.peers.name) {
6055 struct peers *curpeers = peers;
6056
6057 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6058 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6059 free((void *)curproxy->table.peers.name);
6060 curproxy->table.peers.p = peers;
6061 break;
6062 }
6063 }
6064
6065 if (!curpeers) {
6066 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6067 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006068 free((void *)curproxy->table.peers.name);
6069 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006070 cfgerr++;
6071 }
6072 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006073 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6074 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006075 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006076 cfgerr++;
6077 }
6078 }
6079
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006080 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006081 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006082 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6083 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6084 "proxy", curproxy->id);
6085 cfgerr++;
6086 goto out_uri_auth_compat;
6087 }
6088
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006089 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006090 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006091 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006092 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006093
Willy Tarreau95fa4692010-02-01 13:05:50 +01006094 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6095 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006096
6097 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006098 uri_auth_compat_req[i++] = "realm";
6099 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6100 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006101
Willy Tarreau95fa4692010-02-01 13:05:50 +01006102 uri_auth_compat_req[i++] = "unless";
6103 uri_auth_compat_req[i++] = "{";
6104 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6105 uri_auth_compat_req[i++] = "}";
6106 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006107
Willy Tarreauff011f22011-01-06 17:51:27 +01006108 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6109 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006110 cfgerr++;
6111 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006112 }
6113
Willy Tarreauff011f22011-01-06 17:51:27 +01006114 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006115
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006116 if (curproxy->uri_auth->auth_realm) {
6117 free(curproxy->uri_auth->auth_realm);
6118 curproxy->uri_auth->auth_realm = NULL;
6119 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006120
6121 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006122 }
6123out_uri_auth_compat:
6124
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006125 cfgerr += acl_find_targets(curproxy);
6126
Willy Tarreau2738a142006-07-08 17:28:09 +02006127 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006128 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006129 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006130 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006131 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006132 " | While not properly invalid, you will certainly encounter various problems\n"
6133 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006134 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006135 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006136 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006137 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006138
Willy Tarreau1fa31262007-12-03 00:36:16 +01006139 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6140 * We must still support older configurations, so let's find out whether those
6141 * parameters have been set or must be copied from contimeouts.
6142 */
6143 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006144 if (!curproxy->timeout.tarpit ||
6145 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006146 /* tarpit timeout not set. We search in the following order:
6147 * default.tarpit, curr.connect, default.connect.
6148 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006149 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006150 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006151 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006152 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006153 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006154 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006155 }
6156 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006157 (!curproxy->timeout.queue ||
6158 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006159 /* queue timeout not set. We search in the following order:
6160 * default.queue, curr.connect, default.connect.
6161 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006162 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006163 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006164 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006165 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006166 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006167 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006168 }
6169 }
6170
Willy Tarreau1620ec32011-08-06 17:05:02 +02006171 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006172 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6173 curproxy->check_req = (char *)malloc(curproxy->check_len);
6174 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006175 }
6176
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006177 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006178 if (curproxy->nb_req_cap) {
6179 if (curproxy->mode == PR_MODE_HTTP) {
6180 curproxy->req_cap_pool = create_pool("ptrcap",
6181 curproxy->nb_req_cap * sizeof(char *),
6182 MEM_F_SHARED);
6183 } else {
6184 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6185 proxy_type_str(curproxy), curproxy->id);
6186 err_code |= ERR_WARN;
6187 curproxy->to_log &= ~LW_REQHDR;
6188 curproxy->nb_req_cap = 0;
6189 }
6190 }
6191
6192 if (curproxy->nb_rsp_cap) {
6193 if (curproxy->mode == PR_MODE_HTTP) {
6194 curproxy->rsp_cap_pool = create_pool("ptrcap",
6195 curproxy->nb_rsp_cap * sizeof(char *),
6196 MEM_F_SHARED);
6197 } else {
6198 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6199 proxy_type_str(curproxy), curproxy->id);
6200 err_code |= ERR_WARN;
6201 curproxy->to_log &= ~LW_REQHDR;
6202 curproxy->nb_rsp_cap = 0;
6203 }
6204 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006205
Willy Tarreaubaaee002006-06-26 02:48:02 +02006206 /* first, we will invert the servers list order */
6207 newsrv = NULL;
6208 while (curproxy->srv) {
6209 struct server *next;
6210
6211 next = curproxy->srv->next;
6212 curproxy->srv->next = newsrv;
6213 newsrv = curproxy->srv;
6214 if (!next)
6215 break;
6216 curproxy->srv = next;
6217 }
6218
Willy Tarreaudd701652010-05-25 23:03:02 +02006219 /* assign automatic UIDs to servers which don't have one yet */
6220 next_id = 1;
6221 newsrv = curproxy->srv;
6222 while (newsrv != NULL) {
6223 if (!newsrv->puid) {
6224 /* server ID not set, use automatic numbering with first
6225 * spare entry starting with next_svid.
6226 */
6227 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6228 newsrv->conf.id.key = newsrv->puid = next_id;
6229 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6230 }
6231 next_id++;
6232 newsrv = newsrv->next;
6233 }
6234
Willy Tarreau20697042007-11-15 23:26:18 +01006235 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006236 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006237
Willy Tarreau62c3be22012-01-20 13:12:32 +01006238 /*
6239 * If this server supports a maxconn parameter, it needs a dedicated
6240 * tasks to fill the emptied slots when a connection leaves.
6241 * Also, resolve deferred tracking dependency if needed.
6242 */
6243 newsrv = curproxy->srv;
6244 while (newsrv != NULL) {
6245 if (newsrv->minconn > newsrv->maxconn) {
6246 /* Only 'minconn' was specified, or it was higher than or equal
6247 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6248 * this will avoid further useless expensive computations.
6249 */
6250 newsrv->maxconn = newsrv->minconn;
6251 } else if (newsrv->maxconn && !newsrv->minconn) {
6252 /* minconn was not specified, so we set it to maxconn */
6253 newsrv->minconn = newsrv->maxconn;
6254 }
6255
6256 if (newsrv->trackit) {
6257 struct proxy *px;
6258 struct server *srv;
6259 char *pname, *sname;
6260
6261 pname = newsrv->trackit;
6262 sname = strrchr(pname, '/');
6263
6264 if (sname)
6265 *sname++ = '\0';
6266 else {
6267 sname = pname;
6268 pname = NULL;
6269 }
6270
6271 if (pname) {
6272 px = findproxy(pname, PR_CAP_BE);
6273 if (!px) {
6274 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6275 proxy_type_str(curproxy), curproxy->id,
6276 newsrv->id, pname);
6277 cfgerr++;
6278 goto next_srv;
6279 }
6280 } else
6281 px = curproxy;
6282
6283 srv = findserver(px, sname);
6284 if (!srv) {
6285 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6286 proxy_type_str(curproxy), curproxy->id,
6287 newsrv->id, sname);
6288 cfgerr++;
6289 goto next_srv;
6290 }
6291
6292 if (!(srv->state & SRV_CHECKED)) {
6293 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6294 "tracking as it does not have checks enabled.\n",
6295 proxy_type_str(curproxy), curproxy->id,
6296 newsrv->id, px->id, srv->id);
6297 cfgerr++;
6298 goto next_srv;
6299 }
6300
6301 if (curproxy != px &&
6302 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6303 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6304 "tracking: disable-on-404 option inconsistency.\n",
6305 proxy_type_str(curproxy), curproxy->id,
6306 newsrv->id, px->id, srv->id);
6307 cfgerr++;
6308 goto next_srv;
6309 }
6310
6311 /* if the other server is forced disabled, we have to do the same here */
6312 if (srv->state & SRV_MAINTAIN) {
6313 newsrv->state |= SRV_MAINTAIN;
6314 newsrv->state &= ~SRV_RUNNING;
6315 newsrv->health = 0;
6316 }
6317
6318 newsrv->track = srv;
6319 newsrv->tracknext = srv->tracknext;
6320 srv->tracknext = newsrv;
6321
6322 free(newsrv->trackit);
6323 newsrv->trackit = NULL;
6324 }
6325 next_srv:
6326 newsrv = newsrv->next;
6327 }
6328
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006329 /* We have to initialize the server lookup mechanism depending
6330 * on what LB algorithm was choosen.
6331 */
6332
6333 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6334 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6335 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006336 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6337 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6338 init_server_map(curproxy);
6339 } else {
6340 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6341 fwrr_init_server_groups(curproxy);
6342 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006343 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006344
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006345 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006346 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6347 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6348 fwlc_init_server_tree(curproxy);
6349 } else {
6350 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6351 fas_init_server_tree(curproxy);
6352 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006353 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006354
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006355 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006356 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6357 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6358 chash_init_server_tree(curproxy);
6359 } else {
6360 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6361 init_server_map(curproxy);
6362 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006363 break;
6364 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006365
6366 if (curproxy->options & PR_O_LOGASAP)
6367 curproxy->to_log &= ~LW_BYTES;
6368
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006369 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006370 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006371 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6372 proxy_type_str(curproxy), curproxy->id);
6373 err_code |= ERR_WARN;
6374 }
6375
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006376 if (curproxy->mode != PR_MODE_HTTP) {
6377 int optnum;
6378
6379 if (curproxy->options & PR_O_COOK_ANY) {
6380 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6381 proxy_type_str(curproxy), curproxy->id);
6382 err_code |= ERR_WARN;
6383 }
6384
6385 if (curproxy->uri_auth) {
6386 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6387 proxy_type_str(curproxy), curproxy->id);
6388 err_code |= ERR_WARN;
6389 curproxy->uri_auth = NULL;
6390 }
6391
Willy Tarreau87cf5142011-08-19 22:57:24 +02006392 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006393 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6394 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6395 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006396 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006397 }
6398
6399 if (curproxy->options & PR_O_ORGTO) {
6400 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6401 "originalto", proxy_type_str(curproxy), curproxy->id);
6402 err_code |= ERR_WARN;
6403 curproxy->options &= ~PR_O_ORGTO;
6404 }
6405
6406 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6407 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6408 (curproxy->cap & cfg_opts[optnum].cap) &&
6409 (curproxy->options & cfg_opts[optnum].val)) {
6410 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6411 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6412 err_code |= ERR_WARN;
6413 curproxy->options &= ~cfg_opts[optnum].val;
6414 }
6415 }
6416
6417 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6418 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6419 (curproxy->cap & cfg_opts2[optnum].cap) &&
6420 (curproxy->options2 & cfg_opts2[optnum].val)) {
6421 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6422 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6423 err_code |= ERR_WARN;
6424 curproxy->options2 &= ~cfg_opts2[optnum].val;
6425 }
6426 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006427
Willy Tarreauefa5f512010-03-30 20:13:29 +02006428#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006429 if (curproxy->bind_hdr_occ) {
6430 curproxy->bind_hdr_occ = 0;
6431 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6432 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6433 err_code |= ERR_WARN;
6434 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006435#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006436 }
6437
Willy Tarreaubaaee002006-06-26 02:48:02 +02006438 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006439 * ensure that we're not cross-dressing a TCP server into HTTP.
6440 */
6441 newsrv = curproxy->srv;
6442 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006443 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006444 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6445 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006446 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006447 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006448
Willy Tarreau0cec3312011-10-31 13:49:26 +01006449 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6450 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6451 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6452 err_code |= ERR_WARN;
6453 }
6454
Willy Tarreauefa5f512010-03-30 20:13:29 +02006455#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006456 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6457 newsrv->bind_hdr_occ = 0;
6458 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6459 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6460 err_code |= ERR_WARN;
6461 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006462#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006463 newsrv = newsrv->next;
6464 }
6465
Willy Tarreauc1a21672009-08-16 22:37:44 +02006466 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006467 curproxy->accept = frontend_accept;
6468
Willy Tarreauc1a21672009-08-16 22:37:44 +02006469 if (curproxy->tcp_req.inspect_delay ||
6470 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006471 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006472
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006473 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006474 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006475 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006476 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006477
6478 /* both TCP and HTTP must check switching rules */
6479 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6480 }
6481
6482 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006483 if (curproxy->tcp_req.inspect_delay ||
6484 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6485 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6486
Emeric Brun97679e72010-09-23 17:56:44 +02006487 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6488 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6489
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006490 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006491 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006492 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006493 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006494
6495 /* If the backend does requires RDP cookie persistence, we have to
6496 * enable the corresponding analyser.
6497 */
6498 if (curproxy->options2 & PR_O2_RDPC_PRST)
6499 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6500 }
6501
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006502 listener = NULL;
6503 while (curproxy->listen) {
6504 struct listener *next;
6505
6506 next = curproxy->listen->next;
6507 curproxy->listen->next = listener;
6508 listener = curproxy->listen;
6509
6510 if (!next)
6511 break;
6512
6513 curproxy->listen = next;
6514 }
6515
Willy Tarreaue6b98942007-10-29 01:09:36 +01006516 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006517 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006518 listener = curproxy->listen;
6519 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006520 if (!listener->luid) {
6521 /* listener ID not set, use automatic numbering with first
6522 * spare entry starting with next_luid.
6523 */
6524 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6525 listener->conf.id.key = listener->luid = next_id;
6526 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006527 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006528 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006529
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006530 /* enable separate counters */
6531 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6532 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6533 if (!listener->name) {
6534 sprintf(trash, "sock-%d", listener->luid);
6535 listener->name = strdup(trash);
6536 }
6537 }
6538
Willy Tarreaue6b98942007-10-29 01:09:36 +01006539 if (curproxy->options & PR_O_TCP_NOLING)
6540 listener->options |= LI_O_NOLINGER;
6541 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006542 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006543 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006544 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006545 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006546 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006547 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006548
Willy Tarreau8a956912010-10-15 14:27:08 +02006549 if (listener->options & LI_O_ACC_PROXY)
6550 listener->analysers |= AN_REQ_DECODE_PROXY;
6551
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006552 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6553 listener->options |= LI_O_TCP_RULES;
6554
Willy Tarreaude3041d2010-05-31 10:56:17 +02006555 if (curproxy->mon_mask.s_addr)
6556 listener->options |= LI_O_CHK_MONNET;
6557
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006558 /* smart accept mode is automatic in HTTP mode */
6559 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6560 (curproxy->mode == PR_MODE_HTTP &&
6561 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6562 listener->options |= LI_O_NOQUICKACK;
6563
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006564 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006565 listener = listener->next;
6566 }
6567
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006568 /* Check multi-process mode compatibility for the current proxy */
6569 if (global.nbproc > 1) {
6570 int nbproc = 0;
6571 if (curproxy->bind_proc) {
6572 int proc;
6573 for (proc = 0; proc < global.nbproc; proc++) {
6574 if (curproxy->bind_proc & (1 << proc)) {
6575 nbproc++;
6576 }
6577 }
6578 } else {
6579 nbproc = global.nbproc;
6580 }
6581 if (curproxy->table.peers.name) {
6582 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6583 curproxy->id);
6584 cfgerr++;
6585 }
6586 if (nbproc > 1) {
6587 if (curproxy->uri_auth) {
6588 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6589 curproxy->id);
6590 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6591 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6592 curproxy->id);
6593 }
6594 }
6595 if (curproxy->appsession_name) {
6596 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6597 curproxy->id);
6598 }
6599 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6600 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6601 curproxy->id);
6602 }
6603 }
6604 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006605
6606 /* create the task associated with the proxy */
6607 curproxy->task = task_new();
6608 if (curproxy->task) {
6609 curproxy->task->context = curproxy;
6610 curproxy->task->process = manage_proxy;
6611 /* no need to queue, it will be done automatically if some
6612 * listener gets limited.
6613 */
6614 curproxy->task->expire = TICK_ETERNITY;
6615 } else {
6616 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6617 curproxy->id);
6618 cfgerr++;
6619 }
6620
Willy Tarreaubaaee002006-06-26 02:48:02 +02006621 curproxy = curproxy->next;
6622 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006623
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006624 /* Check multi-process mode compatibility */
6625 if (global.nbproc > 1) {
6626 if (global.stats_fe) {
6627 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6628 }
6629 }
6630
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006631 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6632 struct auth_users *curuser;
6633 int g;
6634
6635 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6636 unsigned int group_mask = 0;
6637 char *group = NULL;
6638
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006639 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006640 continue;
6641
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006642 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006643
6644 for (g = 0; g < curuserlist->grpcnt; g++)
6645 if (!strcmp(curuserlist->groups[g], group))
6646 break;
6647
6648 if (g == curuserlist->grpcnt) {
6649 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6650 curuserlist->name, group, curuser->user);
6651 err_code |= ERR_ALERT | ERR_FATAL;
6652 goto out;
6653 }
6654
6655 group_mask |= (1 << g);
6656 }
6657
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006658 free(curuser->u.groups);
6659 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006660 }
6661
6662 for (g = 0; g < curuserlist->grpcnt; g++) {
6663 char *user = NULL;
6664
6665 if (!curuserlist->groupusers[g])
6666 continue;
6667
6668 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6669 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6670 if (!strcmp(curuser->user, user))
6671 break;
6672
6673 if (!curuser) {
6674 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6675 curuserlist->name, user, curuserlist->groups[g]);
6676 err_code |= ERR_ALERT | ERR_FATAL;
6677 goto out;
6678 }
6679
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006680 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006681 }
6682
6683 free(curuserlist->groupusers[g]);
6684 }
6685
6686 free(curuserlist->groupusers);
6687
6688#ifdef DEBUG_AUTH
6689 for (g = 0; g < curuserlist->grpcnt; g++) {
6690 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6691
6692 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6693 if (curuser->group_mask & (1 << g))
6694 fprintf(stderr, " %s", curuser->user);
6695 }
6696
6697 fprintf(stderr, "\n");
6698 }
6699#endif
6700
Willy Tarreaufbb78422011-06-05 15:38:35 +02006701 }
6702
6703 /* automatically compute fullconn if not set. We must not do it in the
6704 * loop above because cross-references are not yet fully resolved.
6705 */
6706 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6707 /* If <fullconn> is not set, let's set it to 10% of the sum of
6708 * the possible incoming frontend's maxconns.
6709 */
6710 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6711 struct proxy *fe;
6712 int total = 0;
6713
6714 /* sum up the number of maxconns of frontends which
6715 * reference this backend at least once or which are
6716 * the same one ('listen').
6717 */
6718 for (fe = proxy; fe; fe = fe->next) {
6719 struct switching_rule *rule;
6720 struct hdr_exp *exp;
6721 int found = 0;
6722
6723 if (!(fe->cap & PR_CAP_FE))
6724 continue;
6725
6726 if (fe == curproxy) /* we're on a "listen" instance */
6727 found = 1;
6728
6729 if (fe->defbe.be == curproxy) /* "default_backend" */
6730 found = 1;
6731
6732 /* check if a "use_backend" rule matches */
6733 if (!found) {
6734 list_for_each_entry(rule, &fe->switching_rules, list) {
6735 if (rule->be.backend == curproxy) {
6736 found = 1;
6737 break;
6738 }
6739 }
6740 }
6741
6742 /* check if a "reqsetbe" rule matches */
6743 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6744 if (exp->action == ACT_SETBE &&
6745 (struct proxy *)exp->replace == curproxy) {
6746 found = 1;
6747 break;
6748 }
6749 }
6750
6751 /* now we've checked all possible ways to reference a backend
6752 * from a frontend.
6753 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006754 if (!found)
6755 continue;
6756 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006757 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006758 /* we have the sum of the maxconns in <total>. We only
6759 * keep 10% of that sum to set the default fullconn, with
6760 * a hard minimum of 1 (to avoid a divide by zero).
6761 */
6762 curproxy->fullconn = (total + 9) / 10;
6763 if (!curproxy->fullconn)
6764 curproxy->fullconn = 1;
6765 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006766 }
6767
Willy Tarreau056f5682010-06-06 15:51:11 +02006768 /* initialize stick-tables on backend capable proxies. This must not
6769 * be done earlier because the data size may be discovered while parsing
6770 * other proxies.
6771 */
6772 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006773 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006774
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006775 /*
6776 * Recount currently required checks.
6777 */
6778
6779 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6780 int optnum;
6781
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006782 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6783 if (curproxy->options & cfg_opts[optnum].val)
6784 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006785
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006786 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6787 if (curproxy->options2 & cfg_opts2[optnum].val)
6788 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006789 }
6790
Willy Tarreau122541c2011-09-07 21:24:49 +02006791 if (peers) {
6792 struct peers *curpeers = peers, **last;
6793 struct peer *p, *pb;
6794
6795 /* Remove all peers sections which don't have a valid listener.
6796 * This can happen when a peers section is never referenced and
6797 * does not contain a local peer.
6798 */
6799 last = &peers;
6800 while (*last) {
6801 curpeers = *last;
6802 if (curpeers->peers_fe) {
6803 last = &curpeers->next;
6804 continue;
6805 }
6806
6807 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6808 curpeers->id, localpeer);
6809
6810 p = curpeers->remote;
6811 while (p) {
6812 pb = p->next;
6813 free(p->id);
6814 free(p);
6815 p = pb;
6816 }
6817
6818 /* Destroy and unlink this curpeers section.
6819 * Note: curpeers is backed up into *last.
6820 */
6821 free(curpeers->id);
6822 curpeers = curpeers->next;
6823 free(*last);
6824 *last = curpeers;
6825 }
6826 }
6827
Willy Tarreauac1932d2011-10-24 19:14:41 +02006828 if (!global.tune.max_http_hdr)
6829 global.tune.max_http_hdr = MAX_HTTP_HDR;
6830
Willy Tarreau34eb6712011-10-24 18:15:04 +02006831 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006832 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006833 MEM_F_SHARED);
6834
Willy Tarreaubb925012009-07-23 13:36:36 +02006835 if (cfgerr > 0)
6836 err_code |= ERR_ALERT | ERR_FATAL;
6837 out:
6838 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006839}
6840
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006841/*
6842 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6843 * parsing sessions.
6844 */
6845void cfg_register_keywords(struct cfg_kw_list *kwl)
6846{
6847 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6848}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006849
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006850/*
6851 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6852 */
6853void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6854{
6855 LIST_DEL(&kwl->list);
6856 LIST_INIT(&kwl->list);
6857}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006858
6859/*
6860 * Local variables:
6861 * c-indent-level: 8
6862 * c-basic-offset: 8
6863 * End:
6864 */